@meetsmore-oss/use-ai-client 1.4.0 → 1.5.0
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 +3780 -2392
- package/dist/bundled.js.map +1 -1
- package/dist/{chunk-QTQR7MAU.js → chunk-STF3H6F5.js} +1 -1
- package/dist/chunk-STF3H6F5.js.map +1 -0
- package/dist/{chunk-AKQM6IWU.js → chunk-UM4UCU4W.js} +1 -1
- package/dist/chunk-UM4UCU4W.js.map +1 -0
- package/dist/index.d.ts +90 -12
- package/dist/index.js +328 -73
- package/dist/index.js.map +1 -1
- package/dist/{types-64CH2HXY.js → types-GWPQMSYT.js} +2 -2
- package/dist/{types-STDS67SG.js → types-RJZTRF3U.js} +2 -2
- package/package.json +2 -2
- package/dist/chunk-AKQM6IWU.js.map +0 -1
- package/dist/chunk-QTQR7MAU.js.map +0 -1
- /package/dist/{types-64CH2HXY.js.map → types-GWPQMSYT.js.map} +0 -0
- /package/dist/{types-STDS67SG.js.map → types-RJZTRF3U.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateChatId,
|
|
3
3
|
generateMessageId
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-STF3H6F5.js";
|
|
5
5
|
|
|
6
6
|
// src/useAI.ts
|
|
7
|
-
import { useState as
|
|
7
|
+
import { useState as useState12, useEffect as useEffect11, useRef as useRef12, useCallback as useCallback11, useMemo as useMemo6 } from "react";
|
|
8
8
|
|
|
9
9
|
// src/providers/useAIProvider.tsx
|
|
10
|
-
import { createContext as createContext4, useContext as useContext4, useState as
|
|
10
|
+
import { createContext as createContext4, useContext as useContext4, useState as useState11, useEffect as useEffect10, useCallback as useCallback10, useRef as useRef10 } from "react";
|
|
11
11
|
|
|
12
12
|
// src/types.ts
|
|
13
13
|
import { EventType, ErrorCode } from "@meetsmore-oss/use-ai-core";
|
|
@@ -104,6 +104,11 @@ var defaultStrings = {
|
|
|
104
104
|
RATE_LIMITED: "Too many requests. Please wait a moment before trying again.",
|
|
105
105
|
/** Error for unknown/unexpected errors */
|
|
106
106
|
UNKNOWN_ERROR: "An unexpected error occurred. Please try again."
|
|
107
|
+
},
|
|
108
|
+
// Tool execution status
|
|
109
|
+
toolExecution: {
|
|
110
|
+
/** Fallback messages when no tool title is provided (one randomly selected) */
|
|
111
|
+
fallbackMessages: ["Working", "Processing", "Thinking"]
|
|
107
112
|
}
|
|
108
113
|
};
|
|
109
114
|
var StringsContext = createContext(defaultStrings);
|
|
@@ -1571,6 +1576,71 @@ function useDropdownState(options = {}) {
|
|
|
1571
1576
|
|
|
1572
1577
|
// src/components/UseAIChatPanel.tsx
|
|
1573
1578
|
import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1579
|
+
function FeedbackButton({ type, isSelected, onClick, selectedColor, unselectedColor }) {
|
|
1580
|
+
const buttonRef = useRef4(null);
|
|
1581
|
+
const handleClick = () => {
|
|
1582
|
+
if (!isSelected && buttonRef.current) {
|
|
1583
|
+
buttonRef.current.style.transform = "scale(1.3)";
|
|
1584
|
+
setTimeout(() => {
|
|
1585
|
+
if (buttonRef.current) {
|
|
1586
|
+
buttonRef.current.style.transform = "scale(1)";
|
|
1587
|
+
}
|
|
1588
|
+
}, 150);
|
|
1589
|
+
}
|
|
1590
|
+
onClick();
|
|
1591
|
+
};
|
|
1592
|
+
const thumbsUpPath = "M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3";
|
|
1593
|
+
const thumbsDownPath = "M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17";
|
|
1594
|
+
return /* @__PURE__ */ jsx10(
|
|
1595
|
+
"button",
|
|
1596
|
+
{
|
|
1597
|
+
ref: buttonRef,
|
|
1598
|
+
"data-testid": `feedback-${type}`,
|
|
1599
|
+
onClick: handleClick,
|
|
1600
|
+
title: type === "upvote" ? "Good response" : "Poor response",
|
|
1601
|
+
style: {
|
|
1602
|
+
background: "transparent",
|
|
1603
|
+
border: "none",
|
|
1604
|
+
padding: "4px",
|
|
1605
|
+
cursor: "pointer",
|
|
1606
|
+
color: isSelected ? selectedColor : unselectedColor,
|
|
1607
|
+
opacity: isSelected ? 1 : 0.5,
|
|
1608
|
+
transition: "all 0.15s",
|
|
1609
|
+
display: "flex",
|
|
1610
|
+
alignItems: "center",
|
|
1611
|
+
justifyContent: "center",
|
|
1612
|
+
borderRadius: "4px",
|
|
1613
|
+
transform: "scale(1)"
|
|
1614
|
+
},
|
|
1615
|
+
onMouseEnter: (e) => {
|
|
1616
|
+
if (!isSelected) {
|
|
1617
|
+
e.currentTarget.style.opacity = "0.8";
|
|
1618
|
+
e.currentTarget.style.color = selectedColor;
|
|
1619
|
+
}
|
|
1620
|
+
},
|
|
1621
|
+
onMouseLeave: (e) => {
|
|
1622
|
+
if (!isSelected) {
|
|
1623
|
+
e.currentTarget.style.opacity = "0.5";
|
|
1624
|
+
e.currentTarget.style.color = unselectedColor;
|
|
1625
|
+
}
|
|
1626
|
+
},
|
|
1627
|
+
children: /* @__PURE__ */ jsx10(
|
|
1628
|
+
"svg",
|
|
1629
|
+
{
|
|
1630
|
+
width: "14",
|
|
1631
|
+
height: "14",
|
|
1632
|
+
viewBox: "0 0 24 24",
|
|
1633
|
+
fill: isSelected ? "currentColor" : "none",
|
|
1634
|
+
stroke: "currentColor",
|
|
1635
|
+
strokeWidth: "2",
|
|
1636
|
+
strokeLinecap: "round",
|
|
1637
|
+
strokeLinejoin: "round",
|
|
1638
|
+
children: /* @__PURE__ */ jsx10("path", { d: type === "upvote" ? thumbsUpPath : thumbsDownPath })
|
|
1639
|
+
}
|
|
1640
|
+
)
|
|
1641
|
+
}
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1574
1644
|
function getTextContent(content) {
|
|
1575
1645
|
if (typeof content === "string") {
|
|
1576
1646
|
return content;
|
|
@@ -1603,7 +1673,10 @@ function UseAIChatPanel({
|
|
|
1603
1673
|
onSaveCommand,
|
|
1604
1674
|
onRenameCommand,
|
|
1605
1675
|
onDeleteCommand,
|
|
1606
|
-
closeButton
|
|
1676
|
+
closeButton,
|
|
1677
|
+
executingTool,
|
|
1678
|
+
feedbackEnabled,
|
|
1679
|
+
onFeedback
|
|
1607
1680
|
}) {
|
|
1608
1681
|
const strings = useStrings();
|
|
1609
1682
|
const theme = useTheme();
|
|
@@ -2228,6 +2301,46 @@ function UseAIChatPanel({
|
|
|
2228
2301
|
]
|
|
2229
2302
|
}
|
|
2230
2303
|
),
|
|
2304
|
+
message.role === "assistant" && message.traceId && feedbackEnabled && onFeedback && /* @__PURE__ */ jsxs7(
|
|
2305
|
+
"div",
|
|
2306
|
+
{
|
|
2307
|
+
"data-testid": "feedback-buttons",
|
|
2308
|
+
style: {
|
|
2309
|
+
display: "flex",
|
|
2310
|
+
gap: "4px",
|
|
2311
|
+
marginTop: "4px",
|
|
2312
|
+
padding: "0 4px"
|
|
2313
|
+
},
|
|
2314
|
+
children: [
|
|
2315
|
+
/* @__PURE__ */ jsx10(
|
|
2316
|
+
FeedbackButton,
|
|
2317
|
+
{
|
|
2318
|
+
type: "upvote",
|
|
2319
|
+
isSelected: message.feedback === "upvote",
|
|
2320
|
+
onClick: () => {
|
|
2321
|
+
const newFeedback = message.feedback === "upvote" ? null : "upvote";
|
|
2322
|
+
onFeedback(message.id, message.traceId, newFeedback);
|
|
2323
|
+
},
|
|
2324
|
+
selectedColor: theme.primaryColor,
|
|
2325
|
+
unselectedColor: theme.secondaryTextColor
|
|
2326
|
+
}
|
|
2327
|
+
),
|
|
2328
|
+
/* @__PURE__ */ jsx10(
|
|
2329
|
+
FeedbackButton,
|
|
2330
|
+
{
|
|
2331
|
+
type: "downvote",
|
|
2332
|
+
isSelected: message.feedback === "downvote",
|
|
2333
|
+
onClick: () => {
|
|
2334
|
+
const newFeedback = message.feedback === "downvote" ? null : "downvote";
|
|
2335
|
+
onFeedback(message.id, message.traceId, newFeedback);
|
|
2336
|
+
},
|
|
2337
|
+
selectedColor: theme.errorTextColor,
|
|
2338
|
+
unselectedColor: theme.secondaryTextColor
|
|
2339
|
+
}
|
|
2340
|
+
)
|
|
2341
|
+
]
|
|
2342
|
+
}
|
|
2343
|
+
),
|
|
2231
2344
|
/* @__PURE__ */ jsx10(
|
|
2232
2345
|
"div",
|
|
2233
2346
|
{
|
|
@@ -2289,10 +2402,7 @@ function UseAIChatPanel({
|
|
|
2289
2402
|
} }) })
|
|
2290
2403
|
] }),
|
|
2291
2404
|
fileProcessing.progress == null && /* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
|
|
2292
|
-
] }) : /* @__PURE__ */
|
|
2293
|
-
/* @__PURE__ */ jsx10("span", { style: { opacity: 0.6 }, children: strings.input.thinking }),
|
|
2294
|
-
/* @__PURE__ */ jsx10("span", { className: "dots", style: { marginLeft: "4px" }, children: "..." })
|
|
2295
|
-
] })
|
|
2405
|
+
] }) : /* @__PURE__ */ jsx10("span", { className: "dots", style: { opacity: 0.6 }, children: "..." })
|
|
2296
2406
|
}
|
|
2297
2407
|
)
|
|
2298
2408
|
}
|
|
@@ -2379,7 +2489,7 @@ function UseAIChatPanel({
|
|
|
2379
2489
|
value: input,
|
|
2380
2490
|
onChange: handleInputChange,
|
|
2381
2491
|
onKeyDown: handleKeyDown,
|
|
2382
|
-
placeholder: connected ? strings.input.
|
|
2492
|
+
placeholder: !connected ? strings.input.connectingPlaceholder : loading ? `${executingTool?.displayText ?? strings.input.thinking}...` : strings.input.placeholder,
|
|
2383
2493
|
disabled: !connected || loading,
|
|
2384
2494
|
rows: 1,
|
|
2385
2495
|
style: {
|
|
@@ -2641,7 +2751,10 @@ function UseAIChat({ floating = false }) {
|
|
|
2641
2751
|
commands: ctx.commands.list,
|
|
2642
2752
|
onSaveCommand: ctx.commands.save,
|
|
2643
2753
|
onRenameCommand: ctx.commands.rename,
|
|
2644
|
-
onDeleteCommand: ctx.commands.delete
|
|
2754
|
+
onDeleteCommand: ctx.commands.delete,
|
|
2755
|
+
executingTool: ctx.executingTool,
|
|
2756
|
+
feedbackEnabled: ctx.feedback?.enabled,
|
|
2757
|
+
onFeedback: ctx.feedback?.submit
|
|
2645
2758
|
};
|
|
2646
2759
|
if (floating) {
|
|
2647
2760
|
return /* @__PURE__ */ jsx12(
|
|
@@ -2702,6 +2815,9 @@ var UseAIClient = class {
|
|
|
2702
2815
|
_currentAssistantToolCalls = [];
|
|
2703
2816
|
// Tool call assembly
|
|
2704
2817
|
currentToolCalls = /* @__PURE__ */ new Map();
|
|
2818
|
+
// Feedback tracking
|
|
2819
|
+
_langfuseEnabled = false;
|
|
2820
|
+
langfuseConfigHandlers = /* @__PURE__ */ new Set();
|
|
2705
2821
|
/**
|
|
2706
2822
|
* Establishes a Socket.IO connection to the server.
|
|
2707
2823
|
* Connection state changes are notified via onConnectionStateChange().
|
|
@@ -2744,6 +2860,11 @@ var UseAIClient = class {
|
|
|
2744
2860
|
this._defaultAgent = data.defaultAgent;
|
|
2745
2861
|
this.agentsChangeHandlers.forEach((handler) => handler(data.agents, data.defaultAgent));
|
|
2746
2862
|
});
|
|
2863
|
+
this.socket.on("config", (data) => {
|
|
2864
|
+
console.log("[Client] Received server config:", data);
|
|
2865
|
+
this._langfuseEnabled = data.langfuseEnabled ?? false;
|
|
2866
|
+
this.langfuseConfigHandlers.forEach((handler) => handler(this._langfuseEnabled));
|
|
2867
|
+
});
|
|
2747
2868
|
this.socket.on("connect_error", (error) => {
|
|
2748
2869
|
console.warn("[UseAI] Connection error:", error.message);
|
|
2749
2870
|
});
|
|
@@ -3160,6 +3281,41 @@ var UseAIClient = class {
|
|
|
3160
3281
|
isConnected() {
|
|
3161
3282
|
return this.socket !== null && this.socket.connected;
|
|
3162
3283
|
}
|
|
3284
|
+
/**
|
|
3285
|
+
* Subscribes to Langfuse config changes.
|
|
3286
|
+
*
|
|
3287
|
+
* @param handler - Callback function receiving langfuse enabled status
|
|
3288
|
+
* @returns Cleanup function to unsubscribe
|
|
3289
|
+
*/
|
|
3290
|
+
onLangfuseConfigChange(handler) {
|
|
3291
|
+
this.langfuseConfigHandlers.add(handler);
|
|
3292
|
+
handler(this._langfuseEnabled);
|
|
3293
|
+
return () => {
|
|
3294
|
+
this.langfuseConfigHandlers.delete(handler);
|
|
3295
|
+
};
|
|
3296
|
+
}
|
|
3297
|
+
/**
|
|
3298
|
+
* Submits feedback for an assistant message.
|
|
3299
|
+
* Sends feedback to the server, which forwards it to Langfuse.
|
|
3300
|
+
*
|
|
3301
|
+
* @param messageId - The client-side message ID
|
|
3302
|
+
* @param traceId - The Langfuse trace ID (runId from RUN_FINISHED)
|
|
3303
|
+
* @param feedback - 'upvote' for positive, 'downvote' for negative, null to remove
|
|
3304
|
+
*/
|
|
3305
|
+
submitFeedback(messageId, traceId, feedback) {
|
|
3306
|
+
if (!this.socket?.connected) {
|
|
3307
|
+
console.warn("[UseAI] Cannot submit feedback: not connected");
|
|
3308
|
+
return;
|
|
3309
|
+
}
|
|
3310
|
+
if (!this._langfuseEnabled) {
|
|
3311
|
+
console.warn("[UseAI] Cannot submit feedback: Langfuse not enabled on server");
|
|
3312
|
+
return;
|
|
3313
|
+
}
|
|
3314
|
+
this.send({
|
|
3315
|
+
type: "message_feedback",
|
|
3316
|
+
data: { messageId, traceId, feedback }
|
|
3317
|
+
});
|
|
3318
|
+
}
|
|
3163
3319
|
};
|
|
3164
3320
|
|
|
3165
3321
|
// src/defineTool.ts
|
|
@@ -3199,8 +3355,8 @@ function defineTool(description, schemaOrFn, fnOrOptions, options) {
|
|
|
3199
3355
|
description,
|
|
3200
3356
|
parameters
|
|
3201
3357
|
};
|
|
3202
|
-
if (this._options.
|
|
3203
|
-
toolDef.
|
|
3358
|
+
if (this._options.annotations) {
|
|
3359
|
+
toolDef.annotations = this._options.annotations;
|
|
3204
3360
|
}
|
|
3205
3361
|
return toolDef;
|
|
3206
3362
|
},
|
|
@@ -3398,7 +3554,9 @@ function transformMessagesToUI(storageMessages) {
|
|
|
3398
3554
|
role: msg.role,
|
|
3399
3555
|
content: msg.content,
|
|
3400
3556
|
timestamp: msg.createdAt,
|
|
3401
|
-
displayMode: msg.displayMode
|
|
3557
|
+
displayMode: msg.displayMode,
|
|
3558
|
+
traceId: msg.traceId,
|
|
3559
|
+
feedback: msg.feedback
|
|
3402
3560
|
}));
|
|
3403
3561
|
}
|
|
3404
3562
|
function transformMessagesToClientFormat(uiMessages) {
|
|
@@ -3414,6 +3572,8 @@ function transformMessagesToClientFormat(uiMessages) {
|
|
|
3414
3572
|
function useChatManagement({
|
|
3415
3573
|
repository,
|
|
3416
3574
|
clientRef,
|
|
3575
|
+
messages,
|
|
3576
|
+
setMessages,
|
|
3417
3577
|
onSendMessage,
|
|
3418
3578
|
setOpen,
|
|
3419
3579
|
connected,
|
|
@@ -3421,7 +3581,6 @@ function useChatManagement({
|
|
|
3421
3581
|
}) {
|
|
3422
3582
|
const [currentChatId, setCurrentChatId] = useState5(null);
|
|
3423
3583
|
const [pendingChatId, setPendingChatId] = useState5(null);
|
|
3424
|
-
const [messages, setMessages] = useState5([]);
|
|
3425
3584
|
const currentChatIdSnapshot = useRef5(null);
|
|
3426
3585
|
const pendingChatIdSnapshot = useRef5(null);
|
|
3427
3586
|
useEffect5(() => {
|
|
@@ -3540,7 +3699,7 @@ function useChatManagement({
|
|
|
3540
3699
|
console.error("[ChatManagement] Chat not found:", chatId);
|
|
3541
3700
|
return false;
|
|
3542
3701
|
}
|
|
3543
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3702
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-GWPQMSYT.js");
|
|
3544
3703
|
chat.messages.push({
|
|
3545
3704
|
id: generateMessageId2(),
|
|
3546
3705
|
role: "user",
|
|
@@ -3562,7 +3721,7 @@ function useChatManagement({
|
|
|
3562
3721
|
return false;
|
|
3563
3722
|
}
|
|
3564
3723
|
}, [repository, reloadMessages]);
|
|
3565
|
-
const saveAIResponse = useCallback4(async (content, displayMode) => {
|
|
3724
|
+
const saveAIResponse = useCallback4(async (content, displayMode, traceId) => {
|
|
3566
3725
|
const currentChatIdValue = currentChatIdSnapshot.current;
|
|
3567
3726
|
const pendingChatIdValue = pendingChatIdSnapshot.current;
|
|
3568
3727
|
const displayedChatId2 = pendingChatIdValue || currentChatIdValue;
|
|
@@ -3576,13 +3735,14 @@ function useChatManagement({
|
|
|
3576
3735
|
console.error("[ChatManagement] Chat not found:", currentChatIdValue);
|
|
3577
3736
|
return;
|
|
3578
3737
|
}
|
|
3579
|
-
const { generateMessageId: generateMessageId2 } = await import("./types-
|
|
3738
|
+
const { generateMessageId: generateMessageId2 } = await import("./types-GWPQMSYT.js");
|
|
3580
3739
|
chat.messages.push({
|
|
3581
3740
|
id: generateMessageId2(),
|
|
3582
3741
|
role: "assistant",
|
|
3583
3742
|
content,
|
|
3584
3743
|
createdAt: /* @__PURE__ */ new Date(),
|
|
3585
|
-
displayMode
|
|
3744
|
+
displayMode,
|
|
3745
|
+
traceId
|
|
3586
3746
|
});
|
|
3587
3747
|
if (!chat.title) {
|
|
3588
3748
|
const firstUserMessage = chat.messages.find((msg) => msg.role === "user");
|
|
@@ -3700,7 +3860,6 @@ function useChatManagement({
|
|
|
3700
3860
|
return {
|
|
3701
3861
|
currentChatId,
|
|
3702
3862
|
pendingChatId,
|
|
3703
|
-
messages,
|
|
3704
3863
|
displayedChatId,
|
|
3705
3864
|
createNewChat,
|
|
3706
3865
|
loadChat,
|
|
@@ -4094,6 +4253,68 @@ function usePromptState({
|
|
|
4094
4253
|
};
|
|
4095
4254
|
}
|
|
4096
4255
|
|
|
4256
|
+
// src/hooks/useFeedback.ts
|
|
4257
|
+
import { useState as useState10, useEffect as useEffect9, useRef as useRef9, useCallback as useCallback9 } from "react";
|
|
4258
|
+
function useFeedback({
|
|
4259
|
+
clientRef,
|
|
4260
|
+
repository,
|
|
4261
|
+
getDisplayedChatId,
|
|
4262
|
+
setMessages
|
|
4263
|
+
}) {
|
|
4264
|
+
const [enabled, setEnabled] = useState10(false);
|
|
4265
|
+
const enabledRef = useRef9(false);
|
|
4266
|
+
useEffect9(() => {
|
|
4267
|
+
enabledRef.current = enabled;
|
|
4268
|
+
}, [enabled]);
|
|
4269
|
+
useEffect9(() => {
|
|
4270
|
+
const client = clientRef.current;
|
|
4271
|
+
if (!client) return;
|
|
4272
|
+
const unsubscribe = client.onLangfuseConfigChange((isEnabled) => {
|
|
4273
|
+
setEnabled(isEnabled);
|
|
4274
|
+
});
|
|
4275
|
+
return unsubscribe;
|
|
4276
|
+
}, [clientRef.current]);
|
|
4277
|
+
const updateFeedbackInStorage = useCallback9(async (messageId, feedback) => {
|
|
4278
|
+
const displayedChatId = getDisplayedChatId();
|
|
4279
|
+
if (!displayedChatId) {
|
|
4280
|
+
console.warn("[useFeedback] No chat ID, cannot update feedback");
|
|
4281
|
+
return;
|
|
4282
|
+
}
|
|
4283
|
+
try {
|
|
4284
|
+
const chat = await repository.loadChat(displayedChatId);
|
|
4285
|
+
if (!chat) {
|
|
4286
|
+
console.error("[useFeedback] Chat not found:", displayedChatId);
|
|
4287
|
+
return;
|
|
4288
|
+
}
|
|
4289
|
+
const message = chat.messages.find((msg) => msg.id === messageId);
|
|
4290
|
+
if (message) {
|
|
4291
|
+
message.feedback = feedback;
|
|
4292
|
+
await repository.saveChat(chat);
|
|
4293
|
+
setMessages(
|
|
4294
|
+
(prevMessages) => prevMessages.map(
|
|
4295
|
+
(msg) => msg.id === messageId ? { ...msg, feedback } : msg
|
|
4296
|
+
)
|
|
4297
|
+
);
|
|
4298
|
+
} else {
|
|
4299
|
+
console.warn("[useFeedback] Message not found:", messageId);
|
|
4300
|
+
}
|
|
4301
|
+
} catch (error) {
|
|
4302
|
+
console.error("[useFeedback] Failed to update feedback:", error);
|
|
4303
|
+
}
|
|
4304
|
+
}, [repository, getDisplayedChatId, setMessages]);
|
|
4305
|
+
const submitFeedback = useCallback9((messageId, traceId, feedback) => {
|
|
4306
|
+
updateFeedbackInStorage(messageId, feedback);
|
|
4307
|
+
const client = clientRef.current;
|
|
4308
|
+
if (client && enabledRef.current) {
|
|
4309
|
+
client.submitFeedback(messageId, traceId, feedback);
|
|
4310
|
+
}
|
|
4311
|
+
}, [clientRef, updateFeedbackInStorage]);
|
|
4312
|
+
return {
|
|
4313
|
+
enabled,
|
|
4314
|
+
submitFeedback
|
|
4315
|
+
};
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4097
4318
|
// src/providers/useAIProvider.tsx
|
|
4098
4319
|
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4099
4320
|
var __UseAIContext = createContext4(null);
|
|
@@ -4175,21 +4396,24 @@ function UseAIProvider({
|
|
|
4175
4396
|
const fileUploadConfig = fileUploadConfigProp === false ? void 0 : fileUploadConfigProp ?? DEFAULT_FILE_UPLOAD_CONFIG;
|
|
4176
4397
|
const theme = { ...defaultTheme, ...customTheme };
|
|
4177
4398
|
const strings = { ...defaultStrings, ...customStrings };
|
|
4178
|
-
const [connected, setConnected] =
|
|
4179
|
-
const [isChatOpen, setIsChatOpen] =
|
|
4180
|
-
const [loading, setLoading] =
|
|
4181
|
-
const [
|
|
4182
|
-
const
|
|
4399
|
+
const [connected, setConnected] = useState11(false);
|
|
4400
|
+
const [isChatOpen, setIsChatOpen] = useState11(false);
|
|
4401
|
+
const [loading, setLoading] = useState11(false);
|
|
4402
|
+
const [messages, setMessages] = useState11([]);
|
|
4403
|
+
const [fileProcessingState, setFileProcessingState] = useState11(null);
|
|
4404
|
+
const handleSetChatOpen = useCallback10((open) => {
|
|
4183
4405
|
setIsChatOpen(open);
|
|
4184
4406
|
onOpenChange?.(open);
|
|
4185
4407
|
}, [onOpenChange]);
|
|
4186
|
-
const [streamingText, setStreamingText] =
|
|
4187
|
-
const streamingChatIdRef =
|
|
4188
|
-
const
|
|
4189
|
-
const
|
|
4408
|
+
const [streamingText, setStreamingText] = useState11("");
|
|
4409
|
+
const streamingChatIdRef = useRef10(null);
|
|
4410
|
+
const [executingTool, setExecutingTool] = useState11(null);
|
|
4411
|
+
const executingToolFallbackRef = useRef10(null);
|
|
4412
|
+
const clientRef = useRef10(null);
|
|
4413
|
+
const repositoryRef = useRef10(
|
|
4190
4414
|
chatRepository || new LocalStorageChatRepository()
|
|
4191
4415
|
);
|
|
4192
|
-
const handleSendMessageRef =
|
|
4416
|
+
const handleSendMessageRef = useRef10(null);
|
|
4193
4417
|
const {
|
|
4194
4418
|
registerTools,
|
|
4195
4419
|
unregisterTools,
|
|
@@ -4211,7 +4435,7 @@ function UseAIProvider({
|
|
|
4211
4435
|
clientRef,
|
|
4212
4436
|
connected
|
|
4213
4437
|
});
|
|
4214
|
-
const stableSendMessage =
|
|
4438
|
+
const stableSendMessage = useCallback10(async (message, attachments) => {
|
|
4215
4439
|
if (handleSendMessageRef.current) {
|
|
4216
4440
|
await handleSendMessageRef.current(message, attachments);
|
|
4217
4441
|
}
|
|
@@ -4219,6 +4443,8 @@ function UseAIProvider({
|
|
|
4219
4443
|
const chatManagement = useChatManagement({
|
|
4220
4444
|
repository: repositoryRef.current,
|
|
4221
4445
|
clientRef,
|
|
4446
|
+
messages,
|
|
4447
|
+
setMessages,
|
|
4222
4448
|
onSendMessage: stableSendMessage,
|
|
4223
4449
|
setOpen: handleSetChatOpen,
|
|
4224
4450
|
connected,
|
|
@@ -4227,7 +4453,6 @@ function UseAIProvider({
|
|
|
4227
4453
|
const {
|
|
4228
4454
|
currentChatId,
|
|
4229
4455
|
pendingChatId,
|
|
4230
|
-
messages,
|
|
4231
4456
|
displayedChatId,
|
|
4232
4457
|
createNewChat,
|
|
4233
4458
|
loadChat,
|
|
@@ -4241,6 +4466,12 @@ function UseAIProvider({
|
|
|
4241
4466
|
getCurrentChat,
|
|
4242
4467
|
updateMetadata
|
|
4243
4468
|
} = chatManagement;
|
|
4469
|
+
const feedback = useFeedback({
|
|
4470
|
+
clientRef,
|
|
4471
|
+
repository: repositoryRef.current,
|
|
4472
|
+
getDisplayedChatId: () => displayedChatId,
|
|
4473
|
+
setMessages
|
|
4474
|
+
});
|
|
4244
4475
|
const {
|
|
4245
4476
|
availableAgents,
|
|
4246
4477
|
defaultAgent,
|
|
@@ -4254,7 +4485,7 @@ function UseAIProvider({
|
|
|
4254
4485
|
renameCommand,
|
|
4255
4486
|
deleteCommand
|
|
4256
4487
|
} = useCommandManagement({ repository: commandRepository });
|
|
4257
|
-
|
|
4488
|
+
useEffect10(() => {
|
|
4258
4489
|
console.log("[UseAIProvider] Initializing client with serverUrl:", serverUrl);
|
|
4259
4490
|
const client = new UseAIClient(serverUrl);
|
|
4260
4491
|
if (mcpHeadersProvider) {
|
|
@@ -4267,9 +4498,19 @@ function UseAIProvider({
|
|
|
4267
4498
|
console.log("[UseAIProvider] Connecting...");
|
|
4268
4499
|
client.connect();
|
|
4269
4500
|
const unsubscribe = client.onEvent("globalChat", async (event) => {
|
|
4270
|
-
if (event.type === EventType.
|
|
4501
|
+
if (event.type === EventType.TOOL_CALL_START) {
|
|
4502
|
+
const e = event;
|
|
4503
|
+
const tool = aggregatedToolsRef.current[e.toolCallName];
|
|
4504
|
+
const title = e.annotations?.title ?? tool?._options?.annotations?.title ?? null;
|
|
4505
|
+
if (!title) {
|
|
4506
|
+
const fallbacks = strings.toolExecution.fallbackMessages;
|
|
4507
|
+
executingToolFallbackRef.current = fallbacks[Math.floor(Math.random() * fallbacks.length)];
|
|
4508
|
+
}
|
|
4509
|
+
setExecutingTool({ toolCallId: e.toolCallId, title });
|
|
4510
|
+
} else if (event.type === EventType.TOOL_CALL_END) {
|
|
4271
4511
|
const toolCallEnd = event;
|
|
4272
4512
|
const toolCallId = toolCallEnd.toolCallId;
|
|
4513
|
+
setExecutingTool((prev) => prev?.toolCallId === toolCallId ? null : prev);
|
|
4273
4514
|
const toolCallData = client["currentToolCalls"].get(toolCallId);
|
|
4274
4515
|
if (!toolCallData) {
|
|
4275
4516
|
console.error(`[Provider] Tool call ${toolCallId} not found`);
|
|
@@ -4319,14 +4560,16 @@ function UseAIProvider({
|
|
|
4319
4560
|
const contentEvent = event;
|
|
4320
4561
|
setStreamingText((prev) => prev + contentEvent.delta);
|
|
4321
4562
|
} else if (event.type === EventType.TEXT_MESSAGE_END) {
|
|
4563
|
+
setStreamingText("");
|
|
4564
|
+
streamingChatIdRef.current = null;
|
|
4565
|
+
} else if (event.type === EventType.RUN_FINISHED) {
|
|
4322
4566
|
const content = client.currentMessageContent;
|
|
4323
4567
|
if (content) {
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
streamingChatIdRef.current = null;
|
|
4328
|
-
setLoading(false);
|
|
4568
|
+
const finishedEvent = event;
|
|
4569
|
+
const traceId = finishedEvent.runId;
|
|
4570
|
+
saveAIResponse(content, void 0, traceId);
|
|
4329
4571
|
}
|
|
4572
|
+
setLoading(false);
|
|
4330
4573
|
} else if (event.type === EventType.RUN_ERROR) {
|
|
4331
4574
|
const errorEvent = event;
|
|
4332
4575
|
const errorCode = errorEvent.message;
|
|
@@ -4345,15 +4588,15 @@ function UseAIProvider({
|
|
|
4345
4588
|
client.disconnect();
|
|
4346
4589
|
};
|
|
4347
4590
|
}, [serverUrl]);
|
|
4348
|
-
|
|
4591
|
+
useEffect10(() => {
|
|
4349
4592
|
const client = clientRef.current;
|
|
4350
4593
|
if (!client) return;
|
|
4351
4594
|
if (mcpHeadersProvider) {
|
|
4352
4595
|
client.setMcpHeadersProvider(mcpHeadersProvider);
|
|
4353
4596
|
}
|
|
4354
4597
|
}, [mcpHeadersProvider]);
|
|
4355
|
-
const lastRegisteredToolsRef =
|
|
4356
|
-
|
|
4598
|
+
const lastRegisteredToolsRef = useRef10("");
|
|
4599
|
+
useEffect10(() => {
|
|
4357
4600
|
const client = clientRef.current;
|
|
4358
4601
|
if (!client || !client.isConnected() || !hasTools) return;
|
|
4359
4602
|
const toolKeys = Object.keys(aggregatedTools).sort().join(",");
|
|
@@ -4371,7 +4614,7 @@ function UseAIProvider({
|
|
|
4371
4614
|
console.error("Failed to register tools:", err);
|
|
4372
4615
|
}
|
|
4373
4616
|
}, [hasTools, aggregatedTools, connected]);
|
|
4374
|
-
const handleSendMessage =
|
|
4617
|
+
const handleSendMessage = useCallback10(async (message, attachments) => {
|
|
4375
4618
|
if (!clientRef.current) return;
|
|
4376
4619
|
setStreamingText("");
|
|
4377
4620
|
const activatedChatId = activatePendingChat();
|
|
@@ -4467,6 +4710,9 @@ function UseAIProvider({
|
|
|
4467
4710
|
}
|
|
4468
4711
|
};
|
|
4469
4712
|
const effectiveStreamingText = streamingChatIdRef.current === displayedChatId ? streamingText : "";
|
|
4713
|
+
const executingToolDisplay = executingTool ? {
|
|
4714
|
+
displayText: executingTool.title ?? executingToolFallbackRef.current ?? strings.toolExecution.fallbackMessages[0]
|
|
4715
|
+
} : null;
|
|
4470
4716
|
const chatUIContextValue = {
|
|
4471
4717
|
connected,
|
|
4472
4718
|
loading,
|
|
@@ -4499,6 +4745,11 @@ function UseAIProvider({
|
|
|
4499
4745
|
ui: {
|
|
4500
4746
|
isOpen: isChatOpen,
|
|
4501
4747
|
setOpen: handleSetChatOpen
|
|
4748
|
+
},
|
|
4749
|
+
executingTool: executingToolDisplay,
|
|
4750
|
+
feedback: {
|
|
4751
|
+
enabled: feedback.enabled,
|
|
4752
|
+
submit: feedback.submitFeedback
|
|
4502
4753
|
}
|
|
4503
4754
|
};
|
|
4504
4755
|
const isUIDisabled = CustomButton === null || CustomChat === null;
|
|
@@ -4525,7 +4776,10 @@ function UseAIProvider({
|
|
|
4525
4776
|
commands,
|
|
4526
4777
|
onSaveCommand: saveCommand,
|
|
4527
4778
|
onRenameCommand: renameCommand,
|
|
4528
|
-
onDeleteCommand: deleteCommand
|
|
4779
|
+
onDeleteCommand: deleteCommand,
|
|
4780
|
+
executingTool: executingToolDisplay,
|
|
4781
|
+
feedbackEnabled: feedback.enabled,
|
|
4782
|
+
onFeedback: feedback.submitFeedback
|
|
4529
4783
|
};
|
|
4530
4784
|
const renderDefaultChat = () => {
|
|
4531
4785
|
if (isUIDisabled) return null;
|
|
@@ -4589,11 +4843,11 @@ function useAIContext() {
|
|
|
4589
4843
|
}
|
|
4590
4844
|
|
|
4591
4845
|
// src/hooks/useStableTools.ts
|
|
4592
|
-
import { useRef as
|
|
4846
|
+
import { useRef as useRef11 } from "react";
|
|
4593
4847
|
function useStableTools(tools) {
|
|
4594
|
-
const latestToolsRef =
|
|
4595
|
-
const stableToolsRef =
|
|
4596
|
-
const prevToolNamesRef =
|
|
4848
|
+
const latestToolsRef = useRef11({});
|
|
4849
|
+
const stableToolsRef = useRef11({});
|
|
4850
|
+
const prevToolNamesRef = useRef11("");
|
|
4597
4851
|
if (!tools) {
|
|
4598
4852
|
latestToolsRef.current = {};
|
|
4599
4853
|
return void 0;
|
|
@@ -4663,25 +4917,25 @@ function useAI(options = {}) {
|
|
|
4663
4917
|
const { connected, tools, client, prompts } = useAIContext();
|
|
4664
4918
|
const { register: registerTools, unregister: unregisterTools } = tools;
|
|
4665
4919
|
const { update: updatePrompt, registerWaiter, unregisterWaiter } = prompts;
|
|
4666
|
-
const [response, setResponse] =
|
|
4667
|
-
const [loading, setLoading] =
|
|
4668
|
-
const [error, setError] =
|
|
4669
|
-
const hookId =
|
|
4670
|
-
const toolsRef =
|
|
4671
|
-
const componentRef =
|
|
4672
|
-
const promptChangeResolvers =
|
|
4920
|
+
const [response, setResponse] = useState12(null);
|
|
4921
|
+
const [loading, setLoading] = useState12(false);
|
|
4922
|
+
const [error, setError] = useState12(null);
|
|
4923
|
+
const hookId = useRef12(`useAI-${Math.random().toString(36).substr(2, 9)}`);
|
|
4924
|
+
const toolsRef = useRef12({});
|
|
4925
|
+
const componentRef = useRef12(null);
|
|
4926
|
+
const promptChangeResolvers = useRef12([]);
|
|
4673
4927
|
const stableTools = useStableTools(options.tools);
|
|
4674
4928
|
const toolsKey = useMemo6(() => {
|
|
4675
4929
|
if (!options.tools) return "";
|
|
4676
4930
|
return Object.keys(options.tools).sort().join(",");
|
|
4677
4931
|
}, [options.tools]);
|
|
4678
4932
|
const memoizedSuggestions = useMemo6(() => options.suggestions, [options.suggestions]);
|
|
4679
|
-
|
|
4933
|
+
useEffect11(() => {
|
|
4680
4934
|
if (componentRef.current) {
|
|
4681
4935
|
componentRef.current.setAttribute("data-useai-context", "true");
|
|
4682
4936
|
}
|
|
4683
4937
|
}, []);
|
|
4684
|
-
const waitForPromptChange =
|
|
4938
|
+
const waitForPromptChange = useCallback11(() => {
|
|
4685
4939
|
return new Promise((resolve) => {
|
|
4686
4940
|
const timeoutMs = 100;
|
|
4687
4941
|
const timeoutId = setTimeout(() => {
|
|
@@ -4698,14 +4952,14 @@ function useAI(options = {}) {
|
|
|
4698
4952
|
promptChangeResolvers.current.push(resolveAndCleanup);
|
|
4699
4953
|
});
|
|
4700
4954
|
}, []);
|
|
4701
|
-
|
|
4955
|
+
useEffect11(() => {
|
|
4702
4956
|
if (!enabled || options.invisible) return;
|
|
4703
4957
|
registerWaiter(hookId.current, waitForPromptChange);
|
|
4704
4958
|
return () => {
|
|
4705
4959
|
unregisterWaiter(hookId.current);
|
|
4706
4960
|
};
|
|
4707
4961
|
}, [enabled, options.invisible, registerWaiter, unregisterWaiter, waitForPromptChange]);
|
|
4708
|
-
|
|
4962
|
+
useEffect11(() => {
|
|
4709
4963
|
if (!enabled) return;
|
|
4710
4964
|
updatePrompt(hookId.current, options.prompt, memoizedSuggestions);
|
|
4711
4965
|
if (promptChangeResolvers.current.length > 0) {
|
|
@@ -4713,15 +4967,15 @@ function useAI(options = {}) {
|
|
|
4713
4967
|
promptChangeResolvers.current = [];
|
|
4714
4968
|
}
|
|
4715
4969
|
}, [enabled, options.prompt, memoizedSuggestions, updatePrompt]);
|
|
4716
|
-
const updatePromptRef =
|
|
4970
|
+
const updatePromptRef = useRef12(updatePrompt);
|
|
4717
4971
|
updatePromptRef.current = updatePrompt;
|
|
4718
|
-
|
|
4972
|
+
useEffect11(() => {
|
|
4719
4973
|
const id = hookId.current;
|
|
4720
4974
|
return () => {
|
|
4721
4975
|
updatePromptRef.current(id, void 0, void 0);
|
|
4722
4976
|
};
|
|
4723
4977
|
}, []);
|
|
4724
|
-
|
|
4978
|
+
useEffect11(() => {
|
|
4725
4979
|
if (!enabled) return;
|
|
4726
4980
|
if (stableTools) {
|
|
4727
4981
|
const componentId = options.id || componentRef.current?.id;
|
|
@@ -4735,7 +4989,7 @@ function useAI(options = {}) {
|
|
|
4735
4989
|
}
|
|
4736
4990
|
};
|
|
4737
4991
|
}, [enabled, toolsKey, stableTools, options.id, options.invisible, registerTools, unregisterTools]);
|
|
4738
|
-
|
|
4992
|
+
useEffect11(() => {
|
|
4739
4993
|
if (!enabled || !client) return;
|
|
4740
4994
|
const unsubscribe = client.onEvent(hookId.current, (event) => {
|
|
4741
4995
|
handleAGUIEvent(event);
|
|
@@ -4744,7 +4998,7 @@ function useAI(options = {}) {
|
|
|
4744
4998
|
unsubscribe();
|
|
4745
4999
|
};
|
|
4746
5000
|
}, [enabled, client]);
|
|
4747
|
-
const handleAGUIEvent =
|
|
5001
|
+
const handleAGUIEvent = useCallback11(async (event) => {
|
|
4748
5002
|
switch (event.type) {
|
|
4749
5003
|
case EventType.TEXT_MESSAGE_END: {
|
|
4750
5004
|
const content = client?.currentMessageContent;
|
|
@@ -4764,7 +5018,7 @@ function useAI(options = {}) {
|
|
|
4764
5018
|
}
|
|
4765
5019
|
}
|
|
4766
5020
|
}, [client, options.onError]);
|
|
4767
|
-
const generate =
|
|
5021
|
+
const generate = useCallback11(async (prompt) => {
|
|
4768
5022
|
if (!enabled) {
|
|
4769
5023
|
const error2 = new Error("AI features are disabled");
|
|
4770
5024
|
setError(error2);
|
|
@@ -4800,17 +5054,17 @@ function useAI(options = {}) {
|
|
|
4800
5054
|
}
|
|
4801
5055
|
|
|
4802
5056
|
// src/useAIWorkflow.ts
|
|
4803
|
-
import { useState as
|
|
5057
|
+
import { useState as useState13, useCallback as useCallback12, useRef as useRef13, useEffect as useEffect12 } from "react";
|
|
4804
5058
|
import { EventType as EventType3 } from "@meetsmore-oss/use-ai-core";
|
|
4805
5059
|
import { v4 as uuidv43 } from "uuid";
|
|
4806
5060
|
function useAIWorkflow(runner, workflowId) {
|
|
4807
5061
|
const { connected, client } = useAIContext();
|
|
4808
|
-
const [status, setStatus] =
|
|
4809
|
-
const [text, setText] =
|
|
4810
|
-
const [error, setError] =
|
|
4811
|
-
const currentWorkflowRef =
|
|
4812
|
-
const eventListenerIdRef =
|
|
4813
|
-
const handleWorkflowEvent =
|
|
5062
|
+
const [status, setStatus] = useState13("idle");
|
|
5063
|
+
const [text, setText] = useState13(null);
|
|
5064
|
+
const [error, setError] = useState13(null);
|
|
5065
|
+
const currentWorkflowRef = useRef13(null);
|
|
5066
|
+
const eventListenerIdRef = useRef13(`useAIWorkflow-${Math.random().toString(36).substr(2, 9)}`);
|
|
5067
|
+
const handleWorkflowEvent = useCallback12(async (event) => {
|
|
4814
5068
|
const currentWorkflow = currentWorkflowRef.current;
|
|
4815
5069
|
if (!currentWorkflow) return;
|
|
4816
5070
|
if (event.type === EventType3.RUN_STARTED) {
|
|
@@ -4895,14 +5149,14 @@ function useAIWorkflow(runner, workflowId) {
|
|
|
4895
5149
|
}
|
|
4896
5150
|
}
|
|
4897
5151
|
}, [client]);
|
|
4898
|
-
|
|
5152
|
+
useEffect12(() => {
|
|
4899
5153
|
if (!client) return;
|
|
4900
5154
|
const unsubscribe = client.onEvent(eventListenerIdRef.current, handleWorkflowEvent);
|
|
4901
5155
|
return () => {
|
|
4902
5156
|
unsubscribe();
|
|
4903
5157
|
};
|
|
4904
5158
|
}, [client, handleWorkflowEvent]);
|
|
4905
|
-
const trigger =
|
|
5159
|
+
const trigger = useCallback12(async (options) => {
|
|
4906
5160
|
if (!client?.isConnected()) {
|
|
4907
5161
|
const err = new Error("Not connected to server");
|
|
4908
5162
|
setError(err);
|
|
@@ -4991,6 +5245,7 @@ export {
|
|
|
4991
5245
|
useChatManagement,
|
|
4992
5246
|
useCommandManagement,
|
|
4993
5247
|
useDropdownState,
|
|
5248
|
+
useFeedback,
|
|
4994
5249
|
useFileUpload,
|
|
4995
5250
|
usePromptState,
|
|
4996
5251
|
useSlashCommands,
|