opencami 1.9.0 → 1.9.1
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/client/assets/{CSPContext-TfUptlEu.js → CSPContext-B3PAVjBL.js} +1 -1
- package/dist/client/assets/{DirectionContext-CQMv7g2N.js → DirectionContext-CR5CCisG.js} +1 -1
- package/dist/client/assets/_sessionKey-Bg_9uype.js +23 -0
- package/dist/client/assets/agents-BiTHBb6Z.js +2 -0
- package/dist/client/assets/{agents-screen-fSZJpRi_.js → agents-screen--ZMzN5cB.js} +1 -1
- package/dist/client/assets/bots-DxhRnQp5.js +2 -0
- package/dist/client/assets/{bots-screen-4yT-e3cM.js → bots-screen-C_uJBNwI.js} +1 -1
- package/dist/client/assets/{button-DqP4GZwZ.js → button-BciDmec0.js} +1 -1
- package/dist/client/assets/{composite-BLgu_EOL.js → composite-DArWbFHm.js} +1 -1
- package/dist/client/assets/{connect-CiqRvR6s.js → connect-B48HecjN.js} +1 -1
- package/dist/client/assets/{dashboard-CyWDWpbj.js → dashboard-BVKx9FMy.js} +1 -1
- package/dist/client/assets/{event-2_Dxdv7h.js → event-BCwqPPkP.js} +1 -1
- package/dist/client/assets/{file-explorer-screen-CZ2QKk-0.js → file-explorer-screen-DPs-FWeA.js} +1 -1
- package/dist/client/assets/files-SEycwYCa.js +2 -0
- package/dist/client/assets/{follow-up-suggestions-Bi3Ci2my.js → follow-up-suggestions-BPjWBpiy.js} +1 -1
- package/dist/client/assets/{index-ygitKeM-.js → index-0gdwm1_H.js} +1 -1
- package/dist/client/assets/{index-C_gsW9fo.js → index-CGeJcqZ3.js} +1 -1
- package/dist/client/assets/{keyboard-shortcuts-dialog-z-amTZVi.js → keyboard-shortcuts-dialog-CK_XTzLr.js} +1 -1
- package/dist/client/assets/{main-ZBMVSJTF.js → main-B2CrcRuC.js} +3 -3
- package/dist/client/assets/{markdown-CHUjmWcv.js → markdown-CdkuX06F.js} +1 -1
- package/dist/client/assets/memory-C7lKdkmc.js +2 -0
- package/dist/client/assets/{memory-screen-C_ZNDGLd.js → memory-screen-C1RfLy-d.js} +1 -1
- package/dist/client/assets/{menu-CB88T7R1.js → menu-CIwnliij.js} +1 -1
- package/dist/client/assets/{opencami-logo-C0Kj1DiT.js → opencami-logo-SVuYD55V.js} +1 -1
- package/dist/client/assets/{proxy-D-juuhw6.js → proxy-BijR8W1L.js} +1 -1
- package/dist/client/assets/{react-Akh4y69S.js → react-DWx7OvUo.js} +1 -1
- package/dist/client/assets/{search-dialog-BasfzCyM.js → search-dialog-CB4KE8ec.js} +1 -1
- package/dist/client/assets/{search-sources-badge-DwFHWd7S.js → search-sources-badge-B8Z-8sSf.js} +1 -1
- package/dist/client/assets/{session-export-dialog-CAl3iJnD.js → session-export-dialog-tDiFuv3a.js} +1 -1
- package/dist/client/assets/{settings-dialog-C8OoRXwX.js → settings-dialog-aL-AH4Rt.js} +1 -1
- package/dist/client/assets/skills-D1T6uemU.js +2 -0
- package/dist/client/assets/{skills-panel-B7BRAofP.js → skills-panel-fjJQVMog.js} +1 -1
- package/dist/client/assets/{styles-CXa-SiWC.css → styles-D0L88B64.css} +1 -1
- package/dist/client/assets/{switch-DYEbEgy5.js → switch-Bn5uei2k.js} +1 -1
- package/dist/client/assets/{tabs-eiBvL0H7.js → tabs-DOBNAUVE.js} +1 -1
- package/dist/client/assets/{thinking-CariuioI.js → thinking-dfGrFAMV.js} +1 -1
- package/dist/client/assets/{tooltip-CekkGEYG.js → tooltip-DOKkNFvu.js} +1 -1
- package/dist/client/assets/{use-file-explorer-state-Dfyh4GwR.js → use-file-explorer-state-BAa6Cxyr.js} +1 -1
- package/dist/client/assets/{useBaseUiId-DLhdkHJl.js → useBaseUiId-DFpBD0sg.js} +1 -1
- package/dist/client/assets/{useCompositeItem-DTSTTR0Z.js → useCompositeItem-B-Axq9-D.js} +1 -1
- package/dist/client/assets/{useControlled-CpliTEve.js → useControlled-CQHE0ITz.js} +1 -1
- package/dist/client/assets/{useMutation-CpD2Pn0F.js → useMutation-BFl-7GnD.js} +1 -1
- package/dist/client/assets/{useOnFirstRender-DsFYFJoB.js → useOnFirstRender-DlXHIIGk.js} +1 -1
- package/dist/client/assets/{useQuery-DMTgpIql.js → useQuery-D-sF8Tld.js} +1 -1
- package/dist/server/assets/{_sessionKey-Bhksr7VP.js → _sessionKey-D8TGrDRM.js} +337 -132
- package/dist/server/assets/{_tanstack-start-manifest_v-D-5ReiD4.js → _tanstack-start-manifest_v-DalBo2bY.js} +1 -1
- package/dist/server/assets/{follow-up-suggestions-B3hol2KT.js → follow-up-suggestions-C65ptDij.js} +2 -2
- package/dist/server/assets/{index-4G_4vZNY.js → index-gRco4Ina.js} +1 -1
- package/dist/server/assets/{router-C9JRmWMm.js → router-DaKDqc9w.js} +12 -10
- package/dist/server/assets/{search-dialog-CTJULPB8.js → search-dialog-DSSK93kq.js} +2 -2
- package/dist/server/assets/{settings-dialog-B5yR2pBy.js → settings-dialog-DyWNblva.js} +2 -2
- package/dist/server/assets/{thinking-CHx4Oouj.js → thinking-CU0FRlzT.js} +2 -2
- package/dist/server/server.js +2 -2
- package/package.json +1 -1
- package/dist/client/assets/_sessionKey-DYknvaDS.js +0 -23
- package/dist/client/assets/agents-DNywJUai.js +0 -2
- package/dist/client/assets/bots-Bqjqhws8.js +0 -2
- package/dist/client/assets/files-Cbhud0J8.js +0 -2
- package/dist/client/assets/memory-BRa-0plj.js +0 -2
- package/dist/client/assets/skills-Cx12984a.js +0 -2
|
@@ -19,7 +19,7 @@ import { u as useChatSettings$1 } from "./index-B_F4DTUu.js";
|
|
|
19
19
|
import { createPortal } from "react-dom";
|
|
20
20
|
import { create } from "zustand";
|
|
21
21
|
import { persist } from "zustand/middleware";
|
|
22
|
-
import { a as Route } from "./router-
|
|
22
|
+
import { a as Route } from "./router-DaKDqc9w.js";
|
|
23
23
|
function deriveFriendlyIdFromKey(key) {
|
|
24
24
|
if (!key) return "main";
|
|
25
25
|
const trimmed = key.trim();
|
|
@@ -1686,7 +1686,7 @@ function areSidebarSessionsEqual(prev, next) {
|
|
|
1686
1686
|
return true;
|
|
1687
1687
|
}
|
|
1688
1688
|
const SettingsDialog = lazy(
|
|
1689
|
-
() => import("./settings-dialog-
|
|
1689
|
+
() => import("./settings-dialog-DyWNblva.js").then((m) => ({ default: m.SettingsDialog }))
|
|
1690
1690
|
);
|
|
1691
1691
|
const SessionExportDialog = lazy(
|
|
1692
1692
|
() => import("./session-export-dialog-CgtlOnwf.js").then((m) => ({
|
|
@@ -2833,7 +2833,7 @@ function Tool({ toolPart, defaultOpen = false }) {
|
|
|
2833
2833
|
] }) });
|
|
2834
2834
|
}
|
|
2835
2835
|
const Thinking = lazy(
|
|
2836
|
-
() => import("./thinking-
|
|
2836
|
+
() => import("./thinking-CU0FRlzT.js").then((m) => ({
|
|
2837
2837
|
default: m.Thinking
|
|
2838
2838
|
}))
|
|
2839
2839
|
);
|
|
@@ -3015,7 +3015,9 @@ function MessageItemComponent({
|
|
|
3015
3015
|
wrapperClassName,
|
|
3016
3016
|
wrapperScrollMarginTop,
|
|
3017
3017
|
messageDomId,
|
|
3018
|
-
highlighted = false
|
|
3018
|
+
highlighted = false,
|
|
3019
|
+
onRetry,
|
|
3020
|
+
onDismiss
|
|
3019
3021
|
}) {
|
|
3020
3022
|
const { settings } = useChatSettings$1();
|
|
3021
3023
|
const role = message.role || "assistant";
|
|
@@ -3023,6 +3025,7 @@ function MessageItemComponent({
|
|
|
3023
3025
|
const thinking = thinkingFromMessage(message);
|
|
3024
3026
|
const images = imagesFromMessage(message);
|
|
3025
3027
|
const isUser = role === "user";
|
|
3028
|
+
const isFailed = isUser && message.status === "error";
|
|
3026
3029
|
const imageDataUris = useMemo(
|
|
3027
3030
|
() => images.map(
|
|
3028
3031
|
(img) => `data:${img.source.media_type};base64,${img.source.data}`
|
|
@@ -3165,13 +3168,35 @@ function MessageItemComponent({
|
|
|
3165
3168
|
className: cn(
|
|
3166
3169
|
"text-primary-900 opencami-text-size min-w-0 max-w-full",
|
|
3167
3170
|
isUser ? "opencami-message-user bg-primary-100 px-4 py-[var(--opencami-user-bubble-py)] max-w-[85%]" : "opencami-message-assistant bg-transparent w-full",
|
|
3168
|
-
!isUser && isStreaming && "stream-fade-in"
|
|
3171
|
+
!isUser && isStreaming && "stream-fade-in",
|
|
3172
|
+
isFailed && "opacity-60"
|
|
3169
3173
|
),
|
|
3170
3174
|
children: displayText
|
|
3171
3175
|
}
|
|
3172
3176
|
)
|
|
3173
3177
|
}
|
|
3174
3178
|
),
|
|
3179
|
+
isFailed && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-red-500 dark:text-red-400", children: [
|
|
3180
|
+
/* @__PURE__ */ jsx("span", { children: "Failed to send" }),
|
|
3181
|
+
onRetry && /* @__PURE__ */ jsx(
|
|
3182
|
+
"button",
|
|
3183
|
+
{
|
|
3184
|
+
type: "button",
|
|
3185
|
+
className: "underline hover:text-red-700 dark:hover:text-red-300",
|
|
3186
|
+
onClick: () => onRetry(message),
|
|
3187
|
+
children: "Retry"
|
|
3188
|
+
}
|
|
3189
|
+
),
|
|
3190
|
+
onDismiss && /* @__PURE__ */ jsx(
|
|
3191
|
+
"button",
|
|
3192
|
+
{
|
|
3193
|
+
type: "button",
|
|
3194
|
+
className: "underline hover:text-red-700 dark:hover:text-red-300",
|
|
3195
|
+
onClick: () => onDismiss(message),
|
|
3196
|
+
children: "Dismiss"
|
|
3197
|
+
}
|
|
3198
|
+
)
|
|
3199
|
+
] }),
|
|
3175
3200
|
hasToolCalls && settings.showToolMessages && /* @__PURE__ */ jsx("div", { className: "mt-2 flex w-full min-w-0 max-w-[var(--opencami-chat-width)] flex-col gap-3 overflow-x-hidden", children: toolCalls.map((toolCall) => {
|
|
3176
3201
|
const resultMessage = toolCall.id ? toolResultsByCallId?.get(toolCall.id) : void 0;
|
|
3177
3202
|
const toolPart = mapToolCallToToolPart(toolCall, resultMessage);
|
|
@@ -3213,6 +3238,9 @@ function areMessagesEqual(prevProps, nextProps) {
|
|
|
3213
3238
|
}
|
|
3214
3239
|
if (prevProps.messageDomId !== nextProps.messageDomId) return false;
|
|
3215
3240
|
if (prevProps.highlighted !== nextProps.highlighted) return false;
|
|
3241
|
+
if (prevProps.onRetry !== nextProps.onRetry) return false;
|
|
3242
|
+
if (prevProps.onDismiss !== nextProps.onDismiss) return false;
|
|
3243
|
+
if (prevProps.message.status !== nextProps.message.status) return false;
|
|
3216
3244
|
if ((prevProps.message.role || "assistant") !== (nextProps.message.role || "assistant")) {
|
|
3217
3245
|
return false;
|
|
3218
3246
|
}
|
|
@@ -3474,7 +3502,7 @@ function TypingIndicator({ className }) {
|
|
|
3474
3502
|
] });
|
|
3475
3503
|
}
|
|
3476
3504
|
const FollowUpSuggestions = lazy(
|
|
3477
|
-
() => import("./follow-up-suggestions-
|
|
3505
|
+
() => import("./follow-up-suggestions-C65ptDij.js").then((m) => ({
|
|
3478
3506
|
default: m.FollowUpSuggestions
|
|
3479
3507
|
}))
|
|
3480
3508
|
);
|
|
@@ -3493,7 +3521,9 @@ function ChatMessageListComponent({
|
|
|
3493
3521
|
headerHeight,
|
|
3494
3522
|
contentStyle,
|
|
3495
3523
|
onFollowUpClick,
|
|
3496
|
-
jumpToMessageId
|
|
3524
|
+
jumpToMessageId,
|
|
3525
|
+
onRetryMessage,
|
|
3526
|
+
onDismissMessage
|
|
3497
3527
|
}) {
|
|
3498
3528
|
const anchorRef = useRef(null);
|
|
3499
3529
|
const lastUserRef = useRef(null);
|
|
@@ -3689,7 +3719,9 @@ function ChatMessageListComponent({
|
|
|
3689
3719
|
isLastAssistant,
|
|
3690
3720
|
aggregatedSearchSources: isLastAssistant ? aggregatedSearchSources : void 0,
|
|
3691
3721
|
messageDomId: messageId ? `message-${messageId}` : void 0,
|
|
3692
|
-
highlighted: highlightedMessageId === messageId
|
|
3722
|
+
highlighted: highlightedMessageId === messageId,
|
|
3723
|
+
onRetry: onRetryMessage,
|
|
3724
|
+
onDismiss: onDismissMessage
|
|
3693
3725
|
},
|
|
3694
3726
|
messageKey
|
|
3695
3727
|
);
|
|
@@ -3723,7 +3755,9 @@ function ChatMessageListComponent({
|
|
|
3723
3755
|
wrapperClassName,
|
|
3724
3756
|
wrapperScrollMarginTop,
|
|
3725
3757
|
messageDomId: messageId ? `message-${messageId}` : void 0,
|
|
3726
|
-
highlighted: highlightedMessageId === messageId
|
|
3758
|
+
highlighted: highlightedMessageId === messageId,
|
|
3759
|
+
onRetry: onRetryMessage,
|
|
3760
|
+
onDismiss: onDismissMessage
|
|
3727
3761
|
},
|
|
3728
3762
|
messageKey
|
|
3729
3763
|
);
|
|
@@ -3757,7 +3791,9 @@ function ChatMessageListComponent({
|
|
|
3757
3791
|
isLastAssistant,
|
|
3758
3792
|
aggregatedSearchSources: isLastAssistant ? aggregatedSearchSources : void 0,
|
|
3759
3793
|
messageDomId: messageId ? `message-${messageId}` : void 0,
|
|
3760
|
-
highlighted: highlightedMessageId === messageId
|
|
3794
|
+
highlighted: highlightedMessageId === messageId,
|
|
3795
|
+
onRetry: onRetryMessage,
|
|
3796
|
+
onDismiss: onDismissMessage
|
|
3761
3797
|
},
|
|
3762
3798
|
messageKey
|
|
3763
3799
|
);
|
|
@@ -3782,7 +3818,7 @@ function ChatMessageListComponent({
|
|
|
3782
3818
|
);
|
|
3783
3819
|
}
|
|
3784
3820
|
function areChatMessageListEqual(prev, next) {
|
|
3785
|
-
return prev.messages === next.messages && prev.loading === next.loading && prev.empty === next.empty && prev.emptyState === next.emptyState && prev.notice === next.notice && prev.noticePosition === next.noticePosition && prev.waitingForResponse === next.waitingForResponse && prev.isStreaming === next.isStreaming && prev.sessionKey === next.sessionKey && prev.pinToTop === next.pinToTop && prev.pinGroupMinHeight === next.pinGroupMinHeight && prev.headerHeight === next.headerHeight && prev.contentStyle === next.contentStyle && prev.onFollowUpClick === next.onFollowUpClick && prev.jumpToMessageId === next.jumpToMessageId;
|
|
3821
|
+
return prev.messages === next.messages && prev.loading === next.loading && prev.empty === next.empty && prev.emptyState === next.emptyState && prev.notice === next.notice && prev.noticePosition === next.noticePosition && prev.waitingForResponse === next.waitingForResponse && prev.isStreaming === next.isStreaming && prev.sessionKey === next.sessionKey && prev.pinToTop === next.pinToTop && prev.pinGroupMinHeight === next.pinGroupMinHeight && prev.headerHeight === next.headerHeight && prev.contentStyle === next.contentStyle && prev.onFollowUpClick === next.onFollowUpClick && prev.jumpToMessageId === next.jumpToMessageId && prev.onRetryMessage === next.onRetryMessage && prev.onDismissMessage === next.onDismissMessage;
|
|
3786
3822
|
}
|
|
3787
3823
|
const MemoizedChatMessageList = memo(
|
|
3788
3824
|
ChatMessageListComponent,
|
|
@@ -5450,13 +5486,20 @@ function useChatHistory({
|
|
|
5450
5486
|
if (message.__optimisticId) return true;
|
|
5451
5487
|
return Boolean(message.clientId);
|
|
5452
5488
|
}) : [];
|
|
5489
|
+
const cachedMessages = Array.isArray(cached?.messages) ? cached.messages : [];
|
|
5453
5490
|
const serverData = await fetchHistory({
|
|
5454
5491
|
sessionKey: sessionKeyForHistory,
|
|
5455
5492
|
friendlyId: activeFriendlyId
|
|
5456
5493
|
});
|
|
5457
|
-
|
|
5458
|
-
const merged = mergeOptimisticHistoryMessages(
|
|
5494
|
+
const serverMessages = restoreCachedImageParts(
|
|
5459
5495
|
serverData.messages,
|
|
5496
|
+
cachedMessages
|
|
5497
|
+
);
|
|
5498
|
+
if (!optimisticMessages.length) {
|
|
5499
|
+
return { ...serverData, messages: serverMessages };
|
|
5500
|
+
}
|
|
5501
|
+
const merged = mergeOptimisticHistoryMessages(
|
|
5502
|
+
serverMessages,
|
|
5460
5503
|
optimisticMessages
|
|
5461
5504
|
);
|
|
5462
5505
|
return {
|
|
@@ -5502,30 +5545,101 @@ function useChatHistory({
|
|
|
5502
5545
|
sessionKeyForHistory
|
|
5503
5546
|
};
|
|
5504
5547
|
}
|
|
5505
|
-
function
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5548
|
+
function findMatchIndex(serverMessages, optimisticMessage) {
|
|
5549
|
+
return serverMessages.findIndex((serverMessage) => {
|
|
5550
|
+
if (optimisticMessage.clientId && serverMessage.clientId && optimisticMessage.clientId === serverMessage.clientId) {
|
|
5551
|
+
return true;
|
|
5552
|
+
}
|
|
5553
|
+
if (optimisticMessage.__optimisticId && serverMessage.__optimisticId && optimisticMessage.__optimisticId === serverMessage.__optimisticId) {
|
|
5554
|
+
return true;
|
|
5555
|
+
}
|
|
5556
|
+
if (optimisticMessage.role && serverMessage.role) {
|
|
5557
|
+
if (optimisticMessage.role !== serverMessage.role) return false;
|
|
5558
|
+
}
|
|
5559
|
+
const optimisticText = textFromMessage(optimisticMessage);
|
|
5560
|
+
if (!optimisticText) return false;
|
|
5561
|
+
if (optimisticText !== textFromMessage(serverMessage)) return false;
|
|
5562
|
+
const optimisticTime = getMessageTimestamp(optimisticMessage);
|
|
5563
|
+
const serverTime = getMessageTimestamp(serverMessage);
|
|
5564
|
+
return Math.abs(optimisticTime - serverTime) <= 1e4;
|
|
5565
|
+
});
|
|
5566
|
+
}
|
|
5567
|
+
function getImageParts(message) {
|
|
5568
|
+
if (!Array.isArray(message.content)) return [];
|
|
5569
|
+
return message.content.filter((part) => {
|
|
5570
|
+
if (typeof part !== "object" || part === null) return false;
|
|
5571
|
+
const p = part;
|
|
5572
|
+
if (p.type !== "image") return false;
|
|
5573
|
+
const source = p.source;
|
|
5574
|
+
return typeof source?.data === "string" && source.data.length > 0;
|
|
5575
|
+
});
|
|
5576
|
+
}
|
|
5577
|
+
function restoreCachedImageParts(serverMessages, cachedMessages) {
|
|
5578
|
+
const cachedMessagesWithImages = cachedMessages.filter(
|
|
5579
|
+
(message) => getImageParts(message).length > 0
|
|
5580
|
+
);
|
|
5581
|
+
if (!cachedMessagesWithImages.length) return serverMessages;
|
|
5582
|
+
return serverMessages.map((serverMessage) => {
|
|
5583
|
+
if (getImageParts(serverMessage).length > 0) return serverMessage;
|
|
5584
|
+
const cachedMatch = cachedMessagesWithImages.find((cachedMessage) => {
|
|
5585
|
+
if (serverMessage.role !== cachedMessage.role) return false;
|
|
5586
|
+
if (serverMessage.id && cachedMessage.id && serverMessage.id === cachedMessage.id) {
|
|
5511
5587
|
return true;
|
|
5512
5588
|
}
|
|
5513
|
-
if (
|
|
5589
|
+
if (serverMessage.clientId && cachedMessage.clientId && serverMessage.clientId === cachedMessage.clientId) {
|
|
5514
5590
|
return true;
|
|
5515
5591
|
}
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
const
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
const serverTime = getMessageTimestamp(serverMessage);
|
|
5524
|
-
return Math.abs(optimisticTime - serverTime) <= 1e4;
|
|
5592
|
+
const serverText = textFromMessage(serverMessage);
|
|
5593
|
+
const cachedText = textFromMessage(cachedMessage);
|
|
5594
|
+
if (!serverText || serverText !== cachedText) return false;
|
|
5595
|
+
const timeDiff = Math.abs(
|
|
5596
|
+
getMessageTimestamp(serverMessage) - getMessageTimestamp(cachedMessage)
|
|
5597
|
+
);
|
|
5598
|
+
return timeDiff <= 3e4;
|
|
5525
5599
|
});
|
|
5526
|
-
if (!
|
|
5600
|
+
if (!cachedMatch) return serverMessage;
|
|
5601
|
+
const imageParts = getImageParts(cachedMatch);
|
|
5602
|
+
if (!imageParts.length) return serverMessage;
|
|
5603
|
+
return {
|
|
5604
|
+
...serverMessage,
|
|
5605
|
+
content: [
|
|
5606
|
+
...imageParts,
|
|
5607
|
+
...Array.isArray(serverMessage.content) ? serverMessage.content : []
|
|
5608
|
+
]
|
|
5609
|
+
};
|
|
5610
|
+
});
|
|
5611
|
+
}
|
|
5612
|
+
function mergeOptimisticHistoryMessages(serverMessages, optimisticMessages) {
|
|
5613
|
+
if (!optimisticMessages.length) return serverMessages;
|
|
5614
|
+
const merged = [...serverMessages];
|
|
5615
|
+
for (const optimisticMessage of optimisticMessages) {
|
|
5616
|
+
const matchIndex = findMatchIndex(merged, optimisticMessage);
|
|
5617
|
+
if (matchIndex === -1) {
|
|
5527
5618
|
merged.push(optimisticMessage);
|
|
5619
|
+
continue;
|
|
5528
5620
|
}
|
|
5621
|
+
const imageParts = getImageParts(optimisticMessage);
|
|
5622
|
+
const serverMessage = merged[matchIndex];
|
|
5623
|
+
const serverImageParts = getImageParts(serverMessage);
|
|
5624
|
+
const needsImages = imageParts.length > 0 && serverImageParts.length === 0;
|
|
5625
|
+
const needsOptimisticId = Boolean(
|
|
5626
|
+
optimisticMessage.__optimisticId && !serverMessage.__optimisticId
|
|
5627
|
+
);
|
|
5628
|
+
const needsClientId = Boolean(
|
|
5629
|
+
optimisticMessage.clientId && !serverMessage.clientId
|
|
5630
|
+
);
|
|
5631
|
+
if (!needsImages && !needsOptimisticId && !needsClientId) continue;
|
|
5632
|
+
merged[matchIndex] = {
|
|
5633
|
+
...serverMessage,
|
|
5634
|
+
...needsOptimisticId ? { __optimisticId: optimisticMessage.__optimisticId } : {},
|
|
5635
|
+
...needsClientId ? { clientId: optimisticMessage.clientId } : {},
|
|
5636
|
+
...needsImages ? {
|
|
5637
|
+
content: [
|
|
5638
|
+
...imageParts,
|
|
5639
|
+
...Array.isArray(serverMessage.content) ? serverMessage.content : []
|
|
5640
|
+
]
|
|
5641
|
+
} : {}
|
|
5642
|
+
};
|
|
5529
5643
|
}
|
|
5530
5644
|
return merged;
|
|
5531
5645
|
}
|
|
@@ -5902,6 +6016,101 @@ function generateHeuristicTitle(message) {
|
|
|
5902
6016
|
function useLlmTitlesEnabled() {
|
|
5903
6017
|
return useLlmSettingsStore((state) => state.settings.useLlmTitles);
|
|
5904
6018
|
}
|
|
6019
|
+
function handleAgentEvent(payload, fallbackSessionKey, options) {
|
|
6020
|
+
const agentPayload = asRecord(payload);
|
|
6021
|
+
const stream = normalizeString(agentPayload?.stream);
|
|
6022
|
+
const runId = normalizeString(agentPayload?.runId);
|
|
6023
|
+
const sessionKey = normalizeString(agentPayload?.sessionKey) || fallbackSessionKey;
|
|
6024
|
+
const streamData = asRecord(agentPayload?.data);
|
|
6025
|
+
if (runId) {
|
|
6026
|
+
options.anyRunSeen.current = true;
|
|
6027
|
+
if (stream === "lifecycle") {
|
|
6028
|
+
const phase = normalizeString(streamData?.phase);
|
|
6029
|
+
if (phase === "end" || phase === "error" || phase === "abort") {
|
|
6030
|
+
options.activeRuns.delete(runId);
|
|
6031
|
+
} else if (phase) {
|
|
6032
|
+
options.activeRuns.add(runId);
|
|
6033
|
+
}
|
|
6034
|
+
} else {
|
|
6035
|
+
options.activeRuns.add(runId);
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
6038
|
+
if (stream === "assistant") {
|
|
6039
|
+
const text = normalizeString(streamData?.delta) || normalizeString(streamData?.text);
|
|
6040
|
+
if (!text) return;
|
|
6041
|
+
options.setState((prev) => {
|
|
6042
|
+
const blocks = [...prev.contentBlocks];
|
|
6043
|
+
const lastBlock = blocks[blocks.length - 1];
|
|
6044
|
+
if (lastBlock?.kind === "text") {
|
|
6045
|
+
blocks[blocks.length - 1] = { ...lastBlock, text: lastBlock.text + text };
|
|
6046
|
+
} else {
|
|
6047
|
+
blocks.push({ kind: "text", text });
|
|
6048
|
+
}
|
|
6049
|
+
return {
|
|
6050
|
+
...prev,
|
|
6051
|
+
sessionKey,
|
|
6052
|
+
text: prev.text + text,
|
|
6053
|
+
contentBlocks: blocks
|
|
6054
|
+
};
|
|
6055
|
+
});
|
|
6056
|
+
options.onAssistantDelta?.({ text, sessionKey });
|
|
6057
|
+
return;
|
|
6058
|
+
}
|
|
6059
|
+
if (!stream.includes("tool")) return;
|
|
6060
|
+
const toolId = normalizeString(streamData?.toolCallId) || normalizeString(streamData?.id) || normalizeString(streamData?.callId) || `${runId || "tool"}:${normalizeString(streamData?.toolName) || normalizeString(streamData?.name) || "unknown"}`;
|
|
6061
|
+
const toolName = normalizeString(streamData?.toolName) || normalizeString(streamData?.name) || "Tool";
|
|
6062
|
+
const toolStatus = deriveToolStatus(stream, streamData);
|
|
6063
|
+
const toolArgs = asRecord(streamData?.arguments) || asRecord(streamData?.input) || asRecord(streamData?.params) || null;
|
|
6064
|
+
const toolOutput = normalizeString(streamData?.result) || normalizeString(streamData?.output) || (stream.includes("result") ? normalizeString(streamData?.text) : "");
|
|
6065
|
+
options.setState((prev) => {
|
|
6066
|
+
const tools = [...prev.tools];
|
|
6067
|
+
const toolIndex = tools.findIndex((tool) => tool.id === toolId);
|
|
6068
|
+
const nextTool = { id: toolId, name: toolName, status: toolStatus };
|
|
6069
|
+
if (toolIndex >= 0) {
|
|
6070
|
+
tools[toolIndex] = nextTool;
|
|
6071
|
+
} else {
|
|
6072
|
+
tools.push(nextTool);
|
|
6073
|
+
}
|
|
6074
|
+
const blocks = [...prev.contentBlocks];
|
|
6075
|
+
const blockIndex = blocks.findIndex(
|
|
6076
|
+
(b) => b.kind === "tool" && b.id === toolId
|
|
6077
|
+
);
|
|
6078
|
+
const existingBlock = blockIndex >= 0 ? blocks[blockIndex] : null;
|
|
6079
|
+
const nextBlock = {
|
|
6080
|
+
kind: "tool",
|
|
6081
|
+
name: toolName,
|
|
6082
|
+
id: toolId,
|
|
6083
|
+
status: toolStatus,
|
|
6084
|
+
// Merge: keep existing arguments/output if new event doesn't carry them
|
|
6085
|
+
arguments: toolArgs ?? existingBlock?.arguments,
|
|
6086
|
+
output: toolOutput || existingBlock?.output || void 0
|
|
6087
|
+
};
|
|
6088
|
+
if (blockIndex >= 0) {
|
|
6089
|
+
blocks[blockIndex] = nextBlock;
|
|
6090
|
+
} else {
|
|
6091
|
+
blocks.push(nextBlock);
|
|
6092
|
+
}
|
|
6093
|
+
return {
|
|
6094
|
+
...prev,
|
|
6095
|
+
sessionKey,
|
|
6096
|
+
tools,
|
|
6097
|
+
contentBlocks: blocks
|
|
6098
|
+
};
|
|
6099
|
+
});
|
|
6100
|
+
}
|
|
6101
|
+
function deriveToolStatus(stream, data) {
|
|
6102
|
+
const explicitStatus = normalizeString(data?.phase) || normalizeString(data?.status) || normalizeString(data?.state);
|
|
6103
|
+
if (explicitStatus) return explicitStatus;
|
|
6104
|
+
if (stream.includes("result") || stream.includes("output")) return "done";
|
|
6105
|
+
if (stream.includes("call")) return "running";
|
|
6106
|
+
return "running";
|
|
6107
|
+
}
|
|
6108
|
+
function asRecord(value) {
|
|
6109
|
+
return value && typeof value === "object" ? value : null;
|
|
6110
|
+
}
|
|
6111
|
+
function normalizeString(value) {
|
|
6112
|
+
return typeof value === "string" ? value.trim() : "";
|
|
6113
|
+
}
|
|
5905
6114
|
const INITIAL_STATE = {
|
|
5906
6115
|
active: false,
|
|
5907
6116
|
text: "",
|
|
@@ -6018,101 +6227,6 @@ function useStreaming(options) {
|
|
|
6018
6227
|
}, []);
|
|
6019
6228
|
return { streaming: state, startStream: start, stopStream: stop };
|
|
6020
6229
|
}
|
|
6021
|
-
function handleAgentEvent(payload, fallbackSessionKey, options) {
|
|
6022
|
-
const agentPayload = asRecord(payload);
|
|
6023
|
-
const stream = normalizeString(agentPayload?.stream);
|
|
6024
|
-
const runId = normalizeString(agentPayload?.runId);
|
|
6025
|
-
const sessionKey = normalizeString(agentPayload?.sessionKey) || fallbackSessionKey;
|
|
6026
|
-
const streamData = asRecord(agentPayload?.data);
|
|
6027
|
-
if (runId) {
|
|
6028
|
-
options.anyRunSeen.current = true;
|
|
6029
|
-
if (stream === "lifecycle") {
|
|
6030
|
-
const phase = normalizeString(streamData?.phase);
|
|
6031
|
-
if (phase === "end" || phase === "error" || phase === "abort") {
|
|
6032
|
-
options.activeRuns.delete(runId);
|
|
6033
|
-
} else if (phase) {
|
|
6034
|
-
options.activeRuns.add(runId);
|
|
6035
|
-
}
|
|
6036
|
-
} else {
|
|
6037
|
-
options.activeRuns.add(runId);
|
|
6038
|
-
}
|
|
6039
|
-
}
|
|
6040
|
-
if (stream === "assistant") {
|
|
6041
|
-
const text = normalizeString(streamData?.delta) || normalizeString(streamData?.text);
|
|
6042
|
-
if (!text) return;
|
|
6043
|
-
options.setState((prev) => {
|
|
6044
|
-
const blocks = [...prev.contentBlocks];
|
|
6045
|
-
const lastBlock = blocks[blocks.length - 1];
|
|
6046
|
-
if (lastBlock?.kind === "text") {
|
|
6047
|
-
blocks[blocks.length - 1] = { ...lastBlock, text: lastBlock.text + text };
|
|
6048
|
-
} else {
|
|
6049
|
-
blocks.push({ kind: "text", text });
|
|
6050
|
-
}
|
|
6051
|
-
return {
|
|
6052
|
-
...prev,
|
|
6053
|
-
sessionKey,
|
|
6054
|
-
text: prev.text + text,
|
|
6055
|
-
contentBlocks: blocks
|
|
6056
|
-
};
|
|
6057
|
-
});
|
|
6058
|
-
options.onAssistantDelta?.({ text, sessionKey });
|
|
6059
|
-
return;
|
|
6060
|
-
}
|
|
6061
|
-
if (!stream.includes("tool")) return;
|
|
6062
|
-
const toolId = normalizeString(streamData?.toolCallId) || normalizeString(streamData?.id) || normalizeString(streamData?.callId) || `${runId || "tool"}:${normalizeString(streamData?.toolName) || normalizeString(streamData?.name) || "unknown"}`;
|
|
6063
|
-
const toolName = normalizeString(streamData?.toolName) || normalizeString(streamData?.name) || "Tool";
|
|
6064
|
-
const toolStatus = deriveToolStatus(stream, streamData);
|
|
6065
|
-
const toolArgs = asRecord(streamData?.arguments) || asRecord(streamData?.input) || asRecord(streamData?.params) || null;
|
|
6066
|
-
const toolOutput = normalizeString(streamData?.result) || normalizeString(streamData?.output) || (stream.includes("result") ? normalizeString(streamData?.text) : "");
|
|
6067
|
-
options.setState((prev) => {
|
|
6068
|
-
const tools = [...prev.tools];
|
|
6069
|
-
const toolIndex = tools.findIndex((tool) => tool.id === toolId);
|
|
6070
|
-
const nextTool = { id: toolId, name: toolName, status: toolStatus };
|
|
6071
|
-
if (toolIndex >= 0) {
|
|
6072
|
-
tools[toolIndex] = nextTool;
|
|
6073
|
-
} else {
|
|
6074
|
-
tools.push(nextTool);
|
|
6075
|
-
}
|
|
6076
|
-
const blocks = [...prev.contentBlocks];
|
|
6077
|
-
const blockIndex = blocks.findIndex(
|
|
6078
|
-
(b) => b.kind === "tool" && b.id === toolId
|
|
6079
|
-
);
|
|
6080
|
-
const existingBlock = blockIndex >= 0 ? blocks[blockIndex] : null;
|
|
6081
|
-
const nextBlock = {
|
|
6082
|
-
kind: "tool",
|
|
6083
|
-
name: toolName,
|
|
6084
|
-
id: toolId,
|
|
6085
|
-
status: toolStatus,
|
|
6086
|
-
// Merge: keep existing arguments/output if new event doesn't carry them
|
|
6087
|
-
arguments: toolArgs ?? existingBlock?.arguments,
|
|
6088
|
-
output: toolOutput || existingBlock?.output || void 0
|
|
6089
|
-
};
|
|
6090
|
-
if (blockIndex >= 0) {
|
|
6091
|
-
blocks[blockIndex] = nextBlock;
|
|
6092
|
-
} else {
|
|
6093
|
-
blocks.push(nextBlock);
|
|
6094
|
-
}
|
|
6095
|
-
return {
|
|
6096
|
-
...prev,
|
|
6097
|
-
sessionKey,
|
|
6098
|
-
tools,
|
|
6099
|
-
contentBlocks: blocks
|
|
6100
|
-
};
|
|
6101
|
-
});
|
|
6102
|
-
}
|
|
6103
|
-
function deriveToolStatus(stream, data) {
|
|
6104
|
-
const explicitStatus = normalizeString(data?.phase) || normalizeString(data?.status) || normalizeString(data?.state);
|
|
6105
|
-
if (explicitStatus) return explicitStatus;
|
|
6106
|
-
if (stream.includes("result") || stream.includes("output")) return "done";
|
|
6107
|
-
if (stream.includes("call")) return "running";
|
|
6108
|
-
return "running";
|
|
6109
|
-
}
|
|
6110
|
-
function asRecord(value) {
|
|
6111
|
-
return value && typeof value === "object" ? value : null;
|
|
6112
|
-
}
|
|
6113
|
-
function normalizeString(value) {
|
|
6114
|
-
return typeof value === "string" ? value.trim() : "";
|
|
6115
|
-
}
|
|
6116
6230
|
function useKeyboardShortcuts(handlers) {
|
|
6117
6231
|
const handleKeyDown = useCallback(
|
|
6118
6232
|
(event) => {
|
|
@@ -6324,11 +6438,32 @@ const KeyboardShortcutsDialog = lazy(
|
|
|
6324
6438
|
}))
|
|
6325
6439
|
);
|
|
6326
6440
|
const SearchDialog = lazy(
|
|
6327
|
-
() => import("./search-dialog-
|
|
6441
|
+
() => import("./search-dialog-DSSK93kq.js").then((m) => ({
|
|
6328
6442
|
default: m.SearchDialog
|
|
6329
6443
|
}))
|
|
6330
6444
|
);
|
|
6331
6445
|
const SEARCH_JUMP_TARGET_KEY = "opencami-search-jump-target";
|
|
6446
|
+
function extractRetryImageAttachments(message) {
|
|
6447
|
+
const parts = Array.isArray(message.content) ? message.content : [];
|
|
6448
|
+
const attachments = [];
|
|
6449
|
+
const payload = [];
|
|
6450
|
+
for (const [index, part] of parts.entries()) {
|
|
6451
|
+
if (part.type !== "image" || !("source" in part) || typeof part.source?.data !== "string" || part.source.data.length === 0) {
|
|
6452
|
+
continue;
|
|
6453
|
+
}
|
|
6454
|
+
const mimeType = typeof part.source?.media_type === "string" && part.source.media_type.length > 0 ? part.source.media_type : "image/jpeg";
|
|
6455
|
+
const content = part.source.data;
|
|
6456
|
+
attachments.push({
|
|
6457
|
+
id: crypto.randomUUID(),
|
|
6458
|
+
file: new File([], `retry-attachment-${index + 1}`, { type: mimeType }),
|
|
6459
|
+
preview: null,
|
|
6460
|
+
type: "image",
|
|
6461
|
+
base64: content
|
|
6462
|
+
});
|
|
6463
|
+
payload.push({ mimeType, content });
|
|
6464
|
+
}
|
|
6465
|
+
return { attachments, payload };
|
|
6466
|
+
}
|
|
6332
6467
|
function ChatScreen({
|
|
6333
6468
|
activeFriendlyId,
|
|
6334
6469
|
isNewChat = false,
|
|
@@ -6808,7 +6943,7 @@ function ChatScreen({
|
|
|
6808
6943
|
queryClient,
|
|
6809
6944
|
resolvedSessionKey
|
|
6810
6945
|
]);
|
|
6811
|
-
function sendMessage(sessionKey, friendlyId, body, skipOptimistic = false, attachments, model) {
|
|
6946
|
+
function sendMessage(sessionKey, friendlyId, body, skipOptimistic = false, attachments, model, retryAttachmentsPayload) {
|
|
6812
6947
|
let optimisticClientId = "";
|
|
6813
6948
|
if (!skipOptimistic) {
|
|
6814
6949
|
const { clientId, optimisticMessage } = createOptimisticMessage(
|
|
@@ -6834,10 +6969,14 @@ function ChatScreen({
|
|
|
6834
6969
|
setError(null);
|
|
6835
6970
|
setWaitingForResponse(true);
|
|
6836
6971
|
setPinToTop(true);
|
|
6837
|
-
const attachmentsPayload = attachments?.
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6972
|
+
const attachmentsPayload = retryAttachmentsPayload ?? attachments?.flatMap(
|
|
6973
|
+
(a) => a.base64 ? [
|
|
6974
|
+
{
|
|
6975
|
+
mimeType: a.file.type,
|
|
6976
|
+
content: a.base64
|
|
6977
|
+
}
|
|
6978
|
+
] : []
|
|
6979
|
+
);
|
|
6841
6980
|
streamingNotificationTextRef.current = "";
|
|
6842
6981
|
streamStart();
|
|
6843
6982
|
const preStreamKey = sessionKey || friendlyId;
|
|
@@ -7006,6 +7145,70 @@ function ChatScreen({
|
|
|
7006
7145
|
return { ...state, isSidebarCollapsed: false };
|
|
7007
7146
|
});
|
|
7008
7147
|
}, [queryClient]);
|
|
7148
|
+
const handleRetryMessage = useCallback(
|
|
7149
|
+
(message) => {
|
|
7150
|
+
const messageText = textFromMessage(message);
|
|
7151
|
+
const {
|
|
7152
|
+
attachments: retryAttachments,
|
|
7153
|
+
payload: retryAttachmentsPayload
|
|
7154
|
+
} = extractRetryImageAttachments(message);
|
|
7155
|
+
if (!messageText && retryAttachments.length === 0) return;
|
|
7156
|
+
const sessionKeyForSend = forcedSessionKey || resolvedSessionKey || activeSessionKey;
|
|
7157
|
+
if (!sessionKeyForSend) return;
|
|
7158
|
+
const clientId = message.clientId;
|
|
7159
|
+
const optimisticId = message.__optimisticId;
|
|
7160
|
+
if (clientId) {
|
|
7161
|
+
removeHistoryMessageByClientId(
|
|
7162
|
+
queryClient,
|
|
7163
|
+
activeFriendlyId,
|
|
7164
|
+
sessionKeyForSend,
|
|
7165
|
+
clientId,
|
|
7166
|
+
optimisticId
|
|
7167
|
+
);
|
|
7168
|
+
}
|
|
7169
|
+
sendMessage(
|
|
7170
|
+
sessionKeyForSend,
|
|
7171
|
+
activeFriendlyId,
|
|
7172
|
+
messageText,
|
|
7173
|
+
false,
|
|
7174
|
+
retryAttachments,
|
|
7175
|
+
void 0,
|
|
7176
|
+
retryAttachmentsPayload
|
|
7177
|
+
);
|
|
7178
|
+
},
|
|
7179
|
+
[
|
|
7180
|
+
activeFriendlyId,
|
|
7181
|
+
activeSessionKey,
|
|
7182
|
+
forcedSessionKey,
|
|
7183
|
+
queryClient,
|
|
7184
|
+
resolvedSessionKey
|
|
7185
|
+
]
|
|
7186
|
+
);
|
|
7187
|
+
const handleDismissMessage = useCallback(
|
|
7188
|
+
(message) => {
|
|
7189
|
+
const sessionKeyForSend = forcedSessionKey || resolvedSessionKey || activeSessionKey;
|
|
7190
|
+
if (!sessionKeyForSend) return;
|
|
7191
|
+
const clientId = message.clientId;
|
|
7192
|
+
const optimisticId = message.__optimisticId;
|
|
7193
|
+
if (clientId) {
|
|
7194
|
+
removeHistoryMessageByClientId(
|
|
7195
|
+
queryClient,
|
|
7196
|
+
activeFriendlyId,
|
|
7197
|
+
sessionKeyForSend,
|
|
7198
|
+
clientId,
|
|
7199
|
+
optimisticId
|
|
7200
|
+
);
|
|
7201
|
+
}
|
|
7202
|
+
setError(null);
|
|
7203
|
+
},
|
|
7204
|
+
[
|
|
7205
|
+
activeFriendlyId,
|
|
7206
|
+
activeSessionKey,
|
|
7207
|
+
forcedSessionKey,
|
|
7208
|
+
queryClient,
|
|
7209
|
+
resolvedSessionKey
|
|
7210
|
+
]
|
|
7211
|
+
);
|
|
7009
7212
|
const handleFollowUpClick = useCallback(
|
|
7010
7213
|
(suggestion) => {
|
|
7011
7214
|
if (isNewChat || !suggestion.trim()) return;
|
|
@@ -7164,7 +7367,9 @@ function ChatScreen({
|
|
|
7164
7367
|
headerHeight,
|
|
7165
7368
|
contentStyle: stableContentStyle,
|
|
7166
7369
|
onFollowUpClick: handleFollowUpClick,
|
|
7167
|
-
jumpToMessageId: searchJumpMessageId
|
|
7370
|
+
jumpToMessageId: searchJumpMessageId,
|
|
7371
|
+
onRetryMessage: handleRetryMessage,
|
|
7372
|
+
onDismissMessage: handleDismissMessage
|
|
7168
7373
|
}
|
|
7169
7374
|
),
|
|
7170
7375
|
/* @__PURE__ */ jsx(
|