@meetsmore-oss/use-ai-client 1.9.0 → 1.9.2
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/bundled.js +3973 -1254
- package/dist/bundled.js.map +1 -1
- package/dist/index.d.ts +547 -539
- package/dist/index.js +191 -73
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-STF3H6F5.js +0 -13
- package/dist/chunk-STF3H6F5.js.map +0 -1
- package/dist/chunk-UM4UCU4W.js +0 -46
- package/dist/chunk-UM4UCU4W.js.map +0 -1
- package/dist/types-GWPQMSYT.js +0 -9
- package/dist/types-GWPQMSYT.js.map +0 -1
- package/dist/types-RJZTRF3U.js +0 -9
- package/dist/types-RJZTRF3U.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
generateChatId,
|
|
3
|
-
generateMessageId
|
|
4
|
-
} from "./chunk-STF3H6F5.js";
|
|
5
|
-
|
|
6
1
|
// src/useAI.ts
|
|
7
2
|
import { useState as useState14, useEffect as useEffect12, useLayoutEffect, useRef as useRef14, useCallback as useCallback13, useMemo as useMemo6 } from "react";
|
|
8
3
|
|
|
@@ -273,13 +268,23 @@ function UseAIFloatingButton({
|
|
|
273
268
|
// src/components/UseAIChatPanel.tsx
|
|
274
269
|
import { useState as useState5, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
275
270
|
|
|
271
|
+
// src/utils/messageContent.ts
|
|
272
|
+
function getTextFromContent(content) {
|
|
273
|
+
if (typeof content === "string") {
|
|
274
|
+
return content;
|
|
275
|
+
}
|
|
276
|
+
return content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
277
|
+
}
|
|
278
|
+
|
|
276
279
|
// src/components/MarkdownContent.tsx
|
|
277
280
|
import ReactMarkdown from "react-markdown";
|
|
281
|
+
import remarkGfm from "remark-gfm";
|
|
278
282
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
279
283
|
function MarkdownContent({ content }) {
|
|
280
284
|
return /* @__PURE__ */ jsx2(
|
|
281
285
|
ReactMarkdown,
|
|
282
286
|
{
|
|
287
|
+
remarkPlugins: [remarkGfm],
|
|
283
288
|
components: {
|
|
284
289
|
// Override default element rendering for better chat styling
|
|
285
290
|
p: ({ children }) => /* @__PURE__ */ jsx2("p", { style: { margin: "0 0 0.5em 0" }, children }),
|
|
@@ -394,6 +399,23 @@ function MarkdownContent({ content }) {
|
|
|
394
399
|
},
|
|
395
400
|
children
|
|
396
401
|
}
|
|
402
|
+
),
|
|
403
|
+
// Render images as links to prevent automatic HTTP requests.
|
|
404
|
+
// <img> tags fire GET requests on render, which could be exploited
|
|
405
|
+
// via prompt injection to exfiltrate sensitive data through URLs.
|
|
406
|
+
img: ({ src, alt }) => /* @__PURE__ */ jsx2(
|
|
407
|
+
"a",
|
|
408
|
+
{
|
|
409
|
+
href: src,
|
|
410
|
+
target: "_blank",
|
|
411
|
+
rel: "noopener noreferrer",
|
|
412
|
+
style: {
|
|
413
|
+
color: "inherit",
|
|
414
|
+
textDecoration: "underline",
|
|
415
|
+
textUnderlineOffset: "2px"
|
|
416
|
+
},
|
|
417
|
+
children: alt || "Image"
|
|
418
|
+
}
|
|
397
419
|
)
|
|
398
420
|
},
|
|
399
421
|
children: content
|
|
@@ -1891,12 +1913,6 @@ function FeedbackButton({ type, isSelected, onClick, selectedColor, unselectedCo
|
|
|
1891
1913
|
}
|
|
1892
1914
|
);
|
|
1893
1915
|
}
|
|
1894
|
-
function getTextContent(content) {
|
|
1895
|
-
if (typeof content === "string") {
|
|
1896
|
-
return content;
|
|
1897
|
-
}
|
|
1898
|
-
return content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
1899
|
-
}
|
|
1900
1916
|
function hasFileContent(content) {
|
|
1901
1917
|
return Array.isArray(content) && content.some((part) => part.type === "file");
|
|
1902
1918
|
}
|
|
@@ -1933,6 +1949,11 @@ function UseAIChatPanel({
|
|
|
1933
1949
|
}) {
|
|
1934
1950
|
const strings = useStrings();
|
|
1935
1951
|
const theme = useTheme();
|
|
1952
|
+
const displayMessages = messages.filter((m) => {
|
|
1953
|
+
if (m.role === "tool") return false;
|
|
1954
|
+
if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0 && !getTextFromContent(m.content)) return false;
|
|
1955
|
+
return true;
|
|
1956
|
+
});
|
|
1936
1957
|
const [input, setInput] = useState5("");
|
|
1937
1958
|
const chatHistoryDropdown = useDropdownState();
|
|
1938
1959
|
const agentDropdown = useDropdownState();
|
|
@@ -2098,10 +2119,10 @@ function UseAIChatPanel({
|
|
|
2098
2119
|
flex: 1,
|
|
2099
2120
|
minWidth: 0
|
|
2100
2121
|
}, children: (() => {
|
|
2101
|
-
if (
|
|
2102
|
-
const firstUserMsg =
|
|
2122
|
+
if (displayMessages.length > 0) {
|
|
2123
|
+
const firstUserMsg = displayMessages.find((m) => m.role === "user");
|
|
2103
2124
|
if (firstUserMsg) {
|
|
2104
|
-
const textContent =
|
|
2125
|
+
const textContent = getTextFromContent(firstUserMsg.content);
|
|
2105
2126
|
const maxLength = 30;
|
|
2106
2127
|
return textContent.length > maxLength ? textContent.substring(0, maxLength) + "..." : textContent || strings.header.newChat;
|
|
2107
2128
|
}
|
|
@@ -2260,7 +2281,7 @@ function UseAIChatPanel({
|
|
|
2260
2281
|
children: /* @__PURE__ */ jsx11("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx11("path", { d: "M8 3.5V12.5M3.5 8H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) })
|
|
2261
2282
|
}
|
|
2262
2283
|
),
|
|
2263
|
-
onDeleteChat &&
|
|
2284
|
+
onDeleteChat && displayMessages.length > 0 && /* @__PURE__ */ jsx11(
|
|
2264
2285
|
"button",
|
|
2265
2286
|
{
|
|
2266
2287
|
"data-testid": "delete-chat-button",
|
|
@@ -2386,7 +2407,7 @@ function UseAIChatPanel({
|
|
|
2386
2407
|
gap: "12px"
|
|
2387
2408
|
},
|
|
2388
2409
|
children: [
|
|
2389
|
-
|
|
2410
|
+
displayMessages.length === 0 && /* @__PURE__ */ jsxs8(
|
|
2390
2411
|
"div",
|
|
2391
2412
|
{
|
|
2392
2413
|
style: {
|
|
@@ -2456,7 +2477,7 @@ function UseAIChatPanel({
|
|
|
2456
2477
|
]
|
|
2457
2478
|
}
|
|
2458
2479
|
),
|
|
2459
|
-
|
|
2480
|
+
displayMessages.map((message) => /* @__PURE__ */ jsxs8(
|
|
2460
2481
|
"div",
|
|
2461
2482
|
{
|
|
2462
2483
|
"data-testid": `chat-message-${message.role}`,
|
|
@@ -2483,7 +2504,7 @@ function UseAIChatPanel({
|
|
|
2483
2504
|
"data-testid": "save-command-button",
|
|
2484
2505
|
onClick: (e) => {
|
|
2485
2506
|
e.stopPropagation();
|
|
2486
|
-
const messageText =
|
|
2507
|
+
const messageText = getTextFromContent(message.content);
|
|
2487
2508
|
slashCommands.startSavingCommand(message.id, messageText);
|
|
2488
2509
|
},
|
|
2489
2510
|
title: "Save as slash command",
|
|
@@ -2543,13 +2564,13 @@ function UseAIChatPanel({
|
|
|
2543
2564
|
},
|
|
2544
2565
|
idx
|
|
2545
2566
|
)) }),
|
|
2546
|
-
message.role === "assistant" ? /* @__PURE__ */ jsx11(MarkdownContent, { content:
|
|
2567
|
+
message.role === "assistant" ? /* @__PURE__ */ jsx11(MarkdownContent, { content: getTextFromContent(message.content) }) : getTextFromContent(message.content)
|
|
2547
2568
|
]
|
|
2548
2569
|
}
|
|
2549
2570
|
),
|
|
2550
2571
|
slashCommands.renderInlineSaveUI({
|
|
2551
2572
|
messageId: message.id,
|
|
2552
|
-
messageText:
|
|
2573
|
+
messageText: getTextFromContent(message.content)
|
|
2553
2574
|
})
|
|
2554
2575
|
]
|
|
2555
2576
|
}
|
|
@@ -2603,7 +2624,7 @@ function UseAIChatPanel({
|
|
|
2603
2624
|
marginTop: "4px",
|
|
2604
2625
|
padding: "0 4px"
|
|
2605
2626
|
},
|
|
2606
|
-
children: message.
|
|
2627
|
+
children: message.createdAt.toLocaleTimeString([], {
|
|
2607
2628
|
hour: "2-digit",
|
|
2608
2629
|
minute: "2-digit"
|
|
2609
2630
|
})
|
|
@@ -3083,6 +3104,8 @@ var UseAIClient = class {
|
|
|
3083
3104
|
// Assistant message assembly (for tracking full conversation history)
|
|
3084
3105
|
_currentAssistantMessage = null;
|
|
3085
3106
|
_currentAssistantToolCalls = [];
|
|
3107
|
+
// Tool results collected during a turn, pushed to _messages in correct order at RUN_FINISHED
|
|
3108
|
+
_pendingToolResults = [];
|
|
3086
3109
|
// Tool call assembly
|
|
3087
3110
|
currentToolCalls = /* @__PURE__ */ new Map();
|
|
3088
3111
|
// Feedback tracking
|
|
@@ -3151,6 +3174,7 @@ var UseAIClient = class {
|
|
|
3151
3174
|
content: ""
|
|
3152
3175
|
};
|
|
3153
3176
|
this._currentAssistantToolCalls = [];
|
|
3177
|
+
this._pendingToolResults = [];
|
|
3154
3178
|
}
|
|
3155
3179
|
if (event.type === EventType.TEXT_MESSAGE_START) {
|
|
3156
3180
|
const e = event;
|
|
@@ -3191,17 +3215,32 @@ var UseAIClient = class {
|
|
|
3191
3215
|
}
|
|
3192
3216
|
} else if (event.type === EventType.RUN_FINISHED) {
|
|
3193
3217
|
if (this._currentAssistantMessage) {
|
|
3194
|
-
const assistantMessage = {
|
|
3195
|
-
id: this._currentAssistantMessage.id,
|
|
3196
|
-
role: "assistant",
|
|
3197
|
-
content: this._currentAssistantMessage.content || ""
|
|
3198
|
-
};
|
|
3199
3218
|
if (this._currentAssistantToolCalls.length > 0) {
|
|
3200
|
-
|
|
3219
|
+
const toolCallMessage = {
|
|
3220
|
+
id: uuidv42(),
|
|
3221
|
+
role: "assistant",
|
|
3222
|
+
content: "",
|
|
3223
|
+
toolCalls: this._currentAssistantToolCalls
|
|
3224
|
+
};
|
|
3225
|
+
this._messages.push(toolCallMessage);
|
|
3226
|
+
this._messages.push(...this._pendingToolResults);
|
|
3227
|
+
const textMessage = {
|
|
3228
|
+
id: this._currentAssistantMessage.id,
|
|
3229
|
+
role: "assistant",
|
|
3230
|
+
content: this._currentAssistantMessage.content || ""
|
|
3231
|
+
};
|
|
3232
|
+
this._messages.push(textMessage);
|
|
3233
|
+
} else {
|
|
3234
|
+
const assistantMessage = {
|
|
3235
|
+
id: this._currentAssistantMessage.id,
|
|
3236
|
+
role: "assistant",
|
|
3237
|
+
content: this._currentAssistantMessage.content || ""
|
|
3238
|
+
};
|
|
3239
|
+
this._messages.push(assistantMessage);
|
|
3201
3240
|
}
|
|
3202
|
-
this._messages.push(assistantMessage);
|
|
3203
3241
|
this._currentAssistantMessage = null;
|
|
3204
3242
|
this._currentAssistantToolCalls = [];
|
|
3243
|
+
this._pendingToolResults = [];
|
|
3205
3244
|
}
|
|
3206
3245
|
}
|
|
3207
3246
|
this.eventHandlers.forEach((handler) => handler(event));
|
|
@@ -3321,7 +3360,7 @@ var UseAIClient = class {
|
|
|
3321
3360
|
content: toolResultMessage.data.content,
|
|
3322
3361
|
toolCallId
|
|
3323
3362
|
};
|
|
3324
|
-
this.
|
|
3363
|
+
this._pendingToolResults.push(toolResultMsg);
|
|
3325
3364
|
this.send(toolResultMessage);
|
|
3326
3365
|
}
|
|
3327
3366
|
/**
|
|
@@ -3340,6 +3379,14 @@ var UseAIClient = class {
|
|
|
3340
3379
|
reason
|
|
3341
3380
|
}
|
|
3342
3381
|
};
|
|
3382
|
+
if (!approved) {
|
|
3383
|
+
this._pendingToolResults.push({
|
|
3384
|
+
id: uuidv42(),
|
|
3385
|
+
role: "tool",
|
|
3386
|
+
content: JSON.stringify({ rejected: true, reason: reason || "User rejected tool execution" }),
|
|
3387
|
+
toolCallId
|
|
3388
|
+
});
|
|
3389
|
+
}
|
|
3343
3390
|
this.send(message);
|
|
3344
3391
|
}
|
|
3345
3392
|
/**
|
|
@@ -3536,6 +3583,7 @@ var UseAIClient = class {
|
|
|
3536
3583
|
this.currentToolCalls.clear();
|
|
3537
3584
|
this._currentAssistantMessage = null;
|
|
3538
3585
|
this._currentAssistantToolCalls = [];
|
|
3586
|
+
this._pendingToolResults = [];
|
|
3539
3587
|
}
|
|
3540
3588
|
send(message) {
|
|
3541
3589
|
if (this.socket && this.socket.connected) {
|
|
@@ -3658,6 +3706,14 @@ async function executeDefinedTool(tools, toolName, input, ctx) {
|
|
|
3658
3706
|
return await tool._execute(input, ctx);
|
|
3659
3707
|
}
|
|
3660
3708
|
|
|
3709
|
+
// src/providers/chatRepository/types.ts
|
|
3710
|
+
function generateChatId() {
|
|
3711
|
+
return `chat_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
3712
|
+
}
|
|
3713
|
+
function generateMessageId() {
|
|
3714
|
+
return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
3715
|
+
}
|
|
3716
|
+
|
|
3661
3717
|
// src/providers/chatRepository/LocalStorageChatRepository.ts
|
|
3662
3718
|
var STORAGE_KEY_PREFIX = "use-ai:chat:";
|
|
3663
3719
|
var STORAGE_INDEX_KEY = "use-ai:chat-index";
|
|
@@ -3823,31 +3879,31 @@ function deepEquals(a, b) {
|
|
|
3823
3879
|
function generateChatTitle(message) {
|
|
3824
3880
|
return message.length > CHAT_TITLE_MAX_LENGTH ? message.substring(0, CHAT_TITLE_MAX_LENGTH) + "..." : message;
|
|
3825
3881
|
}
|
|
3826
|
-
function
|
|
3827
|
-
|
|
3828
|
-
return content;
|
|
3829
|
-
}
|
|
3830
|
-
return content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
3831
|
-
}
|
|
3832
|
-
function transformMessagesToUI(storageMessages) {
|
|
3833
|
-
return storageMessages.map((msg) => ({
|
|
3834
|
-
id: msg.id,
|
|
3835
|
-
role: msg.role,
|
|
3836
|
-
content: msg.content,
|
|
3837
|
-
timestamp: msg.createdAt,
|
|
3838
|
-
displayMode: msg.displayMode,
|
|
3839
|
-
traceId: msg.traceId,
|
|
3840
|
-
feedback: msg.feedback
|
|
3841
|
-
}));
|
|
3842
|
-
}
|
|
3843
|
-
function transformMessagesToClientFormat(uiMessages) {
|
|
3844
|
-
return uiMessages.map((msg) => {
|
|
3882
|
+
function transformMessagesToClientFormat(persistedMessages) {
|
|
3883
|
+
return persistedMessages.map((msg) => {
|
|
3845
3884
|
const textContent = getTextFromContent(msg.content);
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3885
|
+
switch (msg.role) {
|
|
3886
|
+
case "tool":
|
|
3887
|
+
return {
|
|
3888
|
+
id: msg.id,
|
|
3889
|
+
role: "tool",
|
|
3890
|
+
content: textContent,
|
|
3891
|
+
toolCallId: msg.toolCallId || ""
|
|
3892
|
+
};
|
|
3893
|
+
case "assistant":
|
|
3894
|
+
return {
|
|
3895
|
+
id: msg.id,
|
|
3896
|
+
role: "assistant",
|
|
3897
|
+
content: textContent,
|
|
3898
|
+
...msg.toolCalls && msg.toolCalls.length > 0 ? { toolCalls: msg.toolCalls } : {}
|
|
3899
|
+
};
|
|
3900
|
+
case "user":
|
|
3901
|
+
return {
|
|
3902
|
+
id: msg.id,
|
|
3903
|
+
role: "user",
|
|
3904
|
+
content: textContent
|
|
3905
|
+
};
|
|
3906
|
+
}
|
|
3851
3907
|
});
|
|
3852
3908
|
}
|
|
3853
3909
|
function useChatManagement({
|
|
@@ -3871,9 +3927,8 @@ function useChatManagement({
|
|
|
3871
3927
|
try {
|
|
3872
3928
|
const chat = await repository.loadChat(chatId);
|
|
3873
3929
|
if (chat) {
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
return loadedMessages;
|
|
3930
|
+
console.log("[ChatManagement] Loaded", chat.messages.length, "messages from storage for chat:", chatId);
|
|
3931
|
+
return chat.messages;
|
|
3877
3932
|
} else {
|
|
3878
3933
|
console.log("[ChatManagement] Chat not found in storage:", chatId);
|
|
3879
3934
|
return [];
|
|
@@ -3969,7 +4024,7 @@ function useChatManagement({
|
|
|
3969
4024
|
setCurrentChatId(pendingChatId);
|
|
3970
4025
|
setPendingChatId(null);
|
|
3971
4026
|
return pendingChatId;
|
|
3972
|
-
}, [pendingChatId,
|
|
4027
|
+
}, [pendingChatId, clientRef, messages]);
|
|
3973
4028
|
const saveUserMessage = useCallback4(async (chatId, content) => {
|
|
3974
4029
|
try {
|
|
3975
4030
|
const chat = await repository.loadChat(chatId);
|
|
@@ -3977,13 +4032,13 @@ function useChatManagement({
|
|
|
3977
4032
|
console.error("[ChatManagement] Chat not found:", chatId);
|
|
3978
4033
|
return false;
|
|
3979
4034
|
}
|
|
3980
|
-
const
|
|
3981
|
-
|
|
3982
|
-
id: generateMessageId2(),
|
|
4035
|
+
const newMessage = {
|
|
4036
|
+
id: generateMessageId(),
|
|
3983
4037
|
role: "user",
|
|
3984
4038
|
content,
|
|
3985
4039
|
createdAt: /* @__PURE__ */ new Date()
|
|
3986
|
-
}
|
|
4040
|
+
};
|
|
4041
|
+
chat.messages.push(newMessage);
|
|
3987
4042
|
if (!chat.title) {
|
|
3988
4043
|
const text = getTextFromContent(content);
|
|
3989
4044
|
if (text) {
|
|
@@ -3992,14 +4047,14 @@ function useChatManagement({
|
|
|
3992
4047
|
}
|
|
3993
4048
|
await repository.saveChat(chat);
|
|
3994
4049
|
console.log("[ChatManagement] Saved user message to storage");
|
|
3995
|
-
|
|
4050
|
+
setMessages((prev) => [...prev, newMessage]);
|
|
3996
4051
|
return true;
|
|
3997
4052
|
} catch (error) {
|
|
3998
4053
|
console.error("[ChatManagement] Failed to save user message:", error);
|
|
3999
4054
|
return false;
|
|
4000
4055
|
}
|
|
4001
|
-
}, [repository,
|
|
4002
|
-
const saveAIResponse = useCallback4(async (content, displayMode, traceId) => {
|
|
4056
|
+
}, [repository, setMessages]);
|
|
4057
|
+
const saveAIResponse = useCallback4(async (content, displayMode, traceId, turnMessages) => {
|
|
4003
4058
|
const currentChatIdValue = currentChatIdSnapshot.current;
|
|
4004
4059
|
const pendingChatIdValue = pendingChatIdSnapshot.current;
|
|
4005
4060
|
const displayedChatId2 = pendingChatIdValue || currentChatIdValue;
|
|
@@ -4013,15 +4068,18 @@ function useChatManagement({
|
|
|
4013
4068
|
console.error("[ChatManagement] Chat not found:", currentChatIdValue);
|
|
4014
4069
|
return;
|
|
4015
4070
|
}
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4071
|
+
if (turnMessages && turnMessages.length > 0) {
|
|
4072
|
+
chat.messages.push(...turnMessages);
|
|
4073
|
+
}
|
|
4074
|
+
const finalMessage = {
|
|
4075
|
+
id: generateMessageId(),
|
|
4019
4076
|
role: "assistant",
|
|
4020
4077
|
content,
|
|
4021
4078
|
createdAt: /* @__PURE__ */ new Date(),
|
|
4022
4079
|
displayMode,
|
|
4023
4080
|
traceId
|
|
4024
|
-
}
|
|
4081
|
+
};
|
|
4082
|
+
chat.messages.push(finalMessage);
|
|
4025
4083
|
if (!chat.title) {
|
|
4026
4084
|
const firstUserMessage = chat.messages.find((msg) => msg.role === "user");
|
|
4027
4085
|
if (firstUserMessage) {
|
|
@@ -4034,12 +4092,16 @@ function useChatManagement({
|
|
|
4034
4092
|
await repository.saveChat(chat);
|
|
4035
4093
|
console.log("[ChatManagement] Saved AI response to storage for chatId:", currentChatIdValue);
|
|
4036
4094
|
if (displayedChatId2 === currentChatIdValue) {
|
|
4037
|
-
|
|
4095
|
+
const newMessages = [
|
|
4096
|
+
...turnMessages ?? [],
|
|
4097
|
+
finalMessage
|
|
4098
|
+
];
|
|
4099
|
+
setMessages((prev) => [...prev, ...newMessages]);
|
|
4038
4100
|
}
|
|
4039
4101
|
} catch (error) {
|
|
4040
4102
|
console.error("[ChatManagement] Failed to save AI response:", error);
|
|
4041
4103
|
}
|
|
4042
|
-
}, [repository,
|
|
4104
|
+
}, [repository, setMessages]);
|
|
4043
4105
|
const initializedRef = useRef5(false);
|
|
4044
4106
|
useEffect5(() => {
|
|
4045
4107
|
if (currentChatId === null && pendingChatId === null && !initializedRef.current) {
|
|
@@ -4070,6 +4132,26 @@ function useChatManagement({
|
|
|
4070
4132
|
})();
|
|
4071
4133
|
}
|
|
4072
4134
|
}, [currentChatId, pendingChatId, createNewChat, repository, loadChatMessages, clientRef, setMessages]);
|
|
4135
|
+
const connectionPhaseRef = useRef5("initial");
|
|
4136
|
+
useEffect5(() => {
|
|
4137
|
+
if (connected) {
|
|
4138
|
+
const isReconnect = connectionPhaseRef.current === "disconnected";
|
|
4139
|
+
connectionPhaseRef.current = "connected";
|
|
4140
|
+
if (isReconnect && currentChatId && clientRef.current) {
|
|
4141
|
+
(async () => {
|
|
4142
|
+
const loadedMessages = await loadChatMessages(currentChatId);
|
|
4143
|
+
if (loadedMessages.length > 0) {
|
|
4144
|
+
clientRef.current?.loadMessages(transformMessagesToClientFormat(loadedMessages));
|
|
4145
|
+
console.log("[ChatManagement] Reloaded", loadedMessages.length, "messages from storage on reconnect");
|
|
4146
|
+
}
|
|
4147
|
+
})();
|
|
4148
|
+
}
|
|
4149
|
+
} else {
|
|
4150
|
+
if (connectionPhaseRef.current === "connected") {
|
|
4151
|
+
connectionPhaseRef.current = "disconnected";
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
}, [connected, currentChatId, loadChatMessages, clientRef]);
|
|
4073
4155
|
const displayedChatId = pendingChatId || currentChatId;
|
|
4074
4156
|
return {
|
|
4075
4157
|
currentChatId,
|
|
@@ -4714,6 +4796,30 @@ import { useState as useState12, useCallback as useCallback10, useRef as useRef1
|
|
|
4714
4796
|
import { EventType as EventType2, ErrorCode, TOOL_APPROVAL_REQUEST } from "@meetsmore-oss/use-ai-core";
|
|
4715
4797
|
|
|
4716
4798
|
// src/hooks/useServerEvents.ts
|
|
4799
|
+
function extractTurnMessages(messages, startIndex) {
|
|
4800
|
+
const turnSlice = messages.slice(startIndex);
|
|
4801
|
+
const result = [];
|
|
4802
|
+
for (const msg of turnSlice) {
|
|
4803
|
+
if (msg.role === "assistant" && "toolCalls" in msg && msg.toolCalls) {
|
|
4804
|
+
result.push({
|
|
4805
|
+
id: msg.id,
|
|
4806
|
+
role: "assistant",
|
|
4807
|
+
content: "",
|
|
4808
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4809
|
+
toolCalls: msg.toolCalls
|
|
4810
|
+
});
|
|
4811
|
+
} else if (msg.role === "tool") {
|
|
4812
|
+
result.push({
|
|
4813
|
+
id: msg.id,
|
|
4814
|
+
role: "tool",
|
|
4815
|
+
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
|
|
4816
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4817
|
+
toolCallId: "toolCallId" in msg && msg.toolCallId ? msg.toolCallId : void 0
|
|
4818
|
+
});
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
return result;
|
|
4822
|
+
}
|
|
4717
4823
|
function useServerEvents({
|
|
4718
4824
|
toolSystem,
|
|
4719
4825
|
saveAIResponse,
|
|
@@ -4722,6 +4828,7 @@ function useServerEvents({
|
|
|
4722
4828
|
const [loading, setLoading] = useState12(false);
|
|
4723
4829
|
const [streamingText, setStreamingText] = useState12("");
|
|
4724
4830
|
const streamingChatIdRef = useRef10(null);
|
|
4831
|
+
const messageCountAtRunStartRef = useRef10(0);
|
|
4725
4832
|
const [executingToolRaw, setExecutingTool] = useState12(null);
|
|
4726
4833
|
const executingToolFallbackRef = useRef10(null);
|
|
4727
4834
|
const clearStreamingText = useCallback10(() => {
|
|
@@ -4736,7 +4843,9 @@ function useServerEvents({
|
|
|
4736
4843
|
const handleServerEvent = useCallback10(async (client, event) => {
|
|
4737
4844
|
const ts = toolSystemRef.current;
|
|
4738
4845
|
const strs = stringsRef.current;
|
|
4739
|
-
if (event.type === EventType2.
|
|
4846
|
+
if (event.type === EventType2.RUN_STARTED) {
|
|
4847
|
+
messageCountAtRunStartRef.current = client.messages.length;
|
|
4848
|
+
} else if (event.type === EventType2.TOOL_CALL_START) {
|
|
4740
4849
|
const e = event;
|
|
4741
4850
|
const tool = ts.aggregatedToolsRef.current[e.toolCallName];
|
|
4742
4851
|
const title = e.annotations?.title ?? tool?._options?.annotations?.title ?? null;
|
|
@@ -4781,7 +4890,8 @@ function useServerEvents({
|
|
|
4781
4890
|
if (content) {
|
|
4782
4891
|
const finishedEvent = event;
|
|
4783
4892
|
const traceId = finishedEvent.runId;
|
|
4784
|
-
|
|
4893
|
+
const turnMessages = extractTurnMessages(client.messages, messageCountAtRunStartRef.current);
|
|
4894
|
+
saveAIResponseRef.current(content, void 0, traceId, turnMessages);
|
|
4785
4895
|
}
|
|
4786
4896
|
setLoading(false);
|
|
4787
4897
|
} else if (event.type === EventType2.RUN_ERROR) {
|
|
@@ -5052,7 +5162,15 @@ function UseAIProvider({
|
|
|
5052
5162
|
const lastRegisteredToolsRef = useRef12("");
|
|
5053
5163
|
useEffect11(() => {
|
|
5054
5164
|
const client = clientRef.current;
|
|
5055
|
-
if (!client || !client.isConnected()
|
|
5165
|
+
if (!client || !client.isConnected()) return;
|
|
5166
|
+
if (!toolSystem.hasTools) {
|
|
5167
|
+
if (lastRegisteredToolsRef.current !== "") {
|
|
5168
|
+
lastRegisteredToolsRef.current = "";
|
|
5169
|
+
client.registerTools([]);
|
|
5170
|
+
console.log("[Provider] All tools unregistered, clearing client tools");
|
|
5171
|
+
}
|
|
5172
|
+
return;
|
|
5173
|
+
}
|
|
5056
5174
|
const toolKeys = Object.keys(toolSystem.aggregatedTools).sort().join(",");
|
|
5057
5175
|
if (toolKeys === lastRegisteredToolsRef.current) {
|
|
5058
5176
|
console.log("[Provider] Skipping re-registration, tools unchanged");
|