@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.cjs
CHANGED
|
@@ -64,14 +64,15 @@ function useTranslation() {
|
|
|
64
64
|
const { translations, language } = locale;
|
|
65
65
|
const t = React.useCallback(
|
|
66
66
|
(key2, params) => {
|
|
67
|
-
|
|
67
|
+
const raw = translations[key2];
|
|
68
|
+
let text = typeof raw === "string" && raw.trim() ? raw : key2;
|
|
68
69
|
if (params) {
|
|
69
70
|
Object.keys(params).forEach((paramKey) => {
|
|
70
71
|
const value = params[paramKey];
|
|
71
72
|
text = text.replace(new RegExp(`{{${paramKey}}}`, "g"), String(value));
|
|
72
73
|
});
|
|
73
74
|
}
|
|
74
|
-
return text;
|
|
75
|
+
return text.trim() ? text : key2;
|
|
75
76
|
},
|
|
76
77
|
[translations]
|
|
77
78
|
);
|
|
@@ -1517,6 +1518,10 @@ var ChatMachine = class {
|
|
|
1517
1518
|
}
|
|
1518
1519
|
/** Sets turns from fetch, preserving pending user-only turns if server hasn't caught up. */
|
|
1519
1520
|
_setTurnsFromFetch(fetchedTurns) {
|
|
1521
|
+
if (!Array.isArray(fetchedTurns)) {
|
|
1522
|
+
console.warn("[ChatMachine] Ignoring malformed turns payload from fetchSession");
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1520
1525
|
const prev = this.state.messaging.turns;
|
|
1521
1526
|
const hasPendingUserOnly = prev.length > 0 && !prev[prev.length - 1].assistantTurn;
|
|
1522
1527
|
if (hasPendingUserOnly && (!fetchedTurns || fetchedTurns.length === 0)) {
|
|
@@ -1906,6 +1911,7 @@ var ChatMachine = class {
|
|
|
1906
1911
|
const curSessionId = this.state.session.currentSessionId;
|
|
1907
1912
|
const curPendingQuestion = this.state.messaging.pendingQuestion;
|
|
1908
1913
|
if (!curSessionId || !curPendingQuestion) return;
|
|
1914
|
+
const previousTurns = this.state.messaging.turns;
|
|
1909
1915
|
this._updateMessaging({ loading: true });
|
|
1910
1916
|
this._updateSession({ error: null, errorRetryable: false });
|
|
1911
1917
|
const previousPendingQuestion = curPendingQuestion;
|
|
@@ -1923,19 +1929,28 @@ var ChatMachine = class {
|
|
|
1923
1929
|
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
1924
1930
|
if (this.disposed) return;
|
|
1925
1931
|
if (fetchResult) {
|
|
1926
|
-
this.
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1932
|
+
this._updateSession({ session: fetchResult.session });
|
|
1933
|
+
this._updateMessaging({ pendingQuestion: fetchResult.pendingQuestion || null });
|
|
1934
|
+
const hasMalformedRefresh = previousTurns.length > 0 && Array.isArray(fetchResult.turns) && fetchResult.turns.length === 0;
|
|
1935
|
+
if (hasMalformedRefresh) {
|
|
1936
|
+
console.warn("[ChatMachine] Preserving previous turns due to empty post-HITL refetch payload", {
|
|
1937
|
+
sessionId: curSessionId,
|
|
1938
|
+
previousTurnCount: previousTurns.length
|
|
1939
|
+
});
|
|
1940
|
+
this._updateSession({
|
|
1941
|
+
error: "Failed to fully refresh session. Showing last known messages.",
|
|
1942
|
+
errorRetryable: true
|
|
1943
|
+
});
|
|
1944
|
+
} else {
|
|
1945
|
+
this._setTurnsFromFetch(fetchResult.turns);
|
|
1946
|
+
}
|
|
1930
1947
|
} else {
|
|
1931
|
-
this.
|
|
1932
|
-
this._updateSession({ error: "Failed to load updated session", errorRetryable: false });
|
|
1948
|
+
this._updateSession({ error: "Failed to load updated session", errorRetryable: true });
|
|
1933
1949
|
}
|
|
1934
1950
|
} catch (fetchErr) {
|
|
1935
1951
|
if (this.disposed) return;
|
|
1936
|
-
this._updateMessaging({ pendingQuestion: previousPendingQuestion });
|
|
1937
1952
|
const normalized = normalizeRPCError(fetchErr, "Failed to load updated session");
|
|
1938
|
-
this._updateSession({ error: normalized.userMessage, errorRetryable:
|
|
1953
|
+
this._updateSession({ error: normalized.userMessage, errorRetryable: true });
|
|
1939
1954
|
}
|
|
1940
1955
|
}
|
|
1941
1956
|
} else {
|
|
@@ -3295,7 +3310,7 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
3295
3310
|
const [currentStep, setCurrentStep] = React.useState(0);
|
|
3296
3311
|
const [answers, setAnswers] = React.useState({});
|
|
3297
3312
|
const [otherTexts, setOtherTexts] = React.useState({});
|
|
3298
|
-
const questions = pendingQuestion.questions;
|
|
3313
|
+
const questions = Array.isArray(pendingQuestion.questions) ? pendingQuestion.questions : [];
|
|
3299
3314
|
const currentQuestion = questions[currentStep];
|
|
3300
3315
|
const isLastStep = currentStep === questions.length - 1;
|
|
3301
3316
|
const isFirstStep = currentStep === 0;
|
|
@@ -3389,9 +3404,31 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
3389
3404
|
e.preventDefault();
|
|
3390
3405
|
handleNext();
|
|
3391
3406
|
};
|
|
3392
|
-
if (!currentQuestion)
|
|
3407
|
+
if (!currentQuestion) {
|
|
3408
|
+
return /* @__PURE__ */ jsxRuntime.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: [
|
|
3409
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-800 dark:text-gray-200", children: t("BiChat.Error.SomethingWentWrong") }),
|
|
3410
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Error.UnexpectedError") }),
|
|
3411
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3412
|
+
"button",
|
|
3413
|
+
{
|
|
3414
|
+
type: "button",
|
|
3415
|
+
onClick: handleRejectPendingQuestion,
|
|
3416
|
+
disabled: loading,
|
|
3417
|
+
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",
|
|
3418
|
+
children: [
|
|
3419
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 14, weight: "bold" }),
|
|
3420
|
+
t("BiChat.InlineQuestion.Dismiss")
|
|
3421
|
+
]
|
|
3422
|
+
}
|
|
3423
|
+
) })
|
|
3424
|
+
] });
|
|
3425
|
+
}
|
|
3393
3426
|
const isMultiSelect = currentQuestion.type === "MULTIPLE_CHOICE";
|
|
3394
|
-
const options = currentQuestion.options || []
|
|
3427
|
+
const options = (currentQuestion.options || []).filter((option) => Boolean(option && typeof option.label === "string")).map((option, index) => ({
|
|
3428
|
+
id: option.id || `${currentQuestion.id}-option-${index}`,
|
|
3429
|
+
label: option.label,
|
|
3430
|
+
value: option.value || option.label
|
|
3431
|
+
}));
|
|
3395
3432
|
const isOtherSelected = currentAnswer?.customText !== void 0;
|
|
3396
3433
|
const canProceed = isCurrentAnswerValid();
|
|
3397
3434
|
return /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
@@ -4305,7 +4342,8 @@ function TurnBubble({
|
|
|
4305
4342
|
userTurn: classNames?.userTurn ?? defaultClassNames3.userTurn,
|
|
4306
4343
|
assistantTurn: classNames?.assistantTurn ?? defaultClassNames3.assistantTurn
|
|
4307
4344
|
};
|
|
4308
|
-
const
|
|
4345
|
+
const userContent = typeof turn.userTurn?.content === "string" ? turn.userTurn.content : "";
|
|
4346
|
+
const isSystemSummaryTurn = userContent.trim() === "" && turn.assistantTurn?.role === "system";
|
|
4309
4347
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.root, "data-turn-id": turn.id, children: [
|
|
4310
4348
|
!isSystemSummaryTurn && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.userTurn, children: renderUserTurn ? renderUserTurn(turn) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4311
4349
|
UserTurnView,
|
|
@@ -6072,6 +6110,8 @@ function WarningBox({ message }) {
|
|
|
6072
6110
|
}
|
|
6073
6111
|
function ArtifactActions({ url }) {
|
|
6074
6112
|
const { t } = useTranslation();
|
|
6113
|
+
const openLabel = t("BiChat.Artifacts.OpenInNewTab");
|
|
6114
|
+
const downloadLabel = t("BiChat.Artifacts.Download");
|
|
6075
6115
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6076
6116
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6077
6117
|
"a",
|
|
@@ -6082,7 +6122,7 @@ function ArtifactActions({ url }) {
|
|
|
6082
6122
|
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",
|
|
6083
6123
|
children: [
|
|
6084
6124
|
/* @__PURE__ */ jsxRuntime.jsx(react.ArrowSquareOut, { className: "h-3.5 w-3.5", weight: "bold" }),
|
|
6085
|
-
|
|
6125
|
+
openLabel
|
|
6086
6126
|
]
|
|
6087
6127
|
}
|
|
6088
6128
|
),
|
|
@@ -6096,7 +6136,7 @@ function ArtifactActions({ url }) {
|
|
|
6096
6136
|
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",
|
|
6097
6137
|
children: [
|
|
6098
6138
|
/* @__PURE__ */ jsxRuntime.jsx(react.DownloadSimple, { className: "h-3.5 w-3.5", weight: "bold" }),
|
|
6099
|
-
|
|
6139
|
+
downloadLabel
|
|
6100
6140
|
]
|
|
6101
6141
|
}
|
|
6102
6142
|
)
|
|
@@ -7416,6 +7456,7 @@ var EditableText = React.forwardRef(
|
|
|
7416
7456
|
setIsEditing(false);
|
|
7417
7457
|
};
|
|
7418
7458
|
const handleKeyDown = (e) => {
|
|
7459
|
+
e.stopPropagation();
|
|
7419
7460
|
if (e.key === "Enter") {
|
|
7420
7461
|
e.preventDefault();
|
|
7421
7462
|
handleSave();
|
|
@@ -7449,6 +7490,7 @@ var EditableText = React.forwardRef(
|
|
|
7449
7490
|
value: editValue,
|
|
7450
7491
|
onChange: (e) => setEditValue(e.target.value),
|
|
7451
7492
|
onKeyDown: handleKeyDown,
|
|
7493
|
+
onKeyUp: (e) => e.stopPropagation(),
|
|
7452
7494
|
onBlur: handleBlur,
|
|
7453
7495
|
maxLength,
|
|
7454
7496
|
placeholder: resolvedPlaceholder,
|
|
@@ -8079,12 +8121,63 @@ function DefaultErrorContent({
|
|
|
8079
8121
|
] })
|
|
8080
8122
|
] });
|
|
8081
8123
|
}
|
|
8124
|
+
function StaticEmergencyErrorContent({
|
|
8125
|
+
error,
|
|
8126
|
+
onReset
|
|
8127
|
+
}) {
|
|
8128
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center justify-center p-8 text-center min-h-[200px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col items-center", children: [
|
|
8129
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mb-5", children: [
|
|
8130
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 rounded-full bg-red-100 scale-150 blur-md" }),
|
|
8131
|
+
/* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(react.WarningCircle, { size: 28, className: "text-red-500", weight: "fill" }) })
|
|
8132
|
+
] }),
|
|
8133
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-1.5", children: "Something went wrong" }),
|
|
8134
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mb-5 max-w-md leading-relaxed", children: error?.message || "An unexpected UI error occurred." }),
|
|
8135
|
+
onReset && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8136
|
+
"button",
|
|
8137
|
+
{
|
|
8138
|
+
type: "button",
|
|
8139
|
+
onClick: onReset,
|
|
8140
|
+
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",
|
|
8141
|
+
children: [
|
|
8142
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { size: 16, weight: "bold" }),
|
|
8143
|
+
"Try again"
|
|
8144
|
+
]
|
|
8145
|
+
}
|
|
8146
|
+
)
|
|
8147
|
+
] }) });
|
|
8148
|
+
}
|
|
8149
|
+
var FallbackGuard = class extends React.Component {
|
|
8150
|
+
constructor(props) {
|
|
8151
|
+
super(props);
|
|
8152
|
+
this.state = { fallbackFailed: false };
|
|
8153
|
+
}
|
|
8154
|
+
static getDerivedStateFromError() {
|
|
8155
|
+
return { fallbackFailed: true };
|
|
8156
|
+
}
|
|
8157
|
+
componentDidCatch(error, errorInfo) {
|
|
8158
|
+
this.props.onFallbackError?.(error, errorInfo);
|
|
8159
|
+
}
|
|
8160
|
+
render() {
|
|
8161
|
+
if (this.state.fallbackFailed) {
|
|
8162
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StaticEmergencyErrorContent, { error: this.props.primaryError, onReset: this.props.onReset });
|
|
8163
|
+
}
|
|
8164
|
+
return this.props.renderFallback();
|
|
8165
|
+
}
|
|
8166
|
+
};
|
|
8082
8167
|
var ErrorBoundary = class extends React.Component {
|
|
8083
8168
|
constructor(props) {
|
|
8084
8169
|
super(props);
|
|
8085
8170
|
this.handleReset = () => {
|
|
8086
8171
|
this.setState({ hasError: false, error: null });
|
|
8087
8172
|
};
|
|
8173
|
+
this.handleFallbackError = (error, errorInfo) => {
|
|
8174
|
+
console.error("React Error Boundary fallback crashed:", {
|
|
8175
|
+
primaryError: this.state.error,
|
|
8176
|
+
fallbackError: error,
|
|
8177
|
+
errorInfo
|
|
8178
|
+
});
|
|
8179
|
+
this.props.onError?.(error, errorInfo);
|
|
8180
|
+
};
|
|
8088
8181
|
this.state = { hasError: false, error: null };
|
|
8089
8182
|
}
|
|
8090
8183
|
static getDerivedStateFromError(error) {
|
|
@@ -8096,13 +8189,24 @@ var ErrorBoundary = class extends React.Component {
|
|
|
8096
8189
|
}
|
|
8097
8190
|
render() {
|
|
8098
8191
|
if (this.state.hasError) {
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8192
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8193
|
+
FallbackGuard,
|
|
8194
|
+
{
|
|
8195
|
+
primaryError: this.state.error,
|
|
8196
|
+
onReset: this.handleReset,
|
|
8197
|
+
onFallbackError: this.handleFallbackError,
|
|
8198
|
+
renderFallback: () => {
|
|
8199
|
+
if (this.props.fallback) {
|
|
8200
|
+
if (typeof this.props.fallback === "function") {
|
|
8201
|
+
return this.props.fallback(this.state.error, this.handleReset);
|
|
8202
|
+
}
|
|
8203
|
+
return this.props.fallback;
|
|
8204
|
+
}
|
|
8205
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DefaultErrorContent, { error: this.state.error, onReset: this.handleReset });
|
|
8206
|
+
}
|
|
8207
|
+
},
|
|
8208
|
+
`${this.state.error?.name ?? "Error"}:${this.state.error?.message ?? ""}`
|
|
8209
|
+
);
|
|
8106
8210
|
}
|
|
8107
8211
|
return this.props.children;
|
|
8108
8212
|
}
|
|
@@ -8495,6 +8599,9 @@ var SessionItem = React.memo(
|
|
|
8495
8599
|
onSelect(session.id);
|
|
8496
8600
|
},
|
|
8497
8601
|
onKeyDown: (e) => {
|
|
8602
|
+
const target = e.target;
|
|
8603
|
+
const isFromEditable = !!target?.closest('input, textarea, [contenteditable="true"]');
|
|
8604
|
+
if (isFromEditable) return;
|
|
8498
8605
|
if (e.key === "Enter" || e.key === " ") {
|
|
8499
8606
|
e.preventDefault();
|
|
8500
8607
|
onSelect(session.id);
|
|
@@ -9253,6 +9360,15 @@ function Sidebar2({
|
|
|
9253
9360
|
React.useEffect(() => {
|
|
9254
9361
|
fetchSessions();
|
|
9255
9362
|
}, [fetchSessions, refreshKey]);
|
|
9363
|
+
React.useEffect(() => {
|
|
9364
|
+
const handleSessionsUpdated = () => {
|
|
9365
|
+
setRefreshKey((k) => k + 1);
|
|
9366
|
+
};
|
|
9367
|
+
window.addEventListener("bichat:sessions-updated", handleSessionsUpdated);
|
|
9368
|
+
return () => {
|
|
9369
|
+
window.removeEventListener("bichat:sessions-updated", handleSessionsUpdated);
|
|
9370
|
+
};
|
|
9371
|
+
}, []);
|
|
9256
9372
|
React.useEffect(() => {
|
|
9257
9373
|
if (!activeSessionId) {
|
|
9258
9374
|
refreshForActiveSessionRef.current = null;
|
|
@@ -9627,13 +9743,14 @@ function Sidebar2({
|
|
|
9627
9743
|
anchor: "top start",
|
|
9628
9744
|
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",
|
|
9629
9745
|
children: [
|
|
9630
|
-
onArchivedView && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9746
|
+
onArchivedView && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9631
9747
|
"button",
|
|
9632
9748
|
{
|
|
9633
9749
|
onClick: (e) => {
|
|
9634
9750
|
e.preventDefault();
|
|
9635
9751
|
e.stopPropagation();
|
|
9636
9752
|
onArchivedView();
|
|
9753
|
+
close();
|
|
9637
9754
|
},
|
|
9638
9755
|
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" : ""}`,
|
|
9639
9756
|
"aria-label": t("BiChat.Sidebar.ArchivedChats"),
|
|
@@ -9643,13 +9760,14 @@ function Sidebar2({
|
|
|
9643
9760
|
]
|
|
9644
9761
|
}
|
|
9645
9762
|
) }),
|
|
9646
|
-
showAllChatsTab && activeTab !== "all-chats" && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9763
|
+
showAllChatsTab && activeTab !== "all-chats" && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9647
9764
|
"button",
|
|
9648
9765
|
{
|
|
9649
9766
|
onClick: (e) => {
|
|
9650
9767
|
e.preventDefault();
|
|
9651
9768
|
e.stopPropagation();
|
|
9652
9769
|
setActiveTab("all-chats");
|
|
9770
|
+
close();
|
|
9653
9771
|
},
|
|
9654
9772
|
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" : ""}`,
|
|
9655
9773
|
"aria-label": t("BiChat.Sidebar.AllChats"),
|
|
@@ -9659,13 +9777,14 @@ function Sidebar2({
|
|
|
9659
9777
|
]
|
|
9660
9778
|
}
|
|
9661
9779
|
) }),
|
|
9662
|
-
showAllChatsTab && activeTab === "all-chats" && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9780
|
+
showAllChatsTab && activeTab === "all-chats" && /* @__PURE__ */ jsxRuntime.jsx(react$1.MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9663
9781
|
"button",
|
|
9664
9782
|
{
|
|
9665
9783
|
onClick: (e) => {
|
|
9666
9784
|
e.preventDefault();
|
|
9667
9785
|
e.stopPropagation();
|
|
9668
9786
|
setActiveTab("my-chats");
|
|
9787
|
+
close();
|
|
9669
9788
|
},
|
|
9670
9789
|
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" : ""}`,
|
|
9671
9790
|
"aria-label": t("BiChat.Sidebar.MyChats"),
|
|
@@ -9780,7 +9899,11 @@ function ArchivedChatList({
|
|
|
9780
9899
|
const confirmRestore = async () => {
|
|
9781
9900
|
if (!sessionToRestore) return;
|
|
9782
9901
|
try {
|
|
9783
|
-
|
|
9902
|
+
const restoredSessionID = sessionToRestore;
|
|
9903
|
+
await dataSource.unarchiveSession(restoredSessionID);
|
|
9904
|
+
window.dispatchEvent(new CustomEvent("bichat:sessions-updated", {
|
|
9905
|
+
detail: { reason: "restored", sessionId: restoredSessionID }
|
|
9906
|
+
}));
|
|
9784
9907
|
setRefreshKey((k) => k + 1);
|
|
9785
9908
|
toast.success(t("BiChat.Archived.ChatRestoredSuccessfully"));
|
|
9786
9909
|
} catch (err) {
|
|
@@ -12042,6 +12165,7 @@ function toSessionArtifact(artifact) {
|
|
|
12042
12165
|
id: artifact.id,
|
|
12043
12166
|
sessionId: artifact.sessionId,
|
|
12044
12167
|
messageId: artifact.messageId,
|
|
12168
|
+
uploadId: artifact.uploadId,
|
|
12045
12169
|
type: artifact.type,
|
|
12046
12170
|
name: artifact.name,
|
|
12047
12171
|
description: artifact.description,
|
|
@@ -12052,21 +12176,272 @@ function toSessionArtifact(artifact) {
|
|
|
12052
12176
|
createdAt: artifact.createdAt
|
|
12053
12177
|
};
|
|
12054
12178
|
}
|
|
12055
|
-
function
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
12179
|
+
function warnMalformedSessionPayload(message, details) {
|
|
12180
|
+
console.warn(`[BiChat] ${message}`, details || {});
|
|
12181
|
+
}
|
|
12182
|
+
function readString(value, fallback = "") {
|
|
12183
|
+
return typeof value === "string" ? value : fallback;
|
|
12184
|
+
}
|
|
12185
|
+
function readNonEmptyString(value) {
|
|
12186
|
+
if (typeof value !== "string") return null;
|
|
12187
|
+
const trimmed = value.trim();
|
|
12188
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
12189
|
+
}
|
|
12190
|
+
function readFiniteNumber(value, fallback = 0) {
|
|
12191
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
12192
|
+
}
|
|
12193
|
+
function readOptionalFiniteNumber(value) {
|
|
12194
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
12195
|
+
}
|
|
12196
|
+
function normalizeQuestionType(rawType) {
|
|
12197
|
+
const normalized = readString(rawType).trim().toUpperCase().replace(/[\s-]+/g, "_");
|
|
12198
|
+
return normalized === "MULTIPLE_CHOICE" ? "MULTIPLE_CHOICE" : "SINGLE_CHOICE";
|
|
12199
|
+
}
|
|
12200
|
+
function normalizeMessageRole(rawRole) {
|
|
12201
|
+
const normalized = readString(rawRole).trim().toLowerCase();
|
|
12202
|
+
if (normalized === "user" /* User */) return "user" /* User */;
|
|
12203
|
+
if (normalized === "system" /* System */) return "system" /* System */;
|
|
12204
|
+
if (normalized === "tool" /* Tool */) return "tool" /* Tool */;
|
|
12205
|
+
return "assistant" /* Assistant */;
|
|
12206
|
+
}
|
|
12207
|
+
function sanitizeAttachment(rawAttachment, turnId, index) {
|
|
12208
|
+
if (!isRecord(rawAttachment)) {
|
|
12209
|
+
warnMalformedSessionPayload("Dropped malformed attachment entry", { turnId, index });
|
|
12210
|
+
return null;
|
|
12211
|
+
}
|
|
12212
|
+
const filename = readString(rawAttachment.filename, "attachment");
|
|
12213
|
+
const mimeType = readString(rawAttachment.mimeType, "application/octet-stream");
|
|
12214
|
+
const id = readNonEmptyString(rawAttachment.id) || void 0;
|
|
12215
|
+
const clientKey = readNonEmptyString(rawAttachment.clientKey) || id || `${turnId}-attachment-${index}`;
|
|
12067
12216
|
return {
|
|
12068
|
-
id
|
|
12069
|
-
|
|
12217
|
+
id,
|
|
12218
|
+
clientKey,
|
|
12219
|
+
filename,
|
|
12220
|
+
mimeType,
|
|
12221
|
+
sizeBytes: readFiniteNumber(rawAttachment.sizeBytes),
|
|
12222
|
+
uploadId: readOptionalFiniteNumber(rawAttachment.uploadId),
|
|
12223
|
+
base64Data: readNonEmptyString(rawAttachment.base64Data) || void 0,
|
|
12224
|
+
url: readNonEmptyString(rawAttachment.url) || void 0,
|
|
12225
|
+
preview: readNonEmptyString(rawAttachment.preview) || void 0
|
|
12226
|
+
};
|
|
12227
|
+
}
|
|
12228
|
+
function sanitizeUserAttachments(rawAttachments, turnId) {
|
|
12229
|
+
if (!Array.isArray(rawAttachments)) return [];
|
|
12230
|
+
const result = [];
|
|
12231
|
+
for (let i = 0; i < rawAttachments.length; i++) {
|
|
12232
|
+
const sanitized = sanitizeAttachment(rawAttachments[i], turnId, i);
|
|
12233
|
+
if (sanitized) result.push(sanitized);
|
|
12234
|
+
}
|
|
12235
|
+
return result;
|
|
12236
|
+
}
|
|
12237
|
+
function sanitizeAssistantArtifacts(rawArtifacts, turnId) {
|
|
12238
|
+
if (!Array.isArray(rawArtifacts)) return [];
|
|
12239
|
+
const artifacts = [];
|
|
12240
|
+
for (let i = 0; i < rawArtifacts.length; i++) {
|
|
12241
|
+
const raw = rawArtifacts[i];
|
|
12242
|
+
if (!isRecord(raw)) {
|
|
12243
|
+
warnMalformedSessionPayload("Dropped malformed assistant artifact", { turnId, index: i });
|
|
12244
|
+
continue;
|
|
12245
|
+
}
|
|
12246
|
+
const type = readString(raw.type).toLowerCase();
|
|
12247
|
+
if (type !== "excel" && type !== "pdf") {
|
|
12248
|
+
continue;
|
|
12249
|
+
}
|
|
12250
|
+
const url = readNonEmptyString(raw.url);
|
|
12251
|
+
if (!url) {
|
|
12252
|
+
warnMalformedSessionPayload("Dropped assistant artifact without url", { turnId, index: i });
|
|
12253
|
+
continue;
|
|
12254
|
+
}
|
|
12255
|
+
artifacts.push({
|
|
12256
|
+
type,
|
|
12257
|
+
filename: readString(raw.filename, "download"),
|
|
12258
|
+
url,
|
|
12259
|
+
sizeReadable: readNonEmptyString(raw.sizeReadable) || void 0,
|
|
12260
|
+
rowCount: typeof raw.rowCount === "number" && Number.isFinite(raw.rowCount) ? raw.rowCount : void 0,
|
|
12261
|
+
description: readNonEmptyString(raw.description) || void 0
|
|
12262
|
+
});
|
|
12263
|
+
}
|
|
12264
|
+
return artifacts;
|
|
12265
|
+
}
|
|
12266
|
+
function sanitizeAssistantTurn(rawAssistantTurn, fallbackCreatedAt, turnId) {
|
|
12267
|
+
if (rawAssistantTurn == null) return void 0;
|
|
12268
|
+
if (!isRecord(rawAssistantTurn)) {
|
|
12269
|
+
warnMalformedSessionPayload("Dropped malformed assistant turn payload", { turnId });
|
|
12270
|
+
return void 0;
|
|
12271
|
+
}
|
|
12272
|
+
const assistantID = readNonEmptyString(rawAssistantTurn.id);
|
|
12273
|
+
if (!assistantID) {
|
|
12274
|
+
warnMalformedSessionPayload("Dropped assistant turn without id", { turnId });
|
|
12275
|
+
return void 0;
|
|
12276
|
+
}
|
|
12277
|
+
const citations = Array.isArray(rawAssistantTurn.citations) ? rawAssistantTurn.citations.filter((item) => isRecord(item)).map((item, index) => ({
|
|
12278
|
+
id: readString(item.id, `${assistantID}-citation-${index}`),
|
|
12279
|
+
type: readString(item.type),
|
|
12280
|
+
title: readString(item.title),
|
|
12281
|
+
url: readString(item.url),
|
|
12282
|
+
startIndex: readFiniteNumber(item.startIndex),
|
|
12283
|
+
endIndex: readFiniteNumber(item.endIndex),
|
|
12284
|
+
excerpt: readNonEmptyString(item.excerpt) || void 0
|
|
12285
|
+
})) : [];
|
|
12286
|
+
const toolCalls = Array.isArray(rawAssistantTurn.toolCalls) ? rawAssistantTurn.toolCalls.filter((item) => isRecord(item)).map((item, index) => ({
|
|
12287
|
+
id: readString(item.id, `${assistantID}-tool-${index}`),
|
|
12288
|
+
name: readString(item.name),
|
|
12289
|
+
arguments: readString(item.arguments),
|
|
12290
|
+
result: readNonEmptyString(item.result) || void 0,
|
|
12291
|
+
error: readNonEmptyString(item.error) || void 0,
|
|
12292
|
+
durationMs: readFiniteNumber(item.durationMs)
|
|
12293
|
+
})) : [];
|
|
12294
|
+
const codeOutputs = Array.isArray(rawAssistantTurn.codeOutputs) ? rawAssistantTurn.codeOutputs.filter((item) => isRecord(item)).map((item) => ({
|
|
12295
|
+
type: (() => {
|
|
12296
|
+
const normalizedType = readString(item.type, "text").toLowerCase();
|
|
12297
|
+
if (normalizedType === "image" || normalizedType === "error") return normalizedType;
|
|
12298
|
+
return "text";
|
|
12299
|
+
})(),
|
|
12300
|
+
content: readString(item.content),
|
|
12301
|
+
filename: readNonEmptyString(item.filename) || void 0,
|
|
12302
|
+
mimeType: readNonEmptyString(item.mimeType) || void 0,
|
|
12303
|
+
sizeBytes: readOptionalFiniteNumber(item.sizeBytes)
|
|
12304
|
+
})) : [];
|
|
12305
|
+
const debugTrace = isRecord(rawAssistantTurn.debug) ? {
|
|
12306
|
+
generationMs: readOptionalFiniteNumber(rawAssistantTurn.debug.generationMs),
|
|
12307
|
+
usage: isRecord(rawAssistantTurn.debug.usage) ? {
|
|
12308
|
+
promptTokens: readFiniteNumber(rawAssistantTurn.debug.usage.promptTokens),
|
|
12309
|
+
completionTokens: readFiniteNumber(rawAssistantTurn.debug.usage.completionTokens),
|
|
12310
|
+
totalTokens: readFiniteNumber(rawAssistantTurn.debug.usage.totalTokens),
|
|
12311
|
+
cachedTokens: readOptionalFiniteNumber(rawAssistantTurn.debug.usage.cachedTokens),
|
|
12312
|
+
cost: readOptionalFiniteNumber(rawAssistantTurn.debug.usage.cost)
|
|
12313
|
+
} : void 0,
|
|
12314
|
+
tools: Array.isArray(rawAssistantTurn.debug.tools) ? rawAssistantTurn.debug.tools.filter((tool) => isRecord(tool)).map((tool) => ({
|
|
12315
|
+
callId: readNonEmptyString(tool.callId) || void 0,
|
|
12316
|
+
name: readString(tool.name),
|
|
12317
|
+
arguments: readNonEmptyString(tool.arguments) || void 0,
|
|
12318
|
+
result: readNonEmptyString(tool.result) || void 0,
|
|
12319
|
+
error: readNonEmptyString(tool.error) || void 0,
|
|
12320
|
+
durationMs: readOptionalFiniteNumber(tool.durationMs)
|
|
12321
|
+
})) : []
|
|
12322
|
+
} : void 0;
|
|
12323
|
+
return {
|
|
12324
|
+
id: assistantID,
|
|
12325
|
+
role: normalizeMessageRole(rawAssistantTurn.role),
|
|
12326
|
+
content: readString(rawAssistantTurn.content),
|
|
12327
|
+
explanation: readNonEmptyString(rawAssistantTurn.explanation) || void 0,
|
|
12328
|
+
citations,
|
|
12329
|
+
toolCalls,
|
|
12330
|
+
chartData: void 0,
|
|
12331
|
+
artifacts: sanitizeAssistantArtifacts(rawAssistantTurn.artifacts, turnId),
|
|
12332
|
+
codeOutputs,
|
|
12333
|
+
debug: debugTrace,
|
|
12334
|
+
createdAt: readString(rawAssistantTurn.createdAt, fallbackCreatedAt)
|
|
12335
|
+
};
|
|
12336
|
+
}
|
|
12337
|
+
function sanitizeConversationTurn(rawTurn, index, fallbackSessionID) {
|
|
12338
|
+
if (!isRecord(rawTurn)) {
|
|
12339
|
+
warnMalformedSessionPayload("Dropped malformed turn payload (not an object)", { index });
|
|
12340
|
+
return null;
|
|
12341
|
+
}
|
|
12342
|
+
if (!isRecord(rawTurn.userTurn)) {
|
|
12343
|
+
warnMalformedSessionPayload("Dropped malformed turn payload (missing user turn)", { index });
|
|
12344
|
+
return null;
|
|
12345
|
+
}
|
|
12346
|
+
const userTurnID = readNonEmptyString(rawTurn.userTurn.id);
|
|
12347
|
+
if (!userTurnID) {
|
|
12348
|
+
warnMalformedSessionPayload("Dropped malformed turn payload (missing user turn id)", { index });
|
|
12349
|
+
return null;
|
|
12350
|
+
}
|
|
12351
|
+
const turnID = readString(rawTurn.id, userTurnID);
|
|
12352
|
+
const createdAt = readString(
|
|
12353
|
+
rawTurn.createdAt,
|
|
12354
|
+
readString(rawTurn.userTurn.createdAt, (/* @__PURE__ */ new Date()).toISOString())
|
|
12355
|
+
);
|
|
12356
|
+
return {
|
|
12357
|
+
id: turnID,
|
|
12358
|
+
sessionId: readString(rawTurn.sessionId, fallbackSessionID),
|
|
12359
|
+
userTurn: {
|
|
12360
|
+
id: userTurnID,
|
|
12361
|
+
content: readString(rawTurn.userTurn.content),
|
|
12362
|
+
attachments: sanitizeUserAttachments(rawTurn.userTurn.attachments, turnID),
|
|
12363
|
+
createdAt: readString(rawTurn.userTurn.createdAt, createdAt)
|
|
12364
|
+
},
|
|
12365
|
+
assistantTurn: sanitizeAssistantTurn(rawTurn.assistantTurn, createdAt, turnID),
|
|
12366
|
+
createdAt
|
|
12367
|
+
};
|
|
12368
|
+
}
|
|
12369
|
+
function sanitizeConversationTurns(rawTurns, sessionID) {
|
|
12370
|
+
if (!Array.isArray(rawTurns)) {
|
|
12371
|
+
warnMalformedSessionPayload("Session payload contained non-array turns field", { sessionID });
|
|
12372
|
+
return [];
|
|
12373
|
+
}
|
|
12374
|
+
const turns = [];
|
|
12375
|
+
let dropped = 0;
|
|
12376
|
+
for (let i = 0; i < rawTurns.length; i++) {
|
|
12377
|
+
const sanitizedTurn = sanitizeConversationTurn(rawTurns[i], i, sessionID);
|
|
12378
|
+
if (sanitizedTurn) {
|
|
12379
|
+
turns.push(sanitizedTurn);
|
|
12380
|
+
} else {
|
|
12381
|
+
dropped++;
|
|
12382
|
+
}
|
|
12383
|
+
}
|
|
12384
|
+
if (dropped > 0) {
|
|
12385
|
+
warnMalformedSessionPayload("Dropped malformed turns from session payload", {
|
|
12386
|
+
sessionID,
|
|
12387
|
+
dropped,
|
|
12388
|
+
total: rawTurns.length
|
|
12389
|
+
});
|
|
12390
|
+
}
|
|
12391
|
+
return turns;
|
|
12392
|
+
}
|
|
12393
|
+
function sanitizePendingQuestion(rawPendingQuestion, sessionID) {
|
|
12394
|
+
if (!rawPendingQuestion) return null;
|
|
12395
|
+
const checkpointID = readNonEmptyString(rawPendingQuestion.checkpointId);
|
|
12396
|
+
if (!checkpointID) {
|
|
12397
|
+
warnMalformedSessionPayload("Dropped malformed pendingQuestion without checkpointId", { sessionID });
|
|
12398
|
+
return null;
|
|
12399
|
+
}
|
|
12400
|
+
if (!Array.isArray(rawPendingQuestion.questions)) {
|
|
12401
|
+
warnMalformedSessionPayload("Pending question had non-array questions payload", {
|
|
12402
|
+
sessionID,
|
|
12403
|
+
checkpointID
|
|
12404
|
+
});
|
|
12405
|
+
}
|
|
12406
|
+
const questions = Array.isArray(rawPendingQuestion.questions) ? rawPendingQuestion.questions.filter((question) => {
|
|
12407
|
+
if (!question || !isRecord(question)) {
|
|
12408
|
+
warnMalformedSessionPayload("Dropped malformed question from pendingQuestion", {
|
|
12409
|
+
sessionID,
|
|
12410
|
+
checkpointID
|
|
12411
|
+
});
|
|
12412
|
+
return false;
|
|
12413
|
+
}
|
|
12414
|
+
return true;
|
|
12415
|
+
}).map((question, index) => {
|
|
12416
|
+
const questionID = readString(question.id, `${checkpointID}-q-${index}`);
|
|
12417
|
+
const options = Array.isArray(question.options) ? question.options.filter((option) => {
|
|
12418
|
+
if (!option || !isRecord(option)) {
|
|
12419
|
+
warnMalformedSessionPayload("Dropped malformed pendingQuestion option", {
|
|
12420
|
+
sessionID,
|
|
12421
|
+
checkpointID,
|
|
12422
|
+
questionID
|
|
12423
|
+
});
|
|
12424
|
+
return false;
|
|
12425
|
+
}
|
|
12426
|
+
return true;
|
|
12427
|
+
}).map((option, optionIndex) => {
|
|
12428
|
+
const label = readString(option.label);
|
|
12429
|
+
return {
|
|
12430
|
+
id: readString(option.id, `${questionID}-opt-${optionIndex}`),
|
|
12431
|
+
label,
|
|
12432
|
+
value: label
|
|
12433
|
+
};
|
|
12434
|
+
}) : [];
|
|
12435
|
+
return {
|
|
12436
|
+
id: questionID,
|
|
12437
|
+
text: readString(question.text),
|
|
12438
|
+
type: normalizeQuestionType(question.type),
|
|
12439
|
+
options
|
|
12440
|
+
};
|
|
12441
|
+
}) : [];
|
|
12442
|
+
return {
|
|
12443
|
+
id: checkpointID,
|
|
12444
|
+
turnId: readString(rawPendingQuestion.turnId),
|
|
12070
12445
|
questions,
|
|
12071
12446
|
status: "PENDING"
|
|
12072
12447
|
};
|
|
@@ -12262,7 +12637,8 @@ var HttpDataSource = class {
|
|
|
12262
12637
|
this.abortController = null;
|
|
12263
12638
|
this.config = {
|
|
12264
12639
|
streamEndpoint: "/stream",
|
|
12265
|
-
|
|
12640
|
+
uploadEndpoint: "/api/uploads",
|
|
12641
|
+
timeout: 12e4,
|
|
12266
12642
|
...config
|
|
12267
12643
|
};
|
|
12268
12644
|
if (config.navigateToSession) {
|
|
@@ -12297,6 +12673,83 @@ var HttpDataSource = class {
|
|
|
12297
12673
|
}
|
|
12298
12674
|
return headers;
|
|
12299
12675
|
}
|
|
12676
|
+
createUploadHeaders(additionalHeaders) {
|
|
12677
|
+
const headers = new Headers({
|
|
12678
|
+
...this.config.headers,
|
|
12679
|
+
...additionalHeaders
|
|
12680
|
+
});
|
|
12681
|
+
const csrfToken = this.getCSRFToken();
|
|
12682
|
+
if (csrfToken) {
|
|
12683
|
+
headers.set("X-CSRF-Token", csrfToken);
|
|
12684
|
+
}
|
|
12685
|
+
headers.delete("Content-Type");
|
|
12686
|
+
return headers;
|
|
12687
|
+
}
|
|
12688
|
+
async uploadFile(file) {
|
|
12689
|
+
const formData = new FormData();
|
|
12690
|
+
formData.append("file", file);
|
|
12691
|
+
const response = await fetch(`${this.config.baseUrl}${this.config.uploadEndpoint}`, {
|
|
12692
|
+
method: "POST",
|
|
12693
|
+
headers: this.createUploadHeaders(),
|
|
12694
|
+
body: formData
|
|
12695
|
+
});
|
|
12696
|
+
let payload = null;
|
|
12697
|
+
try {
|
|
12698
|
+
payload = await response.json();
|
|
12699
|
+
} catch {
|
|
12700
|
+
payload = null;
|
|
12701
|
+
}
|
|
12702
|
+
if (!response.ok) {
|
|
12703
|
+
const errorMessage = isRecord(payload) && typeof payload.error === "string" ? payload.error : `Upload failed: HTTP ${response.status}`;
|
|
12704
|
+
throw new Error(errorMessage);
|
|
12705
|
+
}
|
|
12706
|
+
if (!isRecord(payload) || typeof payload.id !== "number" || payload.id <= 0) {
|
|
12707
|
+
throw new Error("Upload failed: invalid response payload");
|
|
12708
|
+
}
|
|
12709
|
+
return {
|
|
12710
|
+
id: payload.id,
|
|
12711
|
+
url: typeof payload.url === "string" ? payload.url : "",
|
|
12712
|
+
path: typeof payload.path === "string" ? payload.path : "",
|
|
12713
|
+
name: typeof payload.name === "string" ? payload.name : file.name,
|
|
12714
|
+
mimetype: typeof payload.mimetype === "string" ? payload.mimetype : file.type,
|
|
12715
|
+
size: typeof payload.size === "number" && Number.isFinite(payload.size) ? payload.size : file.size
|
|
12716
|
+
};
|
|
12717
|
+
}
|
|
12718
|
+
async attachmentToFile(attachment) {
|
|
12719
|
+
if (attachment.base64Data && attachment.base64Data.trim().length > 0) {
|
|
12720
|
+
const base64Data = attachment.base64Data.trim();
|
|
12721
|
+
const dataUrl = base64Data.startsWith("data:") ? base64Data : `data:${attachment.mimeType || "application/octet-stream"};base64,${base64Data}`;
|
|
12722
|
+
const blob = await fetch(dataUrl).then((response) => response.blob());
|
|
12723
|
+
return new File([blob], attachment.filename, {
|
|
12724
|
+
type: attachment.mimeType || blob.type || "application/octet-stream"
|
|
12725
|
+
});
|
|
12726
|
+
}
|
|
12727
|
+
if (attachment.url) {
|
|
12728
|
+
const response = await fetch(attachment.url);
|
|
12729
|
+
if (!response.ok) {
|
|
12730
|
+
throw new Error(`Failed to read attachment source: HTTP ${response.status}`);
|
|
12731
|
+
}
|
|
12732
|
+
const blob = await response.blob();
|
|
12733
|
+
return new File([blob], attachment.filename, {
|
|
12734
|
+
type: attachment.mimeType || blob.type || "application/octet-stream"
|
|
12735
|
+
});
|
|
12736
|
+
}
|
|
12737
|
+
throw new Error(`Attachment "${attachment.filename}" has no uploadable data`);
|
|
12738
|
+
}
|
|
12739
|
+
async ensureAttachmentUpload(attachment) {
|
|
12740
|
+
if (typeof attachment.uploadId === "number" && attachment.uploadId > 0) {
|
|
12741
|
+
return {
|
|
12742
|
+
id: attachment.uploadId,
|
|
12743
|
+
url: attachment.url || "",
|
|
12744
|
+
path: "",
|
|
12745
|
+
name: attachment.filename,
|
|
12746
|
+
mimetype: attachment.mimeType,
|
|
12747
|
+
size: attachment.sizeBytes
|
|
12748
|
+
};
|
|
12749
|
+
}
|
|
12750
|
+
const file = await this.attachmentToFile(attachment);
|
|
12751
|
+
return this.uploadFile(file);
|
|
12752
|
+
}
|
|
12300
12753
|
async callRPC(method, params) {
|
|
12301
12754
|
return this.rpc.callTyped(method, params);
|
|
12302
12755
|
}
|
|
@@ -12319,11 +12772,22 @@ var HttpDataSource = class {
|
|
|
12319
12772
|
return { artifacts: [], hasMore: false, nextOffset: 0 };
|
|
12320
12773
|
})
|
|
12321
12774
|
]);
|
|
12322
|
-
const
|
|
12775
|
+
const sanitizedTurns = sanitizeConversationTurns(data.turns, id);
|
|
12776
|
+
const turns = attachArtifactsToTurns(
|
|
12777
|
+
normalizeTurns(sanitizedTurns),
|
|
12778
|
+
artifactsData.artifacts || []
|
|
12779
|
+
);
|
|
12780
|
+
const pendingQuestion = sanitizePendingQuestion(data.pendingQuestion, id);
|
|
12781
|
+
if (data.pendingQuestion && pendingQuestion && pendingQuestion.questions.length === 0) {
|
|
12782
|
+
warnMalformedSessionPayload("Pending question normalized to zero renderable questions", {
|
|
12783
|
+
sessionID: id,
|
|
12784
|
+
checkpointID: pendingQuestion.id
|
|
12785
|
+
});
|
|
12786
|
+
}
|
|
12323
12787
|
return {
|
|
12324
12788
|
session: toSession(data.session),
|
|
12325
12789
|
turns,
|
|
12326
|
-
pendingQuestion
|
|
12790
|
+
pendingQuestion
|
|
12327
12791
|
};
|
|
12328
12792
|
} catch (err) {
|
|
12329
12793
|
if (isSessionNotFoundError(err)) {
|
|
@@ -12355,27 +12819,12 @@ var HttpDataSource = class {
|
|
|
12355
12819
|
return { artifacts: [] };
|
|
12356
12820
|
}
|
|
12357
12821
|
validateFileCount(0, files.length, 10);
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
validateAttachmentFile(file);
|
|
12361
|
-
const base64Data = await convertToBase64(file);
|
|
12362
|
-
attachments.push({
|
|
12363
|
-
clientKey: crypto.randomUUID(),
|
|
12364
|
-
filename: file.name,
|
|
12365
|
-
mimeType: file.type,
|
|
12366
|
-
sizeBytes: file.size,
|
|
12367
|
-
base64Data
|
|
12368
|
-
});
|
|
12369
|
-
}
|
|
12822
|
+
files.forEach((file) => validateAttachmentFile(file));
|
|
12823
|
+
const uploads = await Promise.all(files.map((file) => this.uploadFile(file)));
|
|
12370
12824
|
const data = await this.callRPC("bichat.session.uploadArtifacts", {
|
|
12371
12825
|
sessionId,
|
|
12372
|
-
attachments:
|
|
12373
|
-
|
|
12374
|
-
// Backend will assign ID
|
|
12375
|
-
filename: a.filename,
|
|
12376
|
-
mimeType: a.mimeType,
|
|
12377
|
-
sizeBytes: a.sizeBytes,
|
|
12378
|
-
base64Data: a.base64Data
|
|
12826
|
+
attachments: uploads.map((upload) => ({
|
|
12827
|
+
uploadId: upload.id
|
|
12379
12828
|
}))
|
|
12380
12829
|
});
|
|
12381
12830
|
return {
|
|
@@ -12406,22 +12855,21 @@ var HttpDataSource = class {
|
|
|
12406
12855
|
signal.addEventListener("abort", onExternalAbort);
|
|
12407
12856
|
}
|
|
12408
12857
|
const url = `${this.config.baseUrl}${this.config.streamEndpoint}`;
|
|
12409
|
-
const payload = {
|
|
12410
|
-
sessionId,
|
|
12411
|
-
content,
|
|
12412
|
-
debugMode: options?.debugMode ?? false,
|
|
12413
|
-
replaceFromMessageId: options?.replaceFromMessageID,
|
|
12414
|
-
attachments: attachments.map((a) => ({
|
|
12415
|
-
filename: a.filename,
|
|
12416
|
-
mimeType: a.mimeType,
|
|
12417
|
-
sizeBytes: a.sizeBytes,
|
|
12418
|
-
base64Data: a.base64Data,
|
|
12419
|
-
url: a.url
|
|
12420
|
-
}))
|
|
12421
|
-
};
|
|
12422
12858
|
let connectionTimeoutID;
|
|
12423
12859
|
let connectionTimedOut = false;
|
|
12424
12860
|
try {
|
|
12861
|
+
const uploads = await Promise.all(
|
|
12862
|
+
attachments.map((attachment) => this.ensureAttachmentUpload(attachment))
|
|
12863
|
+
);
|
|
12864
|
+
const payload = {
|
|
12865
|
+
sessionId,
|
|
12866
|
+
content,
|
|
12867
|
+
debugMode: options?.debugMode ?? false,
|
|
12868
|
+
replaceFromMessageId: options?.replaceFromMessageID,
|
|
12869
|
+
attachments: uploads.map((upload) => ({
|
|
12870
|
+
uploadId: upload.id
|
|
12871
|
+
}))
|
|
12872
|
+
};
|
|
12425
12873
|
const timeoutMs = this.config.timeout ?? 0;
|
|
12426
12874
|
if (timeoutMs > 0) {
|
|
12427
12875
|
connectionTimeoutID = setTimeout(() => {
|