@iota-uz/sdk 0.4.36 → 0.4.38
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 +458 -263
- package/dist/bichat/index.cjs.map +1 -1
- package/dist/bichat/index.d.cts +46 -19
- package/dist/bichat/index.d.ts +46 -19
- package/dist/bichat/index.mjs +459 -264
- package/dist/bichat/index.mjs.map +1 -1
- package/package.json +1 -1
- package/tailwind/compiled.css +1 -1
- package/tailwind/iota.css +40 -0
package/dist/bichat/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import rehypeKatex from 'rehype-katex';
|
|
|
12
12
|
import { motion, useMotionValue, useTransform, AnimatePresence, MotionConfig, useReducedMotion } from 'framer-motion';
|
|
13
13
|
import 'react-dom/client';
|
|
14
14
|
import { differenceInMinutes, differenceInHours, differenceInDays, format, isSameDay, startOfDay, isToday, isYesterday } from 'date-fns';
|
|
15
|
-
import { Menu, MenuButton, MenuItems, MenuItem, Popover, PopoverButton, PopoverPanel,
|
|
15
|
+
import { Menu, MenuButton, MenuItems, MenuItem, Popover, PopoverButton, PopoverPanel, Transition } from '@headlessui/react';
|
|
16
16
|
import { createPortal } from 'react-dom';
|
|
17
17
|
|
|
18
18
|
var __defProp = Object.defineProperty;
|
|
@@ -2091,6 +2091,14 @@ var ChatMachine = class {
|
|
|
2091
2091
|
this.lastSendAttempt = null;
|
|
2092
2092
|
/** Prevents fetchSession effect from clobbering state while stream is active. */
|
|
2093
2093
|
this.sendingSessionId = null;
|
|
2094
|
+
/**
|
|
2095
|
+
* Monotonic counter bumped on every real session switch. An async op (send
|
|
2096
|
+
* stream, post-stream sync, queue drain, resume, HITL) captures it at start
|
|
2097
|
+
* and re-checks before writing to the single shared `state.messaging`; a stale
|
|
2098
|
+
* epoch means the user navigated to a different session, so the write is
|
|
2099
|
+
* dropped instead of bleeding into / clobbering the now-visible session.
|
|
2100
|
+
*/
|
|
2101
|
+
this.viewEpoch = 0;
|
|
2094
2102
|
this.fetchCancelled = false;
|
|
2095
2103
|
this.disposed = false;
|
|
2096
2104
|
this.reasoningEffortOptions = null;
|
|
@@ -2275,6 +2283,20 @@ var ChatMachine = class {
|
|
|
2275
2283
|
if (id === prev) {
|
|
2276
2284
|
return;
|
|
2277
2285
|
}
|
|
2286
|
+
this.viewEpoch++;
|
|
2287
|
+
this.abortController?.abort();
|
|
2288
|
+
this.sendingSessionId = null;
|
|
2289
|
+
this._stopPassivePolling();
|
|
2290
|
+
this._updateMessaging({
|
|
2291
|
+
streamingContent: "",
|
|
2292
|
+
thinkingContent: "",
|
|
2293
|
+
activeSteps: [],
|
|
2294
|
+
isStreaming: false,
|
|
2295
|
+
loading: false,
|
|
2296
|
+
generationInProgress: false,
|
|
2297
|
+
streamError: null,
|
|
2298
|
+
streamErrorRetryable: false
|
|
2299
|
+
});
|
|
2278
2300
|
this.state.session.currentSessionId = id;
|
|
2279
2301
|
this._hydrateDebugModeForSession(id);
|
|
2280
2302
|
this._notifySession();
|
|
@@ -2352,6 +2374,48 @@ var ChatMachine = class {
|
|
|
2352
2374
|
}
|
|
2353
2375
|
saveQueue(sid, this.state.input.messageQueue);
|
|
2354
2376
|
}
|
|
2377
|
+
/**
|
|
2378
|
+
* True while `epoch` is still the active view — i.e. the machine has not been
|
|
2379
|
+
* disposed and no session switch has happened since `epoch` was captured.
|
|
2380
|
+
* Async ops gate their writes to the shared messaging state on this.
|
|
2381
|
+
*/
|
|
2382
|
+
_isCurrentEpoch(epoch) {
|
|
2383
|
+
return !this.disposed && this.viewEpoch === epoch;
|
|
2384
|
+
}
|
|
2385
|
+
/** A send can't start while generating, mid-resume, or with an open question. */
|
|
2386
|
+
_isBlockedForSend() {
|
|
2387
|
+
return this.state.messaging.loading || this.state.messaging.generationInProgress || isOpenQuestionStatus(this.state.messaging.pendingQuestion?.status);
|
|
2388
|
+
}
|
|
2389
|
+
/**
|
|
2390
|
+
* Send the next queued message, but only if we still own the view (`epoch`)
|
|
2391
|
+
* and nothing is blocking (an in-flight generation or an open question). The
|
|
2392
|
+
* item is dequeued optimistically and restored to the front if it turns out we
|
|
2393
|
+
* can't send when the deferred tick fires — so a queued message is never
|
|
2394
|
+
* silently dropped.
|
|
2395
|
+
*/
|
|
2396
|
+
_drainQueueIfReady(epoch) {
|
|
2397
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
2398
|
+
return;
|
|
2399
|
+
}
|
|
2400
|
+
const queue = this.state.input.messageQueue;
|
|
2401
|
+
if (queue.length === 0 || this._isBlockedForSend()) {
|
|
2402
|
+
return;
|
|
2403
|
+
}
|
|
2404
|
+
const next = queue[0];
|
|
2405
|
+
this._updateInput({ messageQueue: queue.slice(1) });
|
|
2406
|
+
setTimeout(() => {
|
|
2407
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
if (this._isBlockedForSend()) {
|
|
2411
|
+
this._updateInput({
|
|
2412
|
+
messageQueue: [next, ...this.state.input.messageQueue]
|
|
2413
|
+
});
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
2416
|
+
this._sendMessageCore(next.content, next.attachments);
|
|
2417
|
+
}, 0);
|
|
2418
|
+
}
|
|
2355
2419
|
_setDebugModeForSession(sessionId, enabled) {
|
|
2356
2420
|
const nextDebugModeBySession = { ...this.state.session.debugModeBySession };
|
|
2357
2421
|
if (enabled) {
|
|
@@ -2566,7 +2630,9 @@ var ChatMachine = class {
|
|
|
2566
2630
|
return;
|
|
2567
2631
|
}
|
|
2568
2632
|
this.sendingSessionId = sessionId;
|
|
2569
|
-
|
|
2633
|
+
const controller = new AbortController();
|
|
2634
|
+
this.abortController = controller;
|
|
2635
|
+
const epoch = this.viewEpoch;
|
|
2570
2636
|
this._updateMessaging({ isStreaming: true });
|
|
2571
2637
|
try {
|
|
2572
2638
|
let accumulatedContent = "";
|
|
@@ -2574,6 +2640,9 @@ var ChatMachine = class {
|
|
|
2574
2640
|
sessionId,
|
|
2575
2641
|
runId,
|
|
2576
2642
|
(chunk) => {
|
|
2643
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2577
2646
|
if (chunk.type === "snapshot" && chunk.snapshot?.partialContent !== void 0) {
|
|
2578
2647
|
accumulatedContent = chunk.snapshot.partialContent;
|
|
2579
2648
|
this._updateMessaging({ streamingContent: accumulatedContent });
|
|
@@ -2589,21 +2658,25 @@ var ChatMachine = class {
|
|
|
2589
2658
|
} else if (chunk.type === "done" || chunk.type === "error") {
|
|
2590
2659
|
}
|
|
2591
2660
|
},
|
|
2592
|
-
|
|
2661
|
+
controller.signal
|
|
2593
2662
|
);
|
|
2594
2663
|
clearRunMarker(sessionId);
|
|
2595
|
-
await this._syncSessionFromServer(sessionId, true);
|
|
2664
|
+
await this._syncSessionFromServer(sessionId, true, epoch);
|
|
2596
2665
|
} finally {
|
|
2597
|
-
this.
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2666
|
+
if (this.abortController === controller) {
|
|
2667
|
+
this.abortController = null;
|
|
2668
|
+
}
|
|
2669
|
+
if (this._isCurrentEpoch(epoch)) {
|
|
2670
|
+
this.sendingSessionId = null;
|
|
2671
|
+
this._updateMessaging({
|
|
2672
|
+
isStreaming: false,
|
|
2673
|
+
loading: false,
|
|
2674
|
+
streamingContent: "",
|
|
2675
|
+
thinkingContent: "",
|
|
2676
|
+
activeSteps: [],
|
|
2677
|
+
generationInProgress: false
|
|
2678
|
+
});
|
|
2679
|
+
}
|
|
2607
2680
|
}
|
|
2608
2681
|
}
|
|
2609
2682
|
async _resumeAcceptedRunOrPoll(sessionId, runId) {
|
|
@@ -2846,11 +2919,14 @@ var ChatMachine = class {
|
|
|
2846
2919
|
}
|
|
2847
2920
|
return { activeSessionId, shouldNavigateAfter };
|
|
2848
2921
|
}
|
|
2849
|
-
async _syncSessionFromServer(sessionId, allowEmptyTurns = false) {
|
|
2922
|
+
async _syncSessionFromServer(sessionId, allowEmptyTurns = false, epoch) {
|
|
2850
2923
|
const fetchResult = await this.dataSource.fetchSession(sessionId);
|
|
2851
2924
|
if (!fetchResult) {
|
|
2852
2925
|
return;
|
|
2853
2926
|
}
|
|
2927
|
+
if (epoch !== void 0 && !this._isCurrentEpoch(epoch)) {
|
|
2928
|
+
return;
|
|
2929
|
+
}
|
|
2854
2930
|
this._updateSession({ session: fetchResult.session });
|
|
2855
2931
|
this._setTurnsFromFetch(
|
|
2856
2932
|
allowEmptyTurns ? fetchResult.turns ?? [] : fetchResult.turns,
|
|
@@ -2866,7 +2942,9 @@ var ChatMachine = class {
|
|
|
2866
2942
|
replaceFromMessageID,
|
|
2867
2943
|
reasoningEffort,
|
|
2868
2944
|
model,
|
|
2869
|
-
tempTurnId
|
|
2945
|
+
tempTurnId,
|
|
2946
|
+
controller,
|
|
2947
|
+
epoch
|
|
2870
2948
|
} = params;
|
|
2871
2949
|
let accumulatedContent = "";
|
|
2872
2950
|
let createdSessionId;
|
|
@@ -2877,7 +2955,7 @@ var ChatMachine = class {
|
|
|
2877
2955
|
activeSessionId || "new",
|
|
2878
2956
|
content,
|
|
2879
2957
|
attachments,
|
|
2880
|
-
|
|
2958
|
+
controller.signal,
|
|
2881
2959
|
{
|
|
2882
2960
|
debugMode,
|
|
2883
2961
|
replaceFromMessageID,
|
|
@@ -2885,7 +2963,7 @@ var ChatMachine = class {
|
|
|
2885
2963
|
model
|
|
2886
2964
|
}
|
|
2887
2965
|
)) {
|
|
2888
|
-
if (
|
|
2966
|
+
if (controller.signal.aborted || !this._isCurrentEpoch(epoch)) {
|
|
2889
2967
|
break;
|
|
2890
2968
|
}
|
|
2891
2969
|
if (chunk.type === "stream_started" && chunk.runId) {
|
|
@@ -2926,7 +3004,7 @@ var ChatMachine = class {
|
|
|
2926
3004
|
sessionFetched = true;
|
|
2927
3005
|
const finalSessionId2 = createdSessionId || activeSessionId;
|
|
2928
3006
|
if (finalSessionId2 && finalSessionId2 !== "new") {
|
|
2929
|
-
await this._syncSessionFromServer(finalSessionId2);
|
|
3007
|
+
await this._syncSessionFromServer(finalSessionId2, false, epoch);
|
|
2930
3008
|
}
|
|
2931
3009
|
}
|
|
2932
3010
|
} else if (chunk.type === "done") {
|
|
@@ -2937,7 +3015,7 @@ var ChatMachine = class {
|
|
|
2937
3015
|
sessionFetched = true;
|
|
2938
3016
|
const finalSessionId2 = createdSessionId || activeSessionId;
|
|
2939
3017
|
if (finalSessionId2 && finalSessionId2 !== "new") {
|
|
2940
|
-
await this._syncSessionFromServer(finalSessionId2);
|
|
3018
|
+
await this._syncSessionFromServer(finalSessionId2, false, epoch);
|
|
2941
3019
|
}
|
|
2942
3020
|
}
|
|
2943
3021
|
} else if (chunk.type === "user_message" && chunk.sessionId) {
|
|
@@ -2951,10 +3029,10 @@ var ChatMachine = class {
|
|
|
2951
3029
|
if (finalSessionId && finalSessionId !== "new") {
|
|
2952
3030
|
clearRunMarker(finalSessionId);
|
|
2953
3031
|
}
|
|
2954
|
-
const stopped =
|
|
3032
|
+
const stopped = controller.signal.aborted;
|
|
2955
3033
|
return { createdSessionId, sessionFetched, stopped };
|
|
2956
3034
|
}
|
|
2957
|
-
async _ensureSessionSyncAfterStream(activeSessionId, createdSessionId, sessionFetched) {
|
|
3035
|
+
async _ensureSessionSyncAfterStream(activeSessionId, createdSessionId, sessionFetched, epoch) {
|
|
2958
3036
|
if (sessionFetched) {
|
|
2959
3037
|
return;
|
|
2960
3038
|
}
|
|
@@ -2963,7 +3041,7 @@ var ChatMachine = class {
|
|
|
2963
3041
|
return;
|
|
2964
3042
|
}
|
|
2965
3043
|
try {
|
|
2966
|
-
await this._syncSessionFromServer(finalSessionId, true);
|
|
3044
|
+
await this._syncSessionFromServer(finalSessionId, true, epoch);
|
|
2967
3045
|
} catch (fetchErr) {
|
|
2968
3046
|
console.error("Failed to fetch session after stream:", fetchErr);
|
|
2969
3047
|
}
|
|
@@ -2981,32 +3059,36 @@ var ChatMachine = class {
|
|
|
2981
3059
|
this._clearStreamError();
|
|
2982
3060
|
this.lastSendAttempt = null;
|
|
2983
3061
|
}
|
|
2984
|
-
_handleSendError(err, content,
|
|
3062
|
+
_handleSendError(err, content, tempTurn, epoch) {
|
|
3063
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3064
|
+
return false;
|
|
3065
|
+
}
|
|
2985
3066
|
if (err instanceof Error && err.name === "AbortError") {
|
|
2986
3067
|
this._updateInput({ message: content });
|
|
2987
3068
|
this._clearStreamError();
|
|
2988
3069
|
this._updateMessaging({
|
|
2989
3070
|
turns: this.state.messaging.turns.filter(
|
|
2990
|
-
(turn) => turn.id !==
|
|
3071
|
+
(turn) => turn.id !== tempTurn.id
|
|
2991
3072
|
)
|
|
2992
3073
|
});
|
|
2993
3074
|
const sessionId = this.sendingSessionId ?? this.state.session.currentSessionId;
|
|
2994
3075
|
if (sessionId && sessionId !== "new") {
|
|
2995
|
-
this._syncSessionFromServer(sessionId, true).catch(() => {
|
|
3076
|
+
this._syncSessionFromServer(sessionId, true, epoch).catch(() => {
|
|
2996
3077
|
});
|
|
2997
3078
|
}
|
|
2998
3079
|
return false;
|
|
2999
3080
|
}
|
|
3000
|
-
this._updateMessaging({
|
|
3001
|
-
turns: this.state.messaging.turns.filter(
|
|
3002
|
-
(turn) => turn.id !== tempTurnId
|
|
3003
|
-
)
|
|
3004
|
-
});
|
|
3005
3081
|
const normalized = normalizeRPCError(err, "Failed to send message");
|
|
3006
|
-
this.
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3082
|
+
if (this.lastSendAttempt) {
|
|
3083
|
+
this.lastSendAttempt = {
|
|
3084
|
+
...this.lastSendAttempt,
|
|
3085
|
+
options: {
|
|
3086
|
+
...this.lastSendAttempt.options,
|
|
3087
|
+
replaceFromMessageID: tempTurn.userTurn.id
|
|
3088
|
+
}
|
|
3089
|
+
};
|
|
3090
|
+
}
|
|
3091
|
+
this._updateInput({ message: "", inputError: null });
|
|
3010
3092
|
this._updateMessaging({
|
|
3011
3093
|
streamError: normalized.userMessage,
|
|
3012
3094
|
streamErrorRetryable: normalized.retryable
|
|
@@ -3067,7 +3149,9 @@ var ChatMachine = class {
|
|
|
3067
3149
|
loading: true,
|
|
3068
3150
|
streamingContent: ""
|
|
3069
3151
|
});
|
|
3070
|
-
|
|
3152
|
+
const controller = new AbortController();
|
|
3153
|
+
this.abortController = controller;
|
|
3154
|
+
const epoch = this.viewEpoch;
|
|
3071
3155
|
const curSessionId = this.state.session.currentSessionId;
|
|
3072
3156
|
const curDebugMode = deriveDebugMode(this.state);
|
|
3073
3157
|
const replaceFromMessageID = options?.replaceFromMessageID;
|
|
@@ -3093,9 +3177,12 @@ var ChatMachine = class {
|
|
|
3093
3177
|
this.state.session.reasoningEffort
|
|
3094
3178
|
),
|
|
3095
3179
|
model: this.state.session.model,
|
|
3096
|
-
tempTurnId: tempTurn.id
|
|
3180
|
+
tempTurnId: tempTurn.id,
|
|
3181
|
+
controller,
|
|
3182
|
+
epoch
|
|
3097
3183
|
});
|
|
3098
|
-
if (
|
|
3184
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3185
|
+
} else if (stopped) {
|
|
3099
3186
|
this._updateMessaging({
|
|
3100
3187
|
turns: this.state.messaging.turns.filter(
|
|
3101
3188
|
(turn) => turn.id !== tempTurn.id
|
|
@@ -3105,39 +3192,37 @@ var ChatMachine = class {
|
|
|
3105
3192
|
this._clearStreamError();
|
|
3106
3193
|
const syncId = createdSessionId || activeSessionId;
|
|
3107
3194
|
if (syncId && syncId !== "new") {
|
|
3108
|
-
await this._syncSessionFromServer(syncId, true).catch(() => {
|
|
3195
|
+
await this._syncSessionFromServer(syncId, true, epoch).catch(() => {
|
|
3109
3196
|
});
|
|
3110
3197
|
}
|
|
3111
3198
|
} else {
|
|
3112
3199
|
await this._ensureSessionSyncAfterStream(
|
|
3113
3200
|
activeSessionId,
|
|
3114
3201
|
createdSessionId,
|
|
3115
|
-
sessionFetched
|
|
3202
|
+
sessionFetched,
|
|
3203
|
+
epoch
|
|
3116
3204
|
);
|
|
3117
3205
|
const targetSessionId = createdSessionId || activeSessionId;
|
|
3118
3206
|
this._finalizeSuccessfulSend(targetSessionId, shouldNavigateAfter);
|
|
3119
3207
|
}
|
|
3120
3208
|
} catch (err) {
|
|
3121
|
-
shouldDrainQueue = this._handleSendError(err, content, tempTurn
|
|
3209
|
+
shouldDrainQueue = this._handleSendError(err, content, tempTurn, epoch);
|
|
3122
3210
|
} finally {
|
|
3123
|
-
this.
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3211
|
+
if (this._isCurrentEpoch(epoch)) {
|
|
3212
|
+
this._updateMessaging({
|
|
3213
|
+
loading: false,
|
|
3214
|
+
streamingContent: "",
|
|
3215
|
+
isStreaming: false,
|
|
3216
|
+
thinkingContent: "",
|
|
3217
|
+
activeSteps: []
|
|
3218
|
+
});
|
|
3219
|
+
this.sendingSessionId = null;
|
|
3220
|
+
}
|
|
3221
|
+
if (this.abortController === controller) {
|
|
3222
|
+
this.abortController = null;
|
|
3223
|
+
}
|
|
3132
3224
|
if (shouldDrainQueue) {
|
|
3133
|
-
|
|
3134
|
-
if (queue.length > 0 && !isOpenQuestionStatus(this.state.messaging.pendingQuestion?.status)) {
|
|
3135
|
-
const next = queue[0];
|
|
3136
|
-
this._updateInput({ messageQueue: queue.slice(1) });
|
|
3137
|
-
setTimeout(() => {
|
|
3138
|
-
this._sendMessageCore(next.content, next.attachments);
|
|
3139
|
-
}, 0);
|
|
3140
|
-
}
|
|
3225
|
+
this._drainQueueIfReady(epoch);
|
|
3141
3226
|
}
|
|
3142
3227
|
}
|
|
3143
3228
|
}
|
|
@@ -3224,7 +3309,7 @@ var ChatMachine = class {
|
|
|
3224
3309
|
);
|
|
3225
3310
|
}
|
|
3226
3311
|
// ── Regenerate / Edit ───────────────────────────────────────────────────
|
|
3227
|
-
async _handleRegenerate(turnId) {
|
|
3312
|
+
async _handleRegenerate(turnId, model) {
|
|
3228
3313
|
const curSessionId = this.state.session.currentSessionId;
|
|
3229
3314
|
if (!curSessionId || curSessionId === "new") {
|
|
3230
3315
|
return;
|
|
@@ -3233,6 +3318,9 @@ var ChatMachine = class {
|
|
|
3233
3318
|
if (!turn) {
|
|
3234
3319
|
return;
|
|
3235
3320
|
}
|
|
3321
|
+
if (model && model !== this.state.session.model) {
|
|
3322
|
+
this._setModel(model);
|
|
3323
|
+
}
|
|
3236
3324
|
this._updateSession({ error: null, errorRetryable: false });
|
|
3237
3325
|
await this._sendMessageDirect(
|
|
3238
3326
|
turn.userTurn.content,
|
|
@@ -3280,6 +3368,7 @@ var ChatMachine = class {
|
|
|
3280
3368
|
if (!curSessionId || !curPendingQuestion) {
|
|
3281
3369
|
return;
|
|
3282
3370
|
}
|
|
3371
|
+
const epoch = this.viewEpoch;
|
|
3283
3372
|
this._updateMessaging({ loading: true });
|
|
3284
3373
|
this._updateSession({ error: null, errorRetryable: false });
|
|
3285
3374
|
const previousPendingQuestion = curPendingQuestion;
|
|
@@ -3289,7 +3378,7 @@ var ChatMachine = class {
|
|
|
3289
3378
|
previousPendingQuestion.id,
|
|
3290
3379
|
answers
|
|
3291
3380
|
);
|
|
3292
|
-
if (this.
|
|
3381
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3293
3382
|
return;
|
|
3294
3383
|
}
|
|
3295
3384
|
if (result.success) {
|
|
@@ -3310,7 +3399,7 @@ var ChatMachine = class {
|
|
|
3310
3399
|
await this._resumeAcceptedRunOrPoll(curSessionId, result.data.runId);
|
|
3311
3400
|
if (!this.state.messaging.generationInProgress) {
|
|
3312
3401
|
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
3313
|
-
if (this.
|
|
3402
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3314
3403
|
return;
|
|
3315
3404
|
}
|
|
3316
3405
|
if (fetchResult) {
|
|
@@ -3328,7 +3417,7 @@ var ChatMachine = class {
|
|
|
3328
3417
|
}
|
|
3329
3418
|
} else if (curSessionId !== "new") {
|
|
3330
3419
|
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
3331
|
-
if (this.
|
|
3420
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3332
3421
|
return;
|
|
3333
3422
|
}
|
|
3334
3423
|
if (fetchResult) {
|
|
@@ -3351,7 +3440,7 @@ var ChatMachine = class {
|
|
|
3351
3440
|
});
|
|
3352
3441
|
}
|
|
3353
3442
|
} catch (err) {
|
|
3354
|
-
if (this.
|
|
3443
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3355
3444
|
return;
|
|
3356
3445
|
}
|
|
3357
3446
|
const normalized = normalizeRPCError(err, "Failed to submit answers");
|
|
@@ -3360,8 +3449,11 @@ var ChatMachine = class {
|
|
|
3360
3449
|
errorRetryable: normalized.retryable
|
|
3361
3450
|
});
|
|
3362
3451
|
} finally {
|
|
3363
|
-
if (
|
|
3452
|
+
if (this._isCurrentEpoch(epoch)) {
|
|
3364
3453
|
this._updateMessaging({ loading: false });
|
|
3454
|
+
if (!this.state.session.error) {
|
|
3455
|
+
this._drainQueueIfReady(epoch);
|
|
3456
|
+
}
|
|
3365
3457
|
}
|
|
3366
3458
|
}
|
|
3367
3459
|
}
|
|
@@ -3371,9 +3463,10 @@ var ChatMachine = class {
|
|
|
3371
3463
|
if (!curSessionId || !curPendingQuestion) {
|
|
3372
3464
|
return;
|
|
3373
3465
|
}
|
|
3466
|
+
const epoch = this.viewEpoch;
|
|
3374
3467
|
try {
|
|
3375
3468
|
const result = await this.dataSource.rejectPendingQuestion(curSessionId);
|
|
3376
|
-
if (this.
|
|
3469
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3377
3470
|
return;
|
|
3378
3471
|
}
|
|
3379
3472
|
if (result.success) {
|
|
@@ -3392,7 +3485,7 @@ var ChatMachine = class {
|
|
|
3392
3485
|
await this._resumeAcceptedRunOrPoll(curSessionId, result.data.runId);
|
|
3393
3486
|
if (!this.state.messaging.generationInProgress && curSessionId !== "new") {
|
|
3394
3487
|
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
3395
|
-
if (this.
|
|
3488
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3396
3489
|
return;
|
|
3397
3490
|
}
|
|
3398
3491
|
if (fetchResult) {
|
|
@@ -3410,7 +3503,7 @@ var ChatMachine = class {
|
|
|
3410
3503
|
}
|
|
3411
3504
|
} else if (curSessionId !== "new") {
|
|
3412
3505
|
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
3413
|
-
if (this.
|
|
3506
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3414
3507
|
return;
|
|
3415
3508
|
}
|
|
3416
3509
|
if (fetchResult) {
|
|
@@ -3428,7 +3521,7 @@ var ChatMachine = class {
|
|
|
3428
3521
|
});
|
|
3429
3522
|
}
|
|
3430
3523
|
} catch (err) {
|
|
3431
|
-
if (this.
|
|
3524
|
+
if (!this._isCurrentEpoch(epoch)) {
|
|
3432
3525
|
return;
|
|
3433
3526
|
}
|
|
3434
3527
|
const normalized = normalizeRPCError(err, "Failed to reject question");
|
|
@@ -3436,6 +3529,10 @@ var ChatMachine = class {
|
|
|
3436
3529
|
error: normalized.userMessage,
|
|
3437
3530
|
errorRetryable: normalized.retryable
|
|
3438
3531
|
});
|
|
3532
|
+
} finally {
|
|
3533
|
+
if (this._isCurrentEpoch(epoch) && !this.state.session.error) {
|
|
3534
|
+
this._drainQueueIfReady(epoch);
|
|
3535
|
+
}
|
|
3439
3536
|
}
|
|
3440
3537
|
}
|
|
3441
3538
|
// ── Input / queue ───────────────────────────────────────────────────────
|
|
@@ -4292,6 +4389,167 @@ function AttachmentGrid({
|
|
|
4292
4389
|
var MemoizedAttachmentGrid = React.memo(AttachmentGrid);
|
|
4293
4390
|
MemoizedAttachmentGrid.displayName = "AttachmentGrid";
|
|
4294
4391
|
var AttachmentGrid_default = MemoizedAttachmentGrid;
|
|
4392
|
+
function deepActiveElement(root) {
|
|
4393
|
+
let active = root.activeElement;
|
|
4394
|
+
while (active?.shadowRoot?.activeElement) {
|
|
4395
|
+
active = active.shadowRoot.activeElement;
|
|
4396
|
+
}
|
|
4397
|
+
return active instanceof HTMLElement ? active : null;
|
|
4398
|
+
}
|
|
4399
|
+
function useFocusTrap(containerRef, isActive, restoreFocusOnDeactivate) {
|
|
4400
|
+
useEffect(() => {
|
|
4401
|
+
if (!isActive || !containerRef.current) {
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
const container = containerRef.current;
|
|
4405
|
+
const root = container.getRootNode();
|
|
4406
|
+
const previouslyFocused = deepActiveElement(root);
|
|
4407
|
+
const getFocusableElements = () => {
|
|
4408
|
+
const selector = [
|
|
4409
|
+
"button:not([disabled])",
|
|
4410
|
+
"[href]",
|
|
4411
|
+
"input:not([disabled])",
|
|
4412
|
+
"select:not([disabled])",
|
|
4413
|
+
"textarea:not([disabled])",
|
|
4414
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
4415
|
+
].join(", ");
|
|
4416
|
+
return Array.from(container.querySelectorAll(selector));
|
|
4417
|
+
};
|
|
4418
|
+
const focusableElements = getFocusableElements();
|
|
4419
|
+
const initialTarget = container.querySelector("[data-autofocus]") ?? focusableElements[0];
|
|
4420
|
+
initialTarget?.focus();
|
|
4421
|
+
const handleTabKey = (e) => {
|
|
4422
|
+
if (e.key !== "Tab") {
|
|
4423
|
+
return;
|
|
4424
|
+
}
|
|
4425
|
+
const focusableElements2 = getFocusableElements();
|
|
4426
|
+
if (focusableElements2.length === 0) {
|
|
4427
|
+
return;
|
|
4428
|
+
}
|
|
4429
|
+
const firstElement = focusableElements2[0];
|
|
4430
|
+
const lastElement = focusableElements2[focusableElements2.length - 1];
|
|
4431
|
+
const active = deepActiveElement(root);
|
|
4432
|
+
if (e.shiftKey) {
|
|
4433
|
+
if (active === firstElement) {
|
|
4434
|
+
e.preventDefault();
|
|
4435
|
+
lastElement.focus();
|
|
4436
|
+
}
|
|
4437
|
+
} else {
|
|
4438
|
+
if (active === lastElement) {
|
|
4439
|
+
e.preventDefault();
|
|
4440
|
+
firstElement.focus();
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
};
|
|
4444
|
+
container.addEventListener("keydown", handleTabKey);
|
|
4445
|
+
return () => {
|
|
4446
|
+
container.removeEventListener("keydown", handleTabKey);
|
|
4447
|
+
if (restoreFocusOnDeactivate) {
|
|
4448
|
+
restoreFocusOnDeactivate.focus();
|
|
4449
|
+
} else if (previouslyFocused) {
|
|
4450
|
+
previouslyFocused.focus();
|
|
4451
|
+
}
|
|
4452
|
+
};
|
|
4453
|
+
}, [containerRef, isActive, restoreFocusOnDeactivate]);
|
|
4454
|
+
}
|
|
4455
|
+
var lockCount = 0;
|
|
4456
|
+
var restorePreviousStyles = null;
|
|
4457
|
+
function applyBodyLock() {
|
|
4458
|
+
const body = document.body;
|
|
4459
|
+
const previousOverflow = body.style.overflow;
|
|
4460
|
+
const previousPaddingRight = body.style.paddingRight;
|
|
4461
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
4462
|
+
body.style.overflow = "hidden";
|
|
4463
|
+
if (scrollbarWidth > 0) {
|
|
4464
|
+
const currentPadding = parseFloat(window.getComputedStyle(body).paddingRight) || 0;
|
|
4465
|
+
body.style.paddingRight = `${currentPadding + scrollbarWidth}px`;
|
|
4466
|
+
}
|
|
4467
|
+
restorePreviousStyles = () => {
|
|
4468
|
+
body.style.overflow = previousOverflow;
|
|
4469
|
+
body.style.paddingRight = previousPaddingRight;
|
|
4470
|
+
};
|
|
4471
|
+
}
|
|
4472
|
+
function useModalLock(isOpen) {
|
|
4473
|
+
useEffect(() => {
|
|
4474
|
+
if (!isOpen) {
|
|
4475
|
+
return;
|
|
4476
|
+
}
|
|
4477
|
+
if (lockCount === 0) {
|
|
4478
|
+
applyBodyLock();
|
|
4479
|
+
}
|
|
4480
|
+
lockCount += 1;
|
|
4481
|
+
return () => {
|
|
4482
|
+
lockCount -= 1;
|
|
4483
|
+
if (lockCount === 0 && restorePreviousStyles) {
|
|
4484
|
+
restorePreviousStyles();
|
|
4485
|
+
restorePreviousStyles = null;
|
|
4486
|
+
}
|
|
4487
|
+
};
|
|
4488
|
+
}, [isOpen]);
|
|
4489
|
+
}
|
|
4490
|
+
var DialogContext = createContext(null);
|
|
4491
|
+
function InlineDialog({ open, onClose, className, children }) {
|
|
4492
|
+
const containerRef = useRef(null);
|
|
4493
|
+
useModalLock(open);
|
|
4494
|
+
useFocusTrap(containerRef, open);
|
|
4495
|
+
useEffect(() => {
|
|
4496
|
+
if (!open) {
|
|
4497
|
+
return;
|
|
4498
|
+
}
|
|
4499
|
+
const container = containerRef.current;
|
|
4500
|
+
if (!container) {
|
|
4501
|
+
return;
|
|
4502
|
+
}
|
|
4503
|
+
const handler = (e) => {
|
|
4504
|
+
if (e.key === "Escape") {
|
|
4505
|
+
onClose();
|
|
4506
|
+
}
|
|
4507
|
+
};
|
|
4508
|
+
container.addEventListener("keydown", handler);
|
|
4509
|
+
return () => container.removeEventListener("keydown", handler);
|
|
4510
|
+
}, [open, onClose]);
|
|
4511
|
+
if (!open) {
|
|
4512
|
+
return null;
|
|
4513
|
+
}
|
|
4514
|
+
return /* @__PURE__ */ jsx(DialogContext.Provider, { value: onClose, children: /* @__PURE__ */ jsx(
|
|
4515
|
+
"div",
|
|
4516
|
+
{
|
|
4517
|
+
ref: containerRef,
|
|
4518
|
+
className,
|
|
4519
|
+
onClick: onClose,
|
|
4520
|
+
tabIndex: -1,
|
|
4521
|
+
children
|
|
4522
|
+
}
|
|
4523
|
+
) });
|
|
4524
|
+
}
|
|
4525
|
+
function InlineDialogBackdrop(props) {
|
|
4526
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", ...props });
|
|
4527
|
+
}
|
|
4528
|
+
function InlineDialogPanel({
|
|
4529
|
+
children,
|
|
4530
|
+
onClick,
|
|
4531
|
+
...rest
|
|
4532
|
+
}) {
|
|
4533
|
+
return /* @__PURE__ */ jsx(
|
|
4534
|
+
"div",
|
|
4535
|
+
{
|
|
4536
|
+
role: "dialog",
|
|
4537
|
+
"aria-modal": "true",
|
|
4538
|
+
onClick: (e) => {
|
|
4539
|
+
e.stopPropagation();
|
|
4540
|
+
onClick?.(e);
|
|
4541
|
+
},
|
|
4542
|
+
...rest,
|
|
4543
|
+
children
|
|
4544
|
+
}
|
|
4545
|
+
);
|
|
4546
|
+
}
|
|
4547
|
+
function InlineDialogTitle(props) {
|
|
4548
|
+
return /* @__PURE__ */ jsx("h2", { ...props });
|
|
4549
|
+
}
|
|
4550
|
+
function InlineDialogDescription(props) {
|
|
4551
|
+
return /* @__PURE__ */ jsx("p", { ...props });
|
|
4552
|
+
}
|
|
4295
4553
|
init_useTranslation();
|
|
4296
4554
|
function ToolbarButton({
|
|
4297
4555
|
onClick,
|
|
@@ -4494,16 +4752,16 @@ function ImageModal({
|
|
|
4494
4752
|
}, [isZoomed, onClose]);
|
|
4495
4753
|
const previewUrl = attachment.preview || createDataUrl(attachment.base64Data, attachment.mimeType);
|
|
4496
4754
|
const zoomPercent = Math.round(scale * 100);
|
|
4497
|
-
return /* @__PURE__ */ jsxs(
|
|
4755
|
+
return /* @__PURE__ */ jsxs(InlineDialog, { open: isOpen, onClose, className: "relative z-[99999]", children: [
|
|
4498
4756
|
/* @__PURE__ */ jsx(
|
|
4499
|
-
|
|
4757
|
+
InlineDialogBackdrop,
|
|
4500
4758
|
{
|
|
4501
4759
|
className: "fixed inset-0 bg-black/90 backdrop-blur-sm",
|
|
4502
4760
|
style: { zIndex: 99999 }
|
|
4503
4761
|
}
|
|
4504
4762
|
),
|
|
4505
4763
|
/* @__PURE__ */ jsxs(
|
|
4506
|
-
|
|
4764
|
+
InlineDialogPanel,
|
|
4507
4765
|
{
|
|
4508
4766
|
className: "fixed inset-0 flex flex-col",
|
|
4509
4767
|
style: { zIndex: 1e5 },
|
|
@@ -4652,7 +4910,7 @@ var defaultClassNames = {
|
|
|
4652
4910
|
bubble: "bg-primary-600 text-white rounded-2xl rounded-br-sm px-4 py-3 shadow-sm",
|
|
4653
4911
|
content: "text-sm whitespace-pre-wrap break-words leading-relaxed",
|
|
4654
4912
|
attachments: "mb-2 w-full",
|
|
4655
|
-
actions: "flex items-center gap-1 mt-2
|
|
4913
|
+
actions: "flex items-center gap-1 mt-2",
|
|
4656
4914
|
actionButton: "cursor-pointer p-2 min-h-[44px] min-w-[44px] flex items-center justify-center text-gray-500 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 active:bg-gray-200 dark:active:bg-gray-700 rounded-md transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
|
|
4657
4915
|
timestamp: "text-xs text-gray-400 dark:text-gray-500 mr-1"
|
|
4658
4916
|
};
|
|
@@ -5051,6 +5309,7 @@ function UserTurnView({
|
|
|
5051
5309
|
}
|
|
5052
5310
|
);
|
|
5053
5311
|
}
|
|
5312
|
+
init_IotaContext();
|
|
5054
5313
|
init_useTranslation();
|
|
5055
5314
|
function toBase64(str) {
|
|
5056
5315
|
const bytes = new TextEncoder().encode(str);
|
|
@@ -6165,6 +6424,8 @@ function FullscreenOverlay({ title, onClose, closeLabel, children }) {
|
|
|
6165
6424
|
const panelRef = useRef(null);
|
|
6166
6425
|
const onCloseRef = useRef(onClose);
|
|
6167
6426
|
onCloseRef.current = onClose;
|
|
6427
|
+
useModalLock(true);
|
|
6428
|
+
useFocusTrap(panelRef, true);
|
|
6168
6429
|
useEffect(() => {
|
|
6169
6430
|
const onKeyDown = (e) => {
|
|
6170
6431
|
if (e.key === "Escape") {
|
|
@@ -6173,7 +6434,6 @@ function FullscreenOverlay({ title, onClose, closeLabel, children }) {
|
|
|
6173
6434
|
}
|
|
6174
6435
|
};
|
|
6175
6436
|
document.addEventListener("keydown", onKeyDown);
|
|
6176
|
-
panelRef.current?.focus();
|
|
6177
6437
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
6178
6438
|
}, []);
|
|
6179
6439
|
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0", style: { zIndex: 99999 }, children: [
|
|
@@ -7742,7 +8002,7 @@ var defaultClassNames2 = {
|
|
|
7742
8002
|
artifacts: "mb-1 flex flex-wrap gap-2",
|
|
7743
8003
|
sources: "",
|
|
7744
8004
|
explanation: "mt-4 border-t border-gray-100 dark:border-gray-700 pt-4",
|
|
7745
|
-
actions: "flex items-center gap-1
|
|
8005
|
+
actions: "flex items-center gap-1",
|
|
7746
8006
|
actionButton: "cursor-pointer p-2 min-h-[44px] min-w-[44px] flex items-center justify-center text-gray-500 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 active:bg-gray-200 dark:active:bg-gray-700 rounded-md transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
|
|
7747
8007
|
timestamp: "text-xs text-gray-400 dark:text-gray-500 mr-1"
|
|
7748
8008
|
};
|
|
@@ -7776,6 +8036,7 @@ function AssistantMessage({
|
|
|
7776
8036
|
classNames: classNameOverrides,
|
|
7777
8037
|
onCopy,
|
|
7778
8038
|
onRegenerate,
|
|
8039
|
+
regenerateModels,
|
|
7779
8040
|
onSendMessage,
|
|
7780
8041
|
sendDisabled = false,
|
|
7781
8042
|
hideAvatar = false,
|
|
@@ -7786,6 +8047,8 @@ function AssistantMessage({
|
|
|
7786
8047
|
const { t } = useTranslation();
|
|
7787
8048
|
const [explanationExpanded, setExplanationExpanded] = useState(false);
|
|
7788
8049
|
const [isCopied, setIsCopied] = useState(false);
|
|
8050
|
+
const [showRegenPicker, setShowRegenPicker] = useState(false);
|
|
8051
|
+
const regenPickerRef = useRef(null);
|
|
7789
8052
|
const copyFeedbackTimeoutRef = useRef(
|
|
7790
8053
|
null
|
|
7791
8054
|
);
|
|
@@ -7838,11 +8101,56 @@ function AssistantMessage({
|
|
|
7838
8101
|
console.error("Failed to copy:", err);
|
|
7839
8102
|
}
|
|
7840
8103
|
}, [onCopy, turn.content]);
|
|
8104
|
+
const hasRegenChoices = (regenerateModels?.length ?? 0) >= 2;
|
|
7841
8105
|
const handleRegenerateClick = useCallback(async () => {
|
|
7842
|
-
if (onRegenerate
|
|
7843
|
-
|
|
8106
|
+
if (!onRegenerate || !turnId) {
|
|
8107
|
+
return;
|
|
7844
8108
|
}
|
|
7845
|
-
|
|
8109
|
+
if (hasRegenChoices) {
|
|
8110
|
+
setShowRegenPicker((prev) => !prev);
|
|
8111
|
+
return;
|
|
8112
|
+
}
|
|
8113
|
+
await onRegenerate(turnId);
|
|
8114
|
+
}, [onRegenerate, turnId, hasRegenChoices]);
|
|
8115
|
+
const handleRegenerateWithModel = useCallback(
|
|
8116
|
+
async (modelId) => {
|
|
8117
|
+
setShowRegenPicker(false);
|
|
8118
|
+
if (onRegenerate && turnId) {
|
|
8119
|
+
await onRegenerate(turnId, modelId);
|
|
8120
|
+
}
|
|
8121
|
+
},
|
|
8122
|
+
[onRegenerate, turnId]
|
|
8123
|
+
);
|
|
8124
|
+
useEffect(() => {
|
|
8125
|
+
if (!showRegenPicker) {
|
|
8126
|
+
return;
|
|
8127
|
+
}
|
|
8128
|
+
const handlePointer = (e) => {
|
|
8129
|
+
const root = regenPickerRef.current;
|
|
8130
|
+
if (!root) {
|
|
8131
|
+
return;
|
|
8132
|
+
}
|
|
8133
|
+
const path = typeof e.composedPath === "function" ? e.composedPath() : [];
|
|
8134
|
+
const insideViaPath = path.includes(root);
|
|
8135
|
+
const insideViaContains = root.contains(e.target);
|
|
8136
|
+
if (!insideViaPath && !insideViaContains) {
|
|
8137
|
+
setShowRegenPicker(false);
|
|
8138
|
+
}
|
|
8139
|
+
};
|
|
8140
|
+
const handleKey = (e) => {
|
|
8141
|
+
if (e.key === "Escape") {
|
|
8142
|
+
setShowRegenPicker(false);
|
|
8143
|
+
}
|
|
8144
|
+
};
|
|
8145
|
+
document.addEventListener("mousedown", handlePointer);
|
|
8146
|
+
document.addEventListener("touchstart", handlePointer);
|
|
8147
|
+
document.addEventListener("keydown", handleKey);
|
|
8148
|
+
return () => {
|
|
8149
|
+
document.removeEventListener("mousedown", handlePointer);
|
|
8150
|
+
document.removeEventListener("touchstart", handlePointer);
|
|
8151
|
+
document.removeEventListener("keydown", handleKey);
|
|
8152
|
+
};
|
|
8153
|
+
}, [showRegenPicker]);
|
|
7846
8154
|
const timestamp = formatRelativeTime(turn.createdAt, t);
|
|
7847
8155
|
const avatarSlotProps = {
|
|
7848
8156
|
text: isSystemMessage ? "SYS" : "AI"
|
|
@@ -7869,7 +8177,17 @@ function AssistantMessage({
|
|
|
7869
8177
|
};
|
|
7870
8178
|
const actionsSlotProps = {
|
|
7871
8179
|
onCopy: handleCopyClick,
|
|
7872
|
-
onRegenerate: canRegenerate ?
|
|
8180
|
+
onRegenerate: canRegenerate ? (model) => {
|
|
8181
|
+
if (!onRegenerate || !turnId) {
|
|
8182
|
+
return;
|
|
8183
|
+
}
|
|
8184
|
+
if (model) {
|
|
8185
|
+
void handleRegenerateWithModel(model);
|
|
8186
|
+
} else {
|
|
8187
|
+
void handleRegenerateClick();
|
|
8188
|
+
}
|
|
8189
|
+
} : void 0,
|
|
8190
|
+
regenerateModels,
|
|
7873
8191
|
timestamp,
|
|
7874
8192
|
canCopy: hasContent,
|
|
7875
8193
|
canRegenerate
|
|
@@ -8060,16 +8378,56 @@ function AssistantMessage({
|
|
|
8060
8378
|
children: isCopied ? /* @__PURE__ */ jsx(Check, { size: 14, weight: "bold" }) : /* @__PURE__ */ jsx(Copy, { size: 14, weight: "regular" })
|
|
8061
8379
|
}
|
|
8062
8380
|
),
|
|
8063
|
-
canRegenerate && /* @__PURE__ */
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8381
|
+
canRegenerate && /* @__PURE__ */ jsxs("div", { ref: regenPickerRef, className: "relative inline-flex", children: [
|
|
8382
|
+
/* @__PURE__ */ jsx(
|
|
8383
|
+
"button",
|
|
8384
|
+
{
|
|
8385
|
+
onClick: handleRegenerateClick,
|
|
8386
|
+
className: `cursor-pointer ${classes.actionButton} ${showRegenPicker ? "bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-200" : ""}`,
|
|
8387
|
+
"aria-label": t("BiChat.Message.Regenerate"),
|
|
8388
|
+
title: t("BiChat.Message.Regenerate"),
|
|
8389
|
+
"aria-haspopup": hasRegenChoices ? "menu" : void 0,
|
|
8390
|
+
"aria-expanded": hasRegenChoices ? showRegenPicker : void 0,
|
|
8391
|
+
children: /* @__PURE__ */ jsx(ArrowsClockwise, { size: 14, weight: "regular" })
|
|
8392
|
+
}
|
|
8393
|
+
),
|
|
8394
|
+
hasRegenChoices && showRegenPicker && /* @__PURE__ */ jsx(
|
|
8395
|
+
"div",
|
|
8396
|
+
{
|
|
8397
|
+
role: "menu",
|
|
8398
|
+
"aria-label": t("BiChat.Message.Regenerate"),
|
|
8399
|
+
className: "animate-slide-up absolute left-0 top-full z-20 mt-1 flex flex-col gap-0.5 rounded-lg border border-gray-200 bg-white p-1 shadow-lg dark:border-gray-700 dark:bg-gray-800",
|
|
8400
|
+
children: regenerateModels.map((m, i) => {
|
|
8401
|
+
const isFast = i === 0;
|
|
8402
|
+
const Icon = isFast ? Lightning : Brain;
|
|
8403
|
+
const accent = isFast ? "text-amber-600 dark:text-amber-400" : "text-blue-600 dark:text-blue-400";
|
|
8404
|
+
return /* @__PURE__ */ jsxs(
|
|
8405
|
+
"button",
|
|
8406
|
+
{
|
|
8407
|
+
role: "menuitem",
|
|
8408
|
+
type: "button",
|
|
8409
|
+
onClick: () => {
|
|
8410
|
+
void handleRegenerateWithModel(m.id);
|
|
8411
|
+
},
|
|
8412
|
+
className: "flex items-center gap-2 whitespace-nowrap rounded-md px-2.5 py-1.5 text-xs font-medium text-gray-700 transition-colors duration-150 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700",
|
|
8413
|
+
children: [
|
|
8414
|
+
/* @__PURE__ */ jsx(
|
|
8415
|
+
Icon,
|
|
8416
|
+
{
|
|
8417
|
+
size: 14,
|
|
8418
|
+
weight: "fill",
|
|
8419
|
+
className: accent
|
|
8420
|
+
}
|
|
8421
|
+
),
|
|
8422
|
+
/* @__PURE__ */ jsx("span", { children: t(m.label) })
|
|
8423
|
+
]
|
|
8424
|
+
},
|
|
8425
|
+
m.id
|
|
8426
|
+
);
|
|
8427
|
+
})
|
|
8428
|
+
}
|
|
8429
|
+
)
|
|
8430
|
+
] })
|
|
8073
8431
|
] })
|
|
8074
8432
|
)
|
|
8075
8433
|
}
|
|
@@ -8229,6 +8587,14 @@ function AssistantTurnView({
|
|
|
8229
8587
|
}) {
|
|
8230
8588
|
const { debugMode } = useChatSession();
|
|
8231
8589
|
const { handleCopy, handleRegenerate, pendingQuestion, sendMessage: sendMessage2, loading } = useChatMessaging();
|
|
8590
|
+
const iotaContext = useIotaContext();
|
|
8591
|
+
const regenerateModels = useMemo(() => {
|
|
8592
|
+
const models = iotaContext.extensions?.llm?.models;
|
|
8593
|
+
if (!models || models.length < 2) {
|
|
8594
|
+
return void 0;
|
|
8595
|
+
}
|
|
8596
|
+
return models.map((m) => ({ id: m.id, label: m.label }));
|
|
8597
|
+
}, [iotaContext.extensions?.llm?.models]);
|
|
8232
8598
|
const assistantTurn = turn.assistantTurn;
|
|
8233
8599
|
if (!assistantTurn) {
|
|
8234
8600
|
return null;
|
|
@@ -8257,6 +8623,7 @@ function AssistantTurnView({
|
|
|
8257
8623
|
classNames,
|
|
8258
8624
|
onCopy: handleCopy,
|
|
8259
8625
|
onRegenerate: allowRegenerate ? handleRegenerate : void 0,
|
|
8626
|
+
regenerateModels: allowRegenerate ? regenerateModels : void 0,
|
|
8260
8627
|
onSendMessage: sendMessage2,
|
|
8261
8628
|
sendDisabled: loading || isStreaming,
|
|
8262
8629
|
hideAvatar,
|
|
@@ -10557,8 +10924,6 @@ function SessionArtifactList({
|
|
|
10557
10924
|
}) })
|
|
10558
10925
|
] }, group.type)) });
|
|
10559
10926
|
}
|
|
10560
|
-
|
|
10561
|
-
// ui/src/bichat/components/SessionArtifactPreviewModal.tsx
|
|
10562
10927
|
init_useTranslation();
|
|
10563
10928
|
|
|
10564
10929
|
// ui/src/bichat/components/SessionArtifactPreview.tsx
|
|
@@ -10948,9 +11313,9 @@ function SessionArtifactPreviewModal({
|
|
|
10948
11313
|
if (!artifact) {
|
|
10949
11314
|
return null;
|
|
10950
11315
|
}
|
|
10951
|
-
return /* @__PURE__ */ jsxs(
|
|
10952
|
-
/* @__PURE__ */ jsx(
|
|
10953
|
-
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 overflow-y-auto p-4 lg:p-6", children: /* @__PURE__ */ jsx("div", { className: "mx-auto flex min-h-full w-full max-w-6xl items-center justify-center", children: /* @__PURE__ */ jsxs(
|
|
11316
|
+
return /* @__PURE__ */ jsxs(InlineDialog, { open: isOpen, onClose: handleClose, className: "relative z-50", children: [
|
|
11317
|
+
/* @__PURE__ */ jsx(InlineDialogBackdrop, { className: "fixed inset-0 bg-black/50 backdrop-blur-sm" }),
|
|
11318
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 overflow-y-auto p-4 lg:p-6", children: /* @__PURE__ */ jsx("div", { className: "mx-auto flex min-h-full w-full max-w-6xl items-center justify-center", children: /* @__PURE__ */ jsxs(InlineDialogPanel, { className: "flex max-h-[92vh] w-full flex-col overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-xl dark:border-gray-700 dark:bg-gray-900", children: [
|
|
10954
11319
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 border-b border-gray-200 px-4 py-3 dark:border-gray-700", children: [
|
|
10955
11320
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
10956
11321
|
isEditingName ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -11450,109 +11815,6 @@ function SessionArtifactsPanel({
|
|
|
11450
11815
|
}
|
|
11451
11816
|
);
|
|
11452
11817
|
}
|
|
11453
|
-
var DialogContext = createContext(null);
|
|
11454
|
-
var FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
11455
|
-
function InlineDialog({ open, onClose, className, children }) {
|
|
11456
|
-
const containerRef = useRef(null);
|
|
11457
|
-
const previousFocusRef = useRef(null);
|
|
11458
|
-
useEffect(() => {
|
|
11459
|
-
if (!open) {
|
|
11460
|
-
return;
|
|
11461
|
-
}
|
|
11462
|
-
previousFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
11463
|
-
const container = containerRef.current;
|
|
11464
|
-
if (!container) {
|
|
11465
|
-
return;
|
|
11466
|
-
}
|
|
11467
|
-
const getFocusable = () => Array.from(
|
|
11468
|
-
container.querySelectorAll(FOCUSABLE_SELECTOR)
|
|
11469
|
-
);
|
|
11470
|
-
const handler = (e) => {
|
|
11471
|
-
if (e.key === "Escape") {
|
|
11472
|
-
onClose();
|
|
11473
|
-
return;
|
|
11474
|
-
}
|
|
11475
|
-
if (e.key !== "Tab") {
|
|
11476
|
-
return;
|
|
11477
|
-
}
|
|
11478
|
-
const focusable = getFocusable();
|
|
11479
|
-
if (focusable.length === 0) {
|
|
11480
|
-
e.preventDefault();
|
|
11481
|
-
container.focus();
|
|
11482
|
-
return;
|
|
11483
|
-
}
|
|
11484
|
-
const first = focusable[0];
|
|
11485
|
-
const last = focusable[focusable.length - 1];
|
|
11486
|
-
if (e.shiftKey && document.activeElement === first) {
|
|
11487
|
-
e.preventDefault();
|
|
11488
|
-
last.focus();
|
|
11489
|
-
} else if (!e.shiftKey && document.activeElement === last) {
|
|
11490
|
-
e.preventDefault();
|
|
11491
|
-
first.focus();
|
|
11492
|
-
}
|
|
11493
|
-
};
|
|
11494
|
-
(getFocusable()[0] ?? container)?.focus();
|
|
11495
|
-
container.addEventListener("keydown", handler);
|
|
11496
|
-
return () => {
|
|
11497
|
-
container.removeEventListener("keydown", handler);
|
|
11498
|
-
previousFocusRef.current?.focus();
|
|
11499
|
-
};
|
|
11500
|
-
}, [open, onClose]);
|
|
11501
|
-
if (!open) {
|
|
11502
|
-
return null;
|
|
11503
|
-
}
|
|
11504
|
-
return /* @__PURE__ */ jsx(DialogContext.Provider, { value: onClose, children: /* @__PURE__ */ jsx(
|
|
11505
|
-
"div",
|
|
11506
|
-
{
|
|
11507
|
-
ref: containerRef,
|
|
11508
|
-
className,
|
|
11509
|
-
onClick: onClose,
|
|
11510
|
-
tabIndex: -1,
|
|
11511
|
-
children
|
|
11512
|
-
}
|
|
11513
|
-
) });
|
|
11514
|
-
}
|
|
11515
|
-
function InlineDialogBackdrop(props) {
|
|
11516
|
-
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", ...props });
|
|
11517
|
-
}
|
|
11518
|
-
function InlineDialogPanel({
|
|
11519
|
-
children,
|
|
11520
|
-
onClick,
|
|
11521
|
-
...rest
|
|
11522
|
-
}) {
|
|
11523
|
-
const ref = useRef(null);
|
|
11524
|
-
useEffect(() => {
|
|
11525
|
-
if (!ref.current) {
|
|
11526
|
-
return;
|
|
11527
|
-
}
|
|
11528
|
-
const target = ref.current.querySelector("[data-autofocus]") ?? ref.current.querySelector(
|
|
11529
|
-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
11530
|
-
);
|
|
11531
|
-
target?.focus();
|
|
11532
|
-
}, []);
|
|
11533
|
-
return /* @__PURE__ */ jsx(
|
|
11534
|
-
"div",
|
|
11535
|
-
{
|
|
11536
|
-
ref,
|
|
11537
|
-
role: "dialog",
|
|
11538
|
-
"aria-modal": "true",
|
|
11539
|
-
onClick: (e) => {
|
|
11540
|
-
e.stopPropagation();
|
|
11541
|
-
onClick?.(e);
|
|
11542
|
-
},
|
|
11543
|
-
...rest,
|
|
11544
|
-
children
|
|
11545
|
-
}
|
|
11546
|
-
);
|
|
11547
|
-
}
|
|
11548
|
-
function InlineDialogTitle(props) {
|
|
11549
|
-
return /* @__PURE__ */ jsx("h2", { ...props });
|
|
11550
|
-
}
|
|
11551
|
-
function InlineDialogDescription(props) {
|
|
11552
|
-
return /* @__PURE__ */ jsx("p", { ...props });
|
|
11553
|
-
}
|
|
11554
|
-
|
|
11555
|
-
// ui/src/bichat/components/SessionMembersModal.tsx
|
|
11556
11818
|
init_useTranslation();
|
|
11557
11819
|
init_useTranslation();
|
|
11558
11820
|
function ConfirmModalBase({
|
|
@@ -12439,7 +12701,7 @@ function ChatSessionCore({
|
|
|
12439
12701
|
"div",
|
|
12440
12702
|
{
|
|
12441
12703
|
ref: layoutContainerRef,
|
|
12442
|
-
className: "relative flex min-h-0 flex-1 overflow-
|
|
12704
|
+
className: "relative flex min-h-0 flex-1 overflow-clip",
|
|
12443
12705
|
children: [
|
|
12444
12706
|
/* @__PURE__ */ jsx("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: showWelcome ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col overflow-auto", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center px-4 py-8", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-5xl", children: [
|
|
12445
12707
|
welcomeSlot || /* @__PURE__ */ jsx(WelcomeContent_default, { onPromptSelect: handlePromptSelect, disabled: loading || composerDisabled }),
|
|
@@ -15891,61 +16153,6 @@ function useSidebarState() {
|
|
|
15891
16153
|
const toggleMobile = useCallback(() => setIsMobileOpen((v) => !v), []);
|
|
15892
16154
|
return { isMobile, isMobileOpen, openMobile, closeMobile, toggleMobile };
|
|
15893
16155
|
}
|
|
15894
|
-
function useFocusTrap(containerRef, isActive, restoreFocusOnDeactivate) {
|
|
15895
|
-
useEffect(() => {
|
|
15896
|
-
if (!isActive || !containerRef.current) {
|
|
15897
|
-
return;
|
|
15898
|
-
}
|
|
15899
|
-
const container = containerRef.current;
|
|
15900
|
-
const previouslyFocused = document.activeElement;
|
|
15901
|
-
const getFocusableElements = () => {
|
|
15902
|
-
const selector = [
|
|
15903
|
-
"button:not([disabled])",
|
|
15904
|
-
"[href]",
|
|
15905
|
-
"input:not([disabled])",
|
|
15906
|
-
"select:not([disabled])",
|
|
15907
|
-
"textarea:not([disabled])",
|
|
15908
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
15909
|
-
].join(", ");
|
|
15910
|
-
return Array.from(container.querySelectorAll(selector));
|
|
15911
|
-
};
|
|
15912
|
-
const focusableElements = getFocusableElements();
|
|
15913
|
-
if (focusableElements.length > 0) {
|
|
15914
|
-
focusableElements[0].focus();
|
|
15915
|
-
}
|
|
15916
|
-
const handleTabKey = (e) => {
|
|
15917
|
-
if (e.key !== "Tab") {
|
|
15918
|
-
return;
|
|
15919
|
-
}
|
|
15920
|
-
const focusableElements2 = getFocusableElements();
|
|
15921
|
-
if (focusableElements2.length === 0) {
|
|
15922
|
-
return;
|
|
15923
|
-
}
|
|
15924
|
-
const firstElement = focusableElements2[0];
|
|
15925
|
-
const lastElement = focusableElements2[focusableElements2.length - 1];
|
|
15926
|
-
if (e.shiftKey) {
|
|
15927
|
-
if (document.activeElement === firstElement) {
|
|
15928
|
-
e.preventDefault();
|
|
15929
|
-
lastElement.focus();
|
|
15930
|
-
}
|
|
15931
|
-
} else {
|
|
15932
|
-
if (document.activeElement === lastElement) {
|
|
15933
|
-
e.preventDefault();
|
|
15934
|
-
firstElement.focus();
|
|
15935
|
-
}
|
|
15936
|
-
}
|
|
15937
|
-
};
|
|
15938
|
-
container.addEventListener("keydown", handleTabKey);
|
|
15939
|
-
return () => {
|
|
15940
|
-
container.removeEventListener("keydown", handleTabKey);
|
|
15941
|
-
if (restoreFocusOnDeactivate) {
|
|
15942
|
-
restoreFocusOnDeactivate.focus();
|
|
15943
|
-
} else if (previouslyFocused instanceof HTMLElement) {
|
|
15944
|
-
previouslyFocused.focus();
|
|
15945
|
-
}
|
|
15946
|
-
};
|
|
15947
|
-
}, [containerRef, isActive, restoreFocusOnDeactivate]);
|
|
15948
|
-
}
|
|
15949
16156
|
|
|
15950
16157
|
// ui/src/bichat/components/BiChatLayout.tsx
|
|
15951
16158
|
init_useTranslation();
|
|
@@ -17195,18 +17402,6 @@ function useActiveRuns(dataSource, options = {}) {
|
|
|
17195
17402
|
|
|
17196
17403
|
// ui/src/bichat/index.ts
|
|
17197
17404
|
init_useTranslation();
|
|
17198
|
-
function useModalLock(isOpen) {
|
|
17199
|
-
useEffect(() => {
|
|
17200
|
-
if (!isOpen) {
|
|
17201
|
-
return;
|
|
17202
|
-
}
|
|
17203
|
-
const originalOverflow = document.body.style.overflow;
|
|
17204
|
-
document.body.style.overflow = "hidden";
|
|
17205
|
-
return () => {
|
|
17206
|
-
document.body.style.overflow = originalOverflow;
|
|
17207
|
-
};
|
|
17208
|
-
}, [isOpen]);
|
|
17209
|
-
}
|
|
17210
17405
|
function useImageGallery(options = {}) {
|
|
17211
17406
|
const { images: initialImages = [], wrap = false, onOpen, onClose, onNavigate } = options;
|
|
17212
17407
|
const [isOpen, setIsOpen] = useState(false);
|