@hef2024/llmasaservice-ui 0.16.10 → 0.17.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/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +70 -69
- package/dist/index.mjs +70 -69
- package/package.json +1 -1
- package/src/AIAgentPanel.tsx +84 -14
- package/src/AIChatPanel.tsx +36 -80
- package/src/components/ui/Button.tsx +2 -0
- package/src/components/ui/Dialog.tsx +2 -0
- package/src/components/ui/Input.tsx +2 -0
- package/src/components/ui/Select.tsx +2 -0
- package/src/components/ui/Tooltip.tsx +2 -0
- package/src/components/ui/index.ts +2 -0
package/dist/index.d.mts
CHANGED
|
@@ -170,6 +170,12 @@ interface AgentConfig {
|
|
|
170
170
|
localName?: string;
|
|
171
171
|
avatarUrl?: string;
|
|
172
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Imperative handle for programmatic control of AIAgentPanel
|
|
175
|
+
*/
|
|
176
|
+
interface AIAgentPanelHandle {
|
|
177
|
+
startNewConversation: (prompt: string, agent?: string) => void;
|
|
178
|
+
}
|
|
173
179
|
/**
|
|
174
180
|
* Props for AIAgentPanel
|
|
175
181
|
*/
|
|
@@ -218,12 +224,15 @@ interface AIAgentPanelProps {
|
|
|
218
224
|
clickCode?: string;
|
|
219
225
|
style?: string;
|
|
220
226
|
}[];
|
|
227
|
+
initialPrompt?: string;
|
|
228
|
+
initialMessage?: string;
|
|
229
|
+
hideInitialPrompt?: boolean;
|
|
221
230
|
followOnQuestions?: string[];
|
|
222
231
|
followOnPrompt?: string;
|
|
223
232
|
historyListLimit?: number;
|
|
224
233
|
showConversationHistory?: boolean;
|
|
225
234
|
}
|
|
226
|
-
declare const AIAgentPanel: React__default.
|
|
235
|
+
declare const AIAgentPanel: React__default.ForwardRefExoticComponent<AIAgentPanelProps & React__default.RefAttributes<AIAgentPanelHandle>>;
|
|
227
236
|
|
|
228
237
|
/**
|
|
229
238
|
* AIChatPanel - A modern chat interface using shadcn-style components
|
package/dist/index.d.ts
CHANGED
|
@@ -170,6 +170,12 @@ interface AgentConfig {
|
|
|
170
170
|
localName?: string;
|
|
171
171
|
avatarUrl?: string;
|
|
172
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Imperative handle for programmatic control of AIAgentPanel
|
|
175
|
+
*/
|
|
176
|
+
interface AIAgentPanelHandle {
|
|
177
|
+
startNewConversation: (prompt: string, agent?: string) => void;
|
|
178
|
+
}
|
|
173
179
|
/**
|
|
174
180
|
* Props for AIAgentPanel
|
|
175
181
|
*/
|
|
@@ -218,12 +224,15 @@ interface AIAgentPanelProps {
|
|
|
218
224
|
clickCode?: string;
|
|
219
225
|
style?: string;
|
|
220
226
|
}[];
|
|
227
|
+
initialPrompt?: string;
|
|
228
|
+
initialMessage?: string;
|
|
229
|
+
hideInitialPrompt?: boolean;
|
|
221
230
|
followOnQuestions?: string[];
|
|
222
231
|
followOnPrompt?: string;
|
|
223
232
|
historyListLimit?: number;
|
|
224
233
|
showConversationHistory?: boolean;
|
|
225
234
|
}
|
|
226
|
-
declare const AIAgentPanel: React__default.
|
|
235
|
+
declare const AIAgentPanel: React__default.ForwardRefExoticComponent<AIAgentPanelProps & React__default.RefAttributes<AIAgentPanelHandle>>;
|
|
227
236
|
|
|
228
237
|
/**
|
|
229
238
|
* AIChatPanel - A modern chat interface using shadcn-style components
|
package/dist/index.js
CHANGED
|
@@ -3669,6 +3669,7 @@ var AIChatPanel = ({
|
|
|
3669
3669
|
const prevIdleRef = (0, import_react11.useRef)(true);
|
|
3670
3670
|
const hasNotifiedCompletionRef = (0, import_react11.useRef)(true);
|
|
3671
3671
|
const latestHistoryRef = (0, import_react11.useRef)(initialHistory);
|
|
3672
|
+
const initialPromptSentRef = (0, import_react11.useRef)(false);
|
|
3672
3673
|
(0, import_react11.useEffect)(() => {
|
|
3673
3674
|
if (!initialHistory) return;
|
|
3674
3675
|
setHistory((prev) => {
|
|
@@ -3913,11 +3914,22 @@ var AIChatPanel = ({
|
|
|
3913
3914
|
const promptToSend = promptText;
|
|
3914
3915
|
if (!promptToSend || !promptToSend.trim()) return;
|
|
3915
3916
|
setIsLoading(true);
|
|
3917
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3918
|
+
const promptKey = `${timestamp}:${promptToSend.trim()}`;
|
|
3919
|
+
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
3920
|
+
[promptKey]: { content: "", callId: "" }
|
|
3921
|
+
}));
|
|
3922
|
+
setLastPrompt(promptToSend.trim());
|
|
3923
|
+
setLastKey(promptKey);
|
|
3924
|
+
setTimeout(() => {
|
|
3925
|
+
scrollToBottom();
|
|
3926
|
+
}, 0);
|
|
3916
3927
|
console.log("AIChatPanel.continueChat - about to call ensureConversation");
|
|
3917
3928
|
ensureConversation().then((convId) => {
|
|
3918
3929
|
console.log("AIChatPanel.continueChat - ensureConversation resolved with:", convId);
|
|
3919
3930
|
const messagesAndHistory = [];
|
|
3920
3931
|
Object.entries(history).forEach(([historyPrompt, historyEntry]) => {
|
|
3932
|
+
if (historyPrompt === promptKey) return;
|
|
3921
3933
|
let promptForHistory = historyPrompt;
|
|
3922
3934
|
const isoTimestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:/;
|
|
3923
3935
|
if (isoTimestampRegex.test(historyPrompt)) {
|
|
@@ -3930,13 +3942,8 @@ var AIChatPanel = ({
|
|
|
3930
3942
|
messagesAndHistory.push({ role: "user", content: promptForHistory });
|
|
3931
3943
|
messagesAndHistory.push({ role: "assistant", content: historyEntry.content });
|
|
3932
3944
|
});
|
|
3933
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3934
|
-
const promptKey = `${timestamp}:${promptToSend.trim()}`;
|
|
3935
|
-
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
3936
|
-
[promptKey]: { content: "", callId: "" }
|
|
3937
|
-
}));
|
|
3938
3945
|
let fullPromptToSend = promptToSend.trim();
|
|
3939
|
-
if (
|
|
3946
|
+
if (messagesAndHistory.length === 0 && promptTemplate) {
|
|
3940
3947
|
fullPromptToSend = promptTemplate.replace("{{prompt}}", fullPromptToSend);
|
|
3941
3948
|
}
|
|
3942
3949
|
if (followOnPrompt) {
|
|
@@ -3963,17 +3970,12 @@ ${followOnPrompt}`;
|
|
|
3963
3970
|
// Use the conversation ID from ensureConversation
|
|
3964
3971
|
newController
|
|
3965
3972
|
);
|
|
3966
|
-
setLastPrompt(promptToSend.trim());
|
|
3967
3973
|
setLastMessages(messagesAndHistory);
|
|
3968
|
-
setLastKey(promptKey);
|
|
3969
3974
|
if (convId && onConversationCreated) {
|
|
3970
3975
|
setTimeout(() => {
|
|
3971
3976
|
onConversationCreated(convId);
|
|
3972
3977
|
}, 100);
|
|
3973
3978
|
}
|
|
3974
|
-
setTimeout(() => {
|
|
3975
|
-
scrollToBottom();
|
|
3976
|
-
}, 0);
|
|
3977
3979
|
});
|
|
3978
3980
|
}, [
|
|
3979
3981
|
idle,
|
|
@@ -4128,50 +4130,11 @@ ${followOnPrompt}`;
|
|
|
4128
4130
|
};
|
|
4129
4131
|
}, []);
|
|
4130
4132
|
(0, import_react11.useEffect)(() => {
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
}
|
|
4135
|
-
if (initialPrompt && initialPrompt !== "" && initialPrompt !== lastPrompt && !hasLoadedHistory) {
|
|
4136
|
-
setIsLoading(true);
|
|
4137
|
-
setThinkingBlocks([]);
|
|
4138
|
-
setCurrentThinkingIndex(0);
|
|
4139
|
-
setUserHasScrolled(false);
|
|
4140
|
-
ensureConversation().then((convId) => {
|
|
4141
|
-
const controller = new AbortController();
|
|
4142
|
-
setLastController(controller);
|
|
4143
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4144
|
-
const promptKey = `${timestamp}:${initialPrompt}`;
|
|
4145
|
-
setHistory({ [promptKey]: { content: "", callId: "" } });
|
|
4146
|
-
let fullPrompt = initialPrompt;
|
|
4147
|
-
if (promptTemplate) {
|
|
4148
|
-
fullPrompt = promptTemplate.replace("{{prompt}}", initialPrompt);
|
|
4149
|
-
}
|
|
4150
|
-
send(
|
|
4151
|
-
fullPrompt,
|
|
4152
|
-
[],
|
|
4153
|
-
[
|
|
4154
|
-
...dataWithExtras(),
|
|
4155
|
-
{ key: "--messages", data: "0" }
|
|
4156
|
-
],
|
|
4157
|
-
true,
|
|
4158
|
-
true,
|
|
4159
|
-
service,
|
|
4160
|
-
convId,
|
|
4161
|
-
// Use conversation ID from ensureConversation
|
|
4162
|
-
controller
|
|
4163
|
-
);
|
|
4164
|
-
setLastPrompt(initialPrompt);
|
|
4165
|
-
setLastMessages([]);
|
|
4166
|
-
setLastKey(promptKey);
|
|
4167
|
-
if (convId && onConversationCreated) {
|
|
4168
|
-
setTimeout(() => {
|
|
4169
|
-
onConversationCreated(convId);
|
|
4170
|
-
}, 100);
|
|
4171
|
-
}
|
|
4172
|
-
});
|
|
4133
|
+
if (initialPrompt && initialPrompt !== "" && !initialPromptSentRef.current) {
|
|
4134
|
+
initialPromptSentRef.current = true;
|
|
4135
|
+
continueChat(initialPrompt);
|
|
4173
4136
|
}
|
|
4174
|
-
}, [initialPrompt,
|
|
4137
|
+
}, [initialPrompt, continueChat]);
|
|
4175
4138
|
const CodeBlock = (0, import_react11.useCallback)((_a) => {
|
|
4176
4139
|
var _b = _a, { node, inline, className, children } = _b, props = __objRest(_b, ["node", "inline", "className", "children"]);
|
|
4177
4140
|
const match = /language-(\w+)/.exec(className || "");
|
|
@@ -4688,6 +4651,9 @@ var ChatPanelWrapper = ({
|
|
|
4688
4651
|
effectiveCustomer,
|
|
4689
4652
|
showPoweredBy,
|
|
4690
4653
|
actions,
|
|
4654
|
+
initialPrompt,
|
|
4655
|
+
initialMessage,
|
|
4656
|
+
hideInitialPrompt,
|
|
4691
4657
|
followOnQuestions,
|
|
4692
4658
|
followOnPrompt,
|
|
4693
4659
|
agentOptions,
|
|
@@ -4698,7 +4664,8 @@ var ChatPanelWrapper = ({
|
|
|
4698
4664
|
totalContextTokens,
|
|
4699
4665
|
maxContextTokens,
|
|
4700
4666
|
enableContextDetailView,
|
|
4701
|
-
onConversationCreated
|
|
4667
|
+
onConversationCreated,
|
|
4668
|
+
conversationInitialPrompt
|
|
4702
4669
|
}) => {
|
|
4703
4670
|
var _a, _b;
|
|
4704
4671
|
const convAgentProfile = getAgent(activeConv.agentId);
|
|
@@ -4734,6 +4701,7 @@ var ChatPanelWrapper = ({
|
|
|
4734
4701
|
const mcpServers = (0, import_react13.useMemo)(() => {
|
|
4735
4702
|
return (convAgentProfile == null ? void 0 : convAgentProfile.mcpServers) || EMPTY_ARRAY;
|
|
4736
4703
|
}, [convAgentProfile == null ? void 0 : convAgentProfile.mcpServers]);
|
|
4704
|
+
const effectiveInitialPrompt = conversationInitialPrompt || initialPrompt;
|
|
4737
4705
|
if (!convAgentMetadata) return null;
|
|
4738
4706
|
return /* @__PURE__ */ import_react13.default.createElement(
|
|
4739
4707
|
"div",
|
|
@@ -4750,10 +4718,10 @@ var ChatPanelWrapper = ({
|
|
|
4750
4718
|
title: "",
|
|
4751
4719
|
theme,
|
|
4752
4720
|
promptTemplate: convAgentMetadata.displayPromptTemplate || "{{prompt}}",
|
|
4753
|
-
initialMessage: convAgentMetadata.displayStartMessageOrPrompt === "message" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0,
|
|
4754
|
-
initialPrompt: convAgentMetadata.displayStartMessageOrPrompt === "prompt" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0,
|
|
4721
|
+
initialMessage: initialMessage || (convAgentMetadata.displayStartMessageOrPrompt === "message" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0),
|
|
4722
|
+
initialPrompt: effectiveInitialPrompt || (convAgentMetadata.displayStartMessageOrPrompt === "prompt" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0),
|
|
4755
4723
|
placeholder: convAgentMetadata.displayPlaceholder || "Type a message...",
|
|
4756
|
-
hideInitialPrompt: (_a = convAgentMetadata.displayHideInitialPrompt) != null ? _a : true,
|
|
4724
|
+
hideInitialPrompt: (_a = hideInitialPrompt != null ? hideInitialPrompt : convAgentMetadata.displayHideInitialPrompt) != null ? _a : true,
|
|
4757
4725
|
data: chatPanelData,
|
|
4758
4726
|
agent: activeConv.agentId,
|
|
4759
4727
|
conversation: activeConv.conversationId.startsWith("new-") ? void 0 : activeConv.conversationId,
|
|
@@ -4787,7 +4755,7 @@ var ChatPanelWrapper = ({
|
|
|
4787
4755
|
);
|
|
4788
4756
|
};
|
|
4789
4757
|
ChatPanelWrapper.displayName = "ChatPanelWrapper";
|
|
4790
|
-
var AIAgentPanel = ({
|
|
4758
|
+
var AIAgentPanel = import_react13.default.forwardRef(({
|
|
4791
4759
|
agents,
|
|
4792
4760
|
defaultAgent,
|
|
4793
4761
|
customerId,
|
|
@@ -4819,11 +4787,14 @@ var AIAgentPanel = ({
|
|
|
4819
4787
|
showPoweredBy = true,
|
|
4820
4788
|
conversation,
|
|
4821
4789
|
actions = [],
|
|
4790
|
+
initialPrompt,
|
|
4791
|
+
initialMessage,
|
|
4792
|
+
hideInitialPrompt,
|
|
4822
4793
|
followOnQuestions = [],
|
|
4823
4794
|
followOnPrompt = "",
|
|
4824
4795
|
historyListLimit = 50,
|
|
4825
4796
|
showConversationHistory = true
|
|
4826
|
-
}) => {
|
|
4797
|
+
}, ref) => {
|
|
4827
4798
|
var _a, _b, _c, _d;
|
|
4828
4799
|
const [isCollapsed, setIsCollapsed] = (0, import_react13.useState)(defaultCollapsed);
|
|
4829
4800
|
const [isHistoryCollapsed, setIsHistoryCollapsed] = (0, import_react13.useState)(() => {
|
|
@@ -4905,6 +4876,29 @@ var AIAgentPanel = ({
|
|
|
4905
4876
|
activeConversationsRef.current = activeConversations;
|
|
4906
4877
|
const currentConversationIdRef = (0, import_react13.useRef)(currentConversationId);
|
|
4907
4878
|
currentConversationIdRef.current = currentConversationId;
|
|
4879
|
+
import_react13.default.useImperativeHandle(ref, () => ({
|
|
4880
|
+
startNewConversation: (prompt, agent) => {
|
|
4881
|
+
const targetAgent = agent || currentAgentId;
|
|
4882
|
+
const tempId = `new-${Date.now()}`;
|
|
4883
|
+
setActiveConversations((prev) => {
|
|
4884
|
+
const next = new Map(prev);
|
|
4885
|
+
next.set(tempId, {
|
|
4886
|
+
conversationId: tempId,
|
|
4887
|
+
stableKey: tempId,
|
|
4888
|
+
agentId: targetAgent,
|
|
4889
|
+
history: {},
|
|
4890
|
+
isLoading: false,
|
|
4891
|
+
title: "New conversation",
|
|
4892
|
+
conversationInitialPrompt: prompt
|
|
4893
|
+
});
|
|
4894
|
+
return next;
|
|
4895
|
+
});
|
|
4896
|
+
setCurrentConversationId(tempId);
|
|
4897
|
+
if (onConversationChange) {
|
|
4898
|
+
onConversationChange(tempId);
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4901
|
+
}), [currentAgentId, onConversationChange]);
|
|
4908
4902
|
const [showContextNotification, setShowContextNotification] = (0, import_react13.useState)(false);
|
|
4909
4903
|
const prevContextRef = (0, import_react13.useRef)(null);
|
|
4910
4904
|
const contextNotificationTimeoutRef = (0, import_react13.useRef)(null);
|
|
@@ -5248,15 +5242,17 @@ var AIAgentPanel = ({
|
|
|
5248
5242
|
let filtered = apiConversations;
|
|
5249
5243
|
if (searchQuery) {
|
|
5250
5244
|
const query = searchQuery.toLowerCase();
|
|
5251
|
-
filtered = filtered.filter(
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5245
|
+
filtered = filtered.filter((conv) => {
|
|
5246
|
+
var _a2, _b2;
|
|
5247
|
+
if ((_a2 = conv.title) == null ? void 0 : _a2.toLowerCase().includes(query)) return true;
|
|
5248
|
+
if ((_b2 = conv.summary) == null ? void 0 : _b2.toLowerCase().includes(query)) return true;
|
|
5249
|
+
const firstPrompt = conversationFirstPrompts[conv.conversationId];
|
|
5250
|
+
if (firstPrompt == null ? void 0 : firstPrompt.toLowerCase().includes(query)) return true;
|
|
5251
|
+
return false;
|
|
5252
|
+
});
|
|
5257
5253
|
}
|
|
5258
5254
|
return groupConversationsByTime(filtered, true);
|
|
5259
|
-
}, [apiConversations, searchQuery]);
|
|
5255
|
+
}, [apiConversations, searchQuery, conversationFirstPrompts]);
|
|
5260
5256
|
const effectiveCustomer = (0, import_react13.useMemo)(() => {
|
|
5261
5257
|
return __spreadProps(__spreadValues({}, customer), {
|
|
5262
5258
|
customer_id: customerId
|
|
@@ -5865,6 +5861,9 @@ var AIAgentPanel = ({
|
|
|
5865
5861
|
effectiveCustomer,
|
|
5866
5862
|
showPoweredBy,
|
|
5867
5863
|
actions,
|
|
5864
|
+
initialPrompt,
|
|
5865
|
+
initialMessage,
|
|
5866
|
+
hideInitialPrompt,
|
|
5868
5867
|
followOnQuestions,
|
|
5869
5868
|
followOnPrompt,
|
|
5870
5869
|
agentOptions,
|
|
@@ -5875,7 +5874,8 @@ var AIAgentPanel = ({
|
|
|
5875
5874
|
totalContextTokens: mergedContext.totalTokens || 0,
|
|
5876
5875
|
maxContextTokens,
|
|
5877
5876
|
enableContextDetailView,
|
|
5878
|
-
onConversationCreated: handleConversationCreated
|
|
5877
|
+
onConversationCreated: handleConversationCreated,
|
|
5878
|
+
conversationInitialPrompt: activeConv.conversationInitialPrompt
|
|
5879
5879
|
}
|
|
5880
5880
|
)), loadingConversationId && /* @__PURE__ */ import_react13.default.createElement("div", { className: "ai-agent-panel__conversation-loading-overlay" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ import_react13.default.createElement("p", null, "Loading conversation...")), currentAgentMetadata && activeConversationsList.length === 0 && !loadingConversationId && /* @__PURE__ */ import_react13.default.createElement("div", { className: "ai-agent-panel__empty-chat" }, /* @__PURE__ */ import_react13.default.createElement(MessageIcon, null), /* @__PURE__ */ import_react13.default.createElement("p", null, "Select a conversation or start a new one"), /* @__PURE__ */ import_react13.default.createElement(Button, { variant: "default", size: "sm", onClick: handleNewConversation }, "New Conversation")), agentsLoading && !currentAgentMetadata && /* @__PURE__ */ import_react13.default.createElement("div", { className: "ai-agent-panel__loading" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ import_react13.default.createElement("p", null, "Loading agent..."))),
|
|
5881
5881
|
/* @__PURE__ */ import_react13.default.createElement(
|
|
@@ -5889,7 +5889,8 @@ var AIAgentPanel = ({
|
|
|
5889
5889
|
/* @__PURE__ */ import_react13.default.createElement(DialogFooter, null, /* @__PURE__ */ import_react13.default.createElement(Button, { variant: "outline", onClick: handleHandoffCancel }, "Stay with current agent"), /* @__PURE__ */ import_react13.default.createElement(Button, { onClick: handleHandoffConfirm }, "Switch agent"))
|
|
5890
5890
|
)
|
|
5891
5891
|
);
|
|
5892
|
-
};
|
|
5892
|
+
});
|
|
5893
|
+
AIAgentPanel.displayName = "AIAgentPanel";
|
|
5893
5894
|
var AIAgentPanel_default = AIAgentPanel;
|
|
5894
5895
|
|
|
5895
5896
|
// src/hooks/useConversationStore.ts
|
package/dist/index.mjs
CHANGED
|
@@ -3636,6 +3636,7 @@ var AIChatPanel = ({
|
|
|
3636
3636
|
const prevIdleRef = useRef5(true);
|
|
3637
3637
|
const hasNotifiedCompletionRef = useRef5(true);
|
|
3638
3638
|
const latestHistoryRef = useRef5(initialHistory);
|
|
3639
|
+
const initialPromptSentRef = useRef5(false);
|
|
3639
3640
|
useEffect7(() => {
|
|
3640
3641
|
if (!initialHistory) return;
|
|
3641
3642
|
setHistory((prev) => {
|
|
@@ -3880,11 +3881,22 @@ var AIChatPanel = ({
|
|
|
3880
3881
|
const promptToSend = promptText;
|
|
3881
3882
|
if (!promptToSend || !promptToSend.trim()) return;
|
|
3882
3883
|
setIsLoading(true);
|
|
3884
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3885
|
+
const promptKey = `${timestamp}:${promptToSend.trim()}`;
|
|
3886
|
+
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
3887
|
+
[promptKey]: { content: "", callId: "" }
|
|
3888
|
+
}));
|
|
3889
|
+
setLastPrompt(promptToSend.trim());
|
|
3890
|
+
setLastKey(promptKey);
|
|
3891
|
+
setTimeout(() => {
|
|
3892
|
+
scrollToBottom();
|
|
3893
|
+
}, 0);
|
|
3883
3894
|
console.log("AIChatPanel.continueChat - about to call ensureConversation");
|
|
3884
3895
|
ensureConversation().then((convId) => {
|
|
3885
3896
|
console.log("AIChatPanel.continueChat - ensureConversation resolved with:", convId);
|
|
3886
3897
|
const messagesAndHistory = [];
|
|
3887
3898
|
Object.entries(history).forEach(([historyPrompt, historyEntry]) => {
|
|
3899
|
+
if (historyPrompt === promptKey) return;
|
|
3888
3900
|
let promptForHistory = historyPrompt;
|
|
3889
3901
|
const isoTimestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:/;
|
|
3890
3902
|
if (isoTimestampRegex.test(historyPrompt)) {
|
|
@@ -3897,13 +3909,8 @@ var AIChatPanel = ({
|
|
|
3897
3909
|
messagesAndHistory.push({ role: "user", content: promptForHistory });
|
|
3898
3910
|
messagesAndHistory.push({ role: "assistant", content: historyEntry.content });
|
|
3899
3911
|
});
|
|
3900
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3901
|
-
const promptKey = `${timestamp}:${promptToSend.trim()}`;
|
|
3902
|
-
setHistory((prevHistory) => __spreadProps(__spreadValues({}, prevHistory), {
|
|
3903
|
-
[promptKey]: { content: "", callId: "" }
|
|
3904
|
-
}));
|
|
3905
3912
|
let fullPromptToSend = promptToSend.trim();
|
|
3906
|
-
if (
|
|
3913
|
+
if (messagesAndHistory.length === 0 && promptTemplate) {
|
|
3907
3914
|
fullPromptToSend = promptTemplate.replace("{{prompt}}", fullPromptToSend);
|
|
3908
3915
|
}
|
|
3909
3916
|
if (followOnPrompt) {
|
|
@@ -3930,17 +3937,12 @@ ${followOnPrompt}`;
|
|
|
3930
3937
|
// Use the conversation ID from ensureConversation
|
|
3931
3938
|
newController
|
|
3932
3939
|
);
|
|
3933
|
-
setLastPrompt(promptToSend.trim());
|
|
3934
3940
|
setLastMessages(messagesAndHistory);
|
|
3935
|
-
setLastKey(promptKey);
|
|
3936
3941
|
if (convId && onConversationCreated) {
|
|
3937
3942
|
setTimeout(() => {
|
|
3938
3943
|
onConversationCreated(convId);
|
|
3939
3944
|
}, 100);
|
|
3940
3945
|
}
|
|
3941
|
-
setTimeout(() => {
|
|
3942
|
-
scrollToBottom();
|
|
3943
|
-
}, 0);
|
|
3944
3946
|
});
|
|
3945
3947
|
}, [
|
|
3946
3948
|
idle,
|
|
@@ -4095,50 +4097,11 @@ ${followOnPrompt}`;
|
|
|
4095
4097
|
};
|
|
4096
4098
|
}, []);
|
|
4097
4099
|
useEffect7(() => {
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
}
|
|
4102
|
-
if (initialPrompt && initialPrompt !== "" && initialPrompt !== lastPrompt && !hasLoadedHistory) {
|
|
4103
|
-
setIsLoading(true);
|
|
4104
|
-
setThinkingBlocks([]);
|
|
4105
|
-
setCurrentThinkingIndex(0);
|
|
4106
|
-
setUserHasScrolled(false);
|
|
4107
|
-
ensureConversation().then((convId) => {
|
|
4108
|
-
const controller = new AbortController();
|
|
4109
|
-
setLastController(controller);
|
|
4110
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4111
|
-
const promptKey = `${timestamp}:${initialPrompt}`;
|
|
4112
|
-
setHistory({ [promptKey]: { content: "", callId: "" } });
|
|
4113
|
-
let fullPrompt = initialPrompt;
|
|
4114
|
-
if (promptTemplate) {
|
|
4115
|
-
fullPrompt = promptTemplate.replace("{{prompt}}", initialPrompt);
|
|
4116
|
-
}
|
|
4117
|
-
send(
|
|
4118
|
-
fullPrompt,
|
|
4119
|
-
[],
|
|
4120
|
-
[
|
|
4121
|
-
...dataWithExtras(),
|
|
4122
|
-
{ key: "--messages", data: "0" }
|
|
4123
|
-
],
|
|
4124
|
-
true,
|
|
4125
|
-
true,
|
|
4126
|
-
service,
|
|
4127
|
-
convId,
|
|
4128
|
-
// Use conversation ID from ensureConversation
|
|
4129
|
-
controller
|
|
4130
|
-
);
|
|
4131
|
-
setLastPrompt(initialPrompt);
|
|
4132
|
-
setLastMessages([]);
|
|
4133
|
-
setLastKey(promptKey);
|
|
4134
|
-
if (convId && onConversationCreated) {
|
|
4135
|
-
setTimeout(() => {
|
|
4136
|
-
onConversationCreated(convId);
|
|
4137
|
-
}, 100);
|
|
4138
|
-
}
|
|
4139
|
-
});
|
|
4100
|
+
if (initialPrompt && initialPrompt !== "" && !initialPromptSentRef.current) {
|
|
4101
|
+
initialPromptSentRef.current = true;
|
|
4102
|
+
continueChat(initialPrompt);
|
|
4140
4103
|
}
|
|
4141
|
-
}, [initialPrompt,
|
|
4104
|
+
}, [initialPrompt, continueChat]);
|
|
4142
4105
|
const CodeBlock = useCallback2((_a) => {
|
|
4143
4106
|
var _b = _a, { node, inline, className, children } = _b, props = __objRest(_b, ["node", "inline", "className", "children"]);
|
|
4144
4107
|
const match = /language-(\w+)/.exec(className || "");
|
|
@@ -4655,6 +4618,9 @@ var ChatPanelWrapper = ({
|
|
|
4655
4618
|
effectiveCustomer,
|
|
4656
4619
|
showPoweredBy,
|
|
4657
4620
|
actions,
|
|
4621
|
+
initialPrompt,
|
|
4622
|
+
initialMessage,
|
|
4623
|
+
hideInitialPrompt,
|
|
4658
4624
|
followOnQuestions,
|
|
4659
4625
|
followOnPrompt,
|
|
4660
4626
|
agentOptions,
|
|
@@ -4665,7 +4631,8 @@ var ChatPanelWrapper = ({
|
|
|
4665
4631
|
totalContextTokens,
|
|
4666
4632
|
maxContextTokens,
|
|
4667
4633
|
enableContextDetailView,
|
|
4668
|
-
onConversationCreated
|
|
4634
|
+
onConversationCreated,
|
|
4635
|
+
conversationInitialPrompt
|
|
4669
4636
|
}) => {
|
|
4670
4637
|
var _a, _b;
|
|
4671
4638
|
const convAgentProfile = getAgent(activeConv.agentId);
|
|
@@ -4701,6 +4668,7 @@ var ChatPanelWrapper = ({
|
|
|
4701
4668
|
const mcpServers = useMemo4(() => {
|
|
4702
4669
|
return (convAgentProfile == null ? void 0 : convAgentProfile.mcpServers) || EMPTY_ARRAY;
|
|
4703
4670
|
}, [convAgentProfile == null ? void 0 : convAgentProfile.mcpServers]);
|
|
4671
|
+
const effectiveInitialPrompt = conversationInitialPrompt || initialPrompt;
|
|
4704
4672
|
if (!convAgentMetadata) return null;
|
|
4705
4673
|
return /* @__PURE__ */ React12.createElement(
|
|
4706
4674
|
"div",
|
|
@@ -4717,10 +4685,10 @@ var ChatPanelWrapper = ({
|
|
|
4717
4685
|
title: "",
|
|
4718
4686
|
theme,
|
|
4719
4687
|
promptTemplate: convAgentMetadata.displayPromptTemplate || "{{prompt}}",
|
|
4720
|
-
initialMessage: convAgentMetadata.displayStartMessageOrPrompt === "message" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0,
|
|
4721
|
-
initialPrompt: convAgentMetadata.displayStartMessageOrPrompt === "prompt" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0,
|
|
4688
|
+
initialMessage: initialMessage || (convAgentMetadata.displayStartMessageOrPrompt === "message" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0),
|
|
4689
|
+
initialPrompt: effectiveInitialPrompt || (convAgentMetadata.displayStartMessageOrPrompt === "prompt" ? convAgentMetadata.displayInitialMessageOrPrompt : void 0),
|
|
4722
4690
|
placeholder: convAgentMetadata.displayPlaceholder || "Type a message...",
|
|
4723
|
-
hideInitialPrompt: (_a = convAgentMetadata.displayHideInitialPrompt) != null ? _a : true,
|
|
4691
|
+
hideInitialPrompt: (_a = hideInitialPrompt != null ? hideInitialPrompt : convAgentMetadata.displayHideInitialPrompt) != null ? _a : true,
|
|
4724
4692
|
data: chatPanelData,
|
|
4725
4693
|
agent: activeConv.agentId,
|
|
4726
4694
|
conversation: activeConv.conversationId.startsWith("new-") ? void 0 : activeConv.conversationId,
|
|
@@ -4754,7 +4722,7 @@ var ChatPanelWrapper = ({
|
|
|
4754
4722
|
);
|
|
4755
4723
|
};
|
|
4756
4724
|
ChatPanelWrapper.displayName = "ChatPanelWrapper";
|
|
4757
|
-
var AIAgentPanel = ({
|
|
4725
|
+
var AIAgentPanel = React12.forwardRef(({
|
|
4758
4726
|
agents,
|
|
4759
4727
|
defaultAgent,
|
|
4760
4728
|
customerId,
|
|
@@ -4786,11 +4754,14 @@ var AIAgentPanel = ({
|
|
|
4786
4754
|
showPoweredBy = true,
|
|
4787
4755
|
conversation,
|
|
4788
4756
|
actions = [],
|
|
4757
|
+
initialPrompt,
|
|
4758
|
+
initialMessage,
|
|
4759
|
+
hideInitialPrompt,
|
|
4789
4760
|
followOnQuestions = [],
|
|
4790
4761
|
followOnPrompt = "",
|
|
4791
4762
|
historyListLimit = 50,
|
|
4792
4763
|
showConversationHistory = true
|
|
4793
|
-
}) => {
|
|
4764
|
+
}, ref) => {
|
|
4794
4765
|
var _a, _b, _c, _d;
|
|
4795
4766
|
const [isCollapsed, setIsCollapsed] = useState8(defaultCollapsed);
|
|
4796
4767
|
const [isHistoryCollapsed, setIsHistoryCollapsed] = useState8(() => {
|
|
@@ -4872,6 +4843,29 @@ var AIAgentPanel = ({
|
|
|
4872
4843
|
activeConversationsRef.current = activeConversations;
|
|
4873
4844
|
const currentConversationIdRef = useRef6(currentConversationId);
|
|
4874
4845
|
currentConversationIdRef.current = currentConversationId;
|
|
4846
|
+
React12.useImperativeHandle(ref, () => ({
|
|
4847
|
+
startNewConversation: (prompt, agent) => {
|
|
4848
|
+
const targetAgent = agent || currentAgentId;
|
|
4849
|
+
const tempId = `new-${Date.now()}`;
|
|
4850
|
+
setActiveConversations((prev) => {
|
|
4851
|
+
const next = new Map(prev);
|
|
4852
|
+
next.set(tempId, {
|
|
4853
|
+
conversationId: tempId,
|
|
4854
|
+
stableKey: tempId,
|
|
4855
|
+
agentId: targetAgent,
|
|
4856
|
+
history: {},
|
|
4857
|
+
isLoading: false,
|
|
4858
|
+
title: "New conversation",
|
|
4859
|
+
conversationInitialPrompt: prompt
|
|
4860
|
+
});
|
|
4861
|
+
return next;
|
|
4862
|
+
});
|
|
4863
|
+
setCurrentConversationId(tempId);
|
|
4864
|
+
if (onConversationChange) {
|
|
4865
|
+
onConversationChange(tempId);
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
}), [currentAgentId, onConversationChange]);
|
|
4875
4869
|
const [showContextNotification, setShowContextNotification] = useState8(false);
|
|
4876
4870
|
const prevContextRef = useRef6(null);
|
|
4877
4871
|
const contextNotificationTimeoutRef = useRef6(null);
|
|
@@ -5215,15 +5209,17 @@ var AIAgentPanel = ({
|
|
|
5215
5209
|
let filtered = apiConversations;
|
|
5216
5210
|
if (searchQuery) {
|
|
5217
5211
|
const query = searchQuery.toLowerCase();
|
|
5218
|
-
filtered = filtered.filter(
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5212
|
+
filtered = filtered.filter((conv) => {
|
|
5213
|
+
var _a2, _b2;
|
|
5214
|
+
if ((_a2 = conv.title) == null ? void 0 : _a2.toLowerCase().includes(query)) return true;
|
|
5215
|
+
if ((_b2 = conv.summary) == null ? void 0 : _b2.toLowerCase().includes(query)) return true;
|
|
5216
|
+
const firstPrompt = conversationFirstPrompts[conv.conversationId];
|
|
5217
|
+
if (firstPrompt == null ? void 0 : firstPrompt.toLowerCase().includes(query)) return true;
|
|
5218
|
+
return false;
|
|
5219
|
+
});
|
|
5224
5220
|
}
|
|
5225
5221
|
return groupConversationsByTime(filtered, true);
|
|
5226
|
-
}, [apiConversations, searchQuery]);
|
|
5222
|
+
}, [apiConversations, searchQuery, conversationFirstPrompts]);
|
|
5227
5223
|
const effectiveCustomer = useMemo4(() => {
|
|
5228
5224
|
return __spreadProps(__spreadValues({}, customer), {
|
|
5229
5225
|
customer_id: customerId
|
|
@@ -5832,6 +5828,9 @@ var AIAgentPanel = ({
|
|
|
5832
5828
|
effectiveCustomer,
|
|
5833
5829
|
showPoweredBy,
|
|
5834
5830
|
actions,
|
|
5831
|
+
initialPrompt,
|
|
5832
|
+
initialMessage,
|
|
5833
|
+
hideInitialPrompt,
|
|
5835
5834
|
followOnQuestions,
|
|
5836
5835
|
followOnPrompt,
|
|
5837
5836
|
agentOptions,
|
|
@@ -5842,7 +5841,8 @@ var AIAgentPanel = ({
|
|
|
5842
5841
|
totalContextTokens: mergedContext.totalTokens || 0,
|
|
5843
5842
|
maxContextTokens,
|
|
5844
5843
|
enableContextDetailView,
|
|
5845
|
-
onConversationCreated: handleConversationCreated
|
|
5844
|
+
onConversationCreated: handleConversationCreated,
|
|
5845
|
+
conversationInitialPrompt: activeConv.conversationInitialPrompt
|
|
5846
5846
|
}
|
|
5847
5847
|
)), loadingConversationId && /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__conversation-loading-overlay" }, /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ React12.createElement("p", null, "Loading conversation...")), currentAgentMetadata && activeConversationsList.length === 0 && !loadingConversationId && /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__empty-chat" }, /* @__PURE__ */ React12.createElement(MessageIcon, null), /* @__PURE__ */ React12.createElement("p", null, "Select a conversation or start a new one"), /* @__PURE__ */ React12.createElement(Button, { variant: "default", size: "sm", onClick: handleNewConversation }, "New Conversation")), agentsLoading && !currentAgentMetadata && /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__loading" }, /* @__PURE__ */ React12.createElement("div", { className: "ai-agent-panel__loading-spinner" }), /* @__PURE__ */ React12.createElement("p", null, "Loading agent..."))),
|
|
5848
5848
|
/* @__PURE__ */ React12.createElement(
|
|
@@ -5856,7 +5856,8 @@ var AIAgentPanel = ({
|
|
|
5856
5856
|
/* @__PURE__ */ React12.createElement(DialogFooter, null, /* @__PURE__ */ React12.createElement(Button, { variant: "outline", onClick: handleHandoffCancel }, "Stay with current agent"), /* @__PURE__ */ React12.createElement(Button, { onClick: handleHandoffConfirm }, "Switch agent"))
|
|
5857
5857
|
)
|
|
5858
5858
|
);
|
|
5859
|
-
};
|
|
5859
|
+
});
|
|
5860
|
+
AIAgentPanel.displayName = "AIAgentPanel";
|
|
5860
5861
|
var AIAgentPanel_default = AIAgentPanel;
|
|
5861
5862
|
|
|
5862
5863
|
// src/hooks/useConversationStore.ts
|
package/package.json
CHANGED
package/src/AIAgentPanel.tsx
CHANGED
|
@@ -47,6 +47,7 @@ export interface ActiveConversation {
|
|
|
47
47
|
history: Record<string, { content: string; callId: string }>;
|
|
48
48
|
isLoading: boolean;
|
|
49
49
|
title: string;
|
|
50
|
+
conversationInitialPrompt?: string; // Per-conversation initial prompt for programmatic start
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/**
|
|
@@ -58,6 +59,13 @@ export interface AgentConfig {
|
|
|
58
59
|
avatarUrl?: string;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Imperative handle for programmatic control of AIAgentPanel
|
|
64
|
+
*/
|
|
65
|
+
export interface AIAgentPanelHandle {
|
|
66
|
+
startNewConversation: (prompt: string, agent?: string) => void;
|
|
67
|
+
}
|
|
68
|
+
|
|
61
69
|
/**
|
|
62
70
|
* Props for AIAgentPanel
|
|
63
71
|
*/
|
|
@@ -120,7 +128,10 @@ export interface AIAgentPanelProps {
|
|
|
120
128
|
style?: string;
|
|
121
129
|
}[];
|
|
122
130
|
|
|
123
|
-
//
|
|
131
|
+
// Initial prompt and follow-on
|
|
132
|
+
initialPrompt?: string;
|
|
133
|
+
initialMessage?: string;
|
|
134
|
+
hideInitialPrompt?: boolean;
|
|
124
135
|
followOnQuestions?: string[];
|
|
125
136
|
followOnPrompt?: string;
|
|
126
137
|
|
|
@@ -351,6 +362,9 @@ interface ChatPanelWrapperProps {
|
|
|
351
362
|
effectiveCustomer: any;
|
|
352
363
|
showPoweredBy: boolean;
|
|
353
364
|
actions: any[];
|
|
365
|
+
initialPrompt?: string;
|
|
366
|
+
initialMessage?: string;
|
|
367
|
+
hideInitialPrompt?: boolean;
|
|
354
368
|
followOnQuestions: string[];
|
|
355
369
|
followOnPrompt: string;
|
|
356
370
|
agentOptions: any[];
|
|
@@ -364,6 +378,8 @@ interface ChatPanelWrapperProps {
|
|
|
364
378
|
enableContextDetailView: boolean;
|
|
365
379
|
// Conversation creation callback
|
|
366
380
|
onConversationCreated: (tempId: string, realId: string) => void;
|
|
381
|
+
// Per-conversation initial prompt
|
|
382
|
+
conversationInitialPrompt?: string;
|
|
367
383
|
}
|
|
368
384
|
|
|
369
385
|
// Remove React.memo temporarily to debug - ChatPanelWrapper needs to re-render when agentId changes
|
|
@@ -382,6 +398,9 @@ const ChatPanelWrapper = (({
|
|
|
382
398
|
effectiveCustomer,
|
|
383
399
|
showPoweredBy,
|
|
384
400
|
actions,
|
|
401
|
+
initialPrompt,
|
|
402
|
+
initialMessage,
|
|
403
|
+
hideInitialPrompt,
|
|
385
404
|
followOnQuestions,
|
|
386
405
|
followOnPrompt,
|
|
387
406
|
agentOptions,
|
|
@@ -393,6 +412,7 @@ const ChatPanelWrapper = (({
|
|
|
393
412
|
maxContextTokens,
|
|
394
413
|
enableContextDetailView,
|
|
395
414
|
onConversationCreated,
|
|
415
|
+
conversationInitialPrompt,
|
|
396
416
|
}) => {
|
|
397
417
|
const convAgentProfile = getAgent(activeConv.agentId);
|
|
398
418
|
const convAgentMetadata = convAgentProfile?.metadata;
|
|
@@ -441,6 +461,9 @@ const ChatPanelWrapper = (({
|
|
|
441
461
|
return convAgentProfile?.mcpServers || EMPTY_ARRAY;
|
|
442
462
|
}, [convAgentProfile?.mcpServers]);
|
|
443
463
|
|
|
464
|
+
// Determine which initialPrompt to use - conversation-specific OR prop-based
|
|
465
|
+
const effectiveInitialPrompt = conversationInitialPrompt || initialPrompt;
|
|
466
|
+
|
|
444
467
|
if (!convAgentMetadata) return null;
|
|
445
468
|
|
|
446
469
|
return (
|
|
@@ -456,17 +479,19 @@ const ChatPanelWrapper = (({
|
|
|
456
479
|
theme={theme}
|
|
457
480
|
promptTemplate={convAgentMetadata.displayPromptTemplate || '{{prompt}}'}
|
|
458
481
|
initialMessage={
|
|
459
|
-
|
|
482
|
+
initialMessage ||
|
|
483
|
+
(convAgentMetadata.displayStartMessageOrPrompt === 'message'
|
|
460
484
|
? convAgentMetadata.displayInitialMessageOrPrompt
|
|
461
|
-
: undefined
|
|
485
|
+
: undefined)
|
|
462
486
|
}
|
|
463
487
|
initialPrompt={
|
|
464
|
-
|
|
488
|
+
effectiveInitialPrompt ||
|
|
489
|
+
(convAgentMetadata.displayStartMessageOrPrompt === 'prompt'
|
|
465
490
|
? convAgentMetadata.displayInitialMessageOrPrompt
|
|
466
|
-
: undefined
|
|
491
|
+
: undefined)
|
|
467
492
|
}
|
|
468
493
|
placeholder={convAgentMetadata.displayPlaceholder || 'Type a message...'}
|
|
469
|
-
hideInitialPrompt={convAgentMetadata.displayHideInitialPrompt ?? true}
|
|
494
|
+
hideInitialPrompt={hideInitialPrompt ?? convAgentMetadata.displayHideInitialPrompt ?? true}
|
|
470
495
|
data={chatPanelData}
|
|
471
496
|
agent={activeConv.agentId}
|
|
472
497
|
conversation={activeConv.conversationId.startsWith('new-') ? undefined : activeConv.conversationId}
|
|
@@ -502,7 +527,7 @@ const ChatPanelWrapper = (({
|
|
|
502
527
|
|
|
503
528
|
ChatPanelWrapper.displayName = 'ChatPanelWrapper';
|
|
504
529
|
|
|
505
|
-
const AIAgentPanel
|
|
530
|
+
const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
|
|
506
531
|
agents,
|
|
507
532
|
defaultAgent,
|
|
508
533
|
customerId,
|
|
@@ -534,11 +559,14 @@ const AIAgentPanel: React.FC<AIAgentPanelProps> = ({
|
|
|
534
559
|
showPoweredBy = true,
|
|
535
560
|
conversation,
|
|
536
561
|
actions = [],
|
|
562
|
+
initialPrompt,
|
|
563
|
+
initialMessage,
|
|
564
|
+
hideInitialPrompt,
|
|
537
565
|
followOnQuestions = [],
|
|
538
566
|
followOnPrompt = '',
|
|
539
567
|
historyListLimit = 50,
|
|
540
568
|
showConversationHistory = true,
|
|
541
|
-
}) => {
|
|
569
|
+
}, ref) => {
|
|
542
570
|
// Panel state
|
|
543
571
|
const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);
|
|
544
572
|
const [isHistoryCollapsed, setIsHistoryCollapsed] = useState(() => {
|
|
@@ -653,6 +681,33 @@ const AIAgentPanel: React.FC<AIAgentPanelProps> = ({
|
|
|
653
681
|
const currentConversationIdRef = useRef<string | null>(currentConversationId);
|
|
654
682
|
currentConversationIdRef.current = currentConversationId;
|
|
655
683
|
|
|
684
|
+
// Imperative handle for programmatic control
|
|
685
|
+
React.useImperativeHandle(ref, () => ({
|
|
686
|
+
startNewConversation: (prompt: string, agent?: string) => {
|
|
687
|
+
const targetAgent = agent || currentAgentId;
|
|
688
|
+
const tempId = `new-${Date.now()}`;
|
|
689
|
+
|
|
690
|
+
setActiveConversations(prev => {
|
|
691
|
+
const next = new Map(prev);
|
|
692
|
+
next.set(tempId, {
|
|
693
|
+
conversationId: tempId,
|
|
694
|
+
stableKey: tempId,
|
|
695
|
+
agentId: targetAgent,
|
|
696
|
+
history: {},
|
|
697
|
+
isLoading: false,
|
|
698
|
+
title: 'New conversation',
|
|
699
|
+
conversationInitialPrompt: prompt,
|
|
700
|
+
});
|
|
701
|
+
return next;
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
setCurrentConversationId(tempId);
|
|
705
|
+
if (onConversationChange) {
|
|
706
|
+
onConversationChange(tempId);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}), [currentAgentId, onConversationChange]);
|
|
710
|
+
|
|
656
711
|
// Context change notification state
|
|
657
712
|
const [showContextNotification, setShowContextNotification] = useState(false);
|
|
658
713
|
const prevContextRef = useRef<string | null>(null);
|
|
@@ -1138,15 +1193,24 @@ console.log("apiKey", apiKey);
|
|
|
1138
1193
|
// Filter by search query
|
|
1139
1194
|
if (searchQuery) {
|
|
1140
1195
|
const query = searchQuery.toLowerCase();
|
|
1141
|
-
filtered = filtered.filter(conv =>
|
|
1142
|
-
|
|
1143
|
-
conv.
|
|
1144
|
-
|
|
1196
|
+
filtered = filtered.filter(conv => {
|
|
1197
|
+
// Check title from API
|
|
1198
|
+
if (conv.title?.toLowerCase().includes(query)) return true;
|
|
1199
|
+
|
|
1200
|
+
// Check summary from API
|
|
1201
|
+
if (conv.summary?.toLowerCase().includes(query)) return true;
|
|
1202
|
+
|
|
1203
|
+
// Check the first prompt (what's actually displayed in the UI)
|
|
1204
|
+
const firstPrompt = conversationFirstPrompts[conv.conversationId];
|
|
1205
|
+
if (firstPrompt?.toLowerCase().includes(query)) return true;
|
|
1206
|
+
|
|
1207
|
+
return false;
|
|
1208
|
+
});
|
|
1145
1209
|
}
|
|
1146
1210
|
|
|
1147
1211
|
// Group all conversations, show all groups even if empty
|
|
1148
1212
|
return groupConversationsByTime(filtered, true);
|
|
1149
|
-
}, [apiConversations, searchQuery]);
|
|
1213
|
+
}, [apiConversations, searchQuery, conversationFirstPrompts]);
|
|
1150
1214
|
|
|
1151
1215
|
// Build effective customer object with required customerId
|
|
1152
1216
|
const effectiveCustomer = useMemo(() => {
|
|
@@ -2022,6 +2086,9 @@ console.log("apiKey", apiKey);
|
|
|
2022
2086
|
effectiveCustomer={effectiveCustomer}
|
|
2023
2087
|
showPoweredBy={showPoweredBy}
|
|
2024
2088
|
actions={actions}
|
|
2089
|
+
initialPrompt={initialPrompt}
|
|
2090
|
+
initialMessage={initialMessage}
|
|
2091
|
+
hideInitialPrompt={hideInitialPrompt}
|
|
2025
2092
|
followOnQuestions={followOnQuestions}
|
|
2026
2093
|
followOnPrompt={followOnPrompt}
|
|
2027
2094
|
agentOptions={agentOptions}
|
|
@@ -2033,6 +2100,7 @@ console.log("apiKey", apiKey);
|
|
|
2033
2100
|
maxContextTokens={maxContextTokens}
|
|
2034
2101
|
enableContextDetailView={enableContextDetailView}
|
|
2035
2102
|
onConversationCreated={handleConversationCreated}
|
|
2103
|
+
conversationInitialPrompt={activeConv.conversationInitialPrompt}
|
|
2036
2104
|
/>
|
|
2037
2105
|
))}
|
|
2038
2106
|
|
|
@@ -2090,7 +2158,9 @@ console.log("apiKey", apiKey);
|
|
|
2090
2158
|
</Dialog>
|
|
2091
2159
|
</div>
|
|
2092
2160
|
);
|
|
2093
|
-
};
|
|
2161
|
+
});
|
|
2162
|
+
|
|
2163
|
+
AIAgentPanel.displayName = 'AIAgentPanel';
|
|
2094
2164
|
|
|
2095
2165
|
export default AIAgentPanel;
|
|
2096
2166
|
|
package/src/AIChatPanel.tsx
CHANGED
|
@@ -703,6 +703,8 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
703
703
|
const hasNotifiedCompletionRef = useRef<boolean>(true);
|
|
704
704
|
// Store the latest processed history for callbacks (doesn't trigger re-renders)
|
|
705
705
|
const latestHistoryRef = useRef<Record<string, HistoryEntry>>(initialHistory);
|
|
706
|
+
// Track if we've sent the initial prompt (prevents loops)
|
|
707
|
+
const initialPromptSentRef = useRef<boolean>(false);
|
|
706
708
|
|
|
707
709
|
// Sync new entries from initialHistory into local history state
|
|
708
710
|
// This allows parent components to inject messages (e.g., page-based agent suggestions)
|
|
@@ -1063,13 +1065,39 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1063
1065
|
|
|
1064
1066
|
setIsLoading(true);
|
|
1065
1067
|
|
|
1068
|
+
// === OPTIMISTIC UPDATE: Show prompt immediately in UI ===
|
|
1069
|
+
// Generate unique key using ISO timestamp prefix + prompt
|
|
1070
|
+
const timestamp = new Date().toISOString();
|
|
1071
|
+
const promptKey = `${timestamp}:${promptToSend.trim()}`;
|
|
1072
|
+
|
|
1073
|
+
// Add prompt to history IMMEDIATELY - this makes it appear in the UI right away
|
|
1074
|
+
setHistory((prevHistory) => ({
|
|
1075
|
+
...prevHistory,
|
|
1076
|
+
[promptKey]: { content: '', callId: '' },
|
|
1077
|
+
}));
|
|
1078
|
+
|
|
1079
|
+
// Store the key for later use
|
|
1080
|
+
setLastPrompt(promptToSend.trim());
|
|
1081
|
+
setLastKey(promptKey);
|
|
1082
|
+
|
|
1083
|
+
// Scroll to bottom immediately to show the new prompt
|
|
1084
|
+
// Use setTimeout to ensure the DOM has updated
|
|
1085
|
+
setTimeout(() => {
|
|
1086
|
+
scrollToBottom();
|
|
1087
|
+
}, 0);
|
|
1088
|
+
|
|
1089
|
+
// Now proceed with API calls in the background (conversation creation + LLM call)
|
|
1066
1090
|
// Ensure conversation exists before sending (matches ChatPanel)
|
|
1067
1091
|
console.log('AIChatPanel.continueChat - about to call ensureConversation');
|
|
1068
1092
|
ensureConversation().then((convId) => {
|
|
1069
1093
|
console.log('AIChatPanel.continueChat - ensureConversation resolved with:', convId);
|
|
1070
1094
|
// Build messagesAndHistory from history (matches ChatPanel)
|
|
1095
|
+
// IMPORTANT: Exclude the current prompt (promptKey) since it's new and we're sending it now
|
|
1071
1096
|
const messagesAndHistory: { role: string; content: string }[] = [];
|
|
1072
1097
|
Object.entries(history).forEach(([historyPrompt, historyEntry]) => {
|
|
1098
|
+
// Skip the current prompt we just added optimistically
|
|
1099
|
+
if (historyPrompt === promptKey) return;
|
|
1100
|
+
|
|
1073
1101
|
// Strip timestamp prefix from prompt before using it (matches ChatPanel)
|
|
1074
1102
|
let promptForHistory = historyPrompt;
|
|
1075
1103
|
const isoTimestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:/;
|
|
@@ -1085,19 +1113,10 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1085
1113
|
messagesAndHistory.push({ role: 'assistant', content: historyEntry.content });
|
|
1086
1114
|
});
|
|
1087
1115
|
|
|
1088
|
-
// Generate unique key using ISO timestamp prefix + prompt (matches ChatPanel)
|
|
1089
|
-
const timestamp = new Date().toISOString();
|
|
1090
|
-
const promptKey = `${timestamp}:${promptToSend.trim()}`;
|
|
1091
|
-
|
|
1092
|
-
// Set history entry before sending (matches ChatPanel)
|
|
1093
|
-
setHistory((prevHistory) => ({
|
|
1094
|
-
...prevHistory,
|
|
1095
|
-
[promptKey]: { content: '', callId: '' },
|
|
1096
|
-
}));
|
|
1097
|
-
|
|
1098
1116
|
// Build the full prompt - only apply template for first message (matches ChatPanel)
|
|
1117
|
+
// Check if this is the first message by seeing if messagesAndHistory is empty
|
|
1099
1118
|
let fullPromptToSend = promptToSend.trim();
|
|
1100
|
-
if (
|
|
1119
|
+
if (messagesAndHistory.length === 0 && promptTemplate) {
|
|
1101
1120
|
fullPromptToSend = promptTemplate.replace('{{prompt}}', fullPromptToSend);
|
|
1102
1121
|
}
|
|
1103
1122
|
|
|
@@ -1126,9 +1145,7 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1126
1145
|
newController
|
|
1127
1146
|
);
|
|
1128
1147
|
|
|
1129
|
-
setLastPrompt(promptToSend.trim());
|
|
1130
1148
|
setLastMessages(messagesAndHistory);
|
|
1131
|
-
setLastKey(promptKey);
|
|
1132
1149
|
|
|
1133
1150
|
// Notify parent of new conversation ID AFTER send() has started
|
|
1134
1151
|
// This prevents the component from being remounted before send() runs
|
|
@@ -1138,12 +1155,6 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1138
1155
|
onConversationCreated(convId);
|
|
1139
1156
|
}, 100);
|
|
1140
1157
|
}
|
|
1141
|
-
|
|
1142
|
-
// Scroll to bottom after adding the new prompt to show it immediately
|
|
1143
|
-
// Use setTimeout to ensure the DOM has updated with the new history entry
|
|
1144
|
-
setTimeout(() => {
|
|
1145
|
-
scrollToBottom();
|
|
1146
|
-
}, 0);
|
|
1147
1158
|
});
|
|
1148
1159
|
}, [
|
|
1149
1160
|
idle,
|
|
@@ -1376,69 +1387,14 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
1376
1387
|
};
|
|
1377
1388
|
}, []); // Empty deps - only run cleanup on unmount
|
|
1378
1389
|
|
|
1379
|
-
// Auto-send initialPrompt
|
|
1380
|
-
//
|
|
1390
|
+
// Auto-send initialPrompt exactly once when component mounts
|
|
1391
|
+
// Simple behavior matching original ChatPanel - just send the prompt
|
|
1381
1392
|
useEffect(() => {
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
// Don't proceed if project_id is not yet available
|
|
1387
|
-
if (!project_id) {
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
if (initialPrompt && initialPrompt !== '' && initialPrompt !== lastPrompt && !hasLoadedHistory) {
|
|
1392
|
-
setIsLoading(true);
|
|
1393
|
-
setThinkingBlocks([]);
|
|
1394
|
-
setCurrentThinkingIndex(0);
|
|
1395
|
-
setUserHasScrolled(false); // Enable auto-scroll for new prompt
|
|
1396
|
-
|
|
1397
|
-
// Ensure conversation exists before sending (matches ChatPanel)
|
|
1398
|
-
ensureConversation().then((convId) => {
|
|
1399
|
-
const controller = new AbortController();
|
|
1400
|
-
setLastController(controller);
|
|
1401
|
-
|
|
1402
|
-
// Generate timestamp-prefixed key (matches ChatPanel)
|
|
1403
|
-
const timestamp = new Date().toISOString();
|
|
1404
|
-
const promptKey = `${timestamp}:${initialPrompt}`;
|
|
1405
|
-
|
|
1406
|
-
// Set history entry before sending (matches ChatPanel)
|
|
1407
|
-
setHistory({ [promptKey]: { content: '', callId: '' } });
|
|
1408
|
-
|
|
1409
|
-
// Build prompt with template
|
|
1410
|
-
let fullPrompt = initialPrompt;
|
|
1411
|
-
if (promptTemplate) {
|
|
1412
|
-
fullPrompt = promptTemplate.replace('{{prompt}}', initialPrompt);
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
send(
|
|
1416
|
-
fullPrompt,
|
|
1417
|
-
[],
|
|
1418
|
-
[
|
|
1419
|
-
...dataWithExtras(),
|
|
1420
|
-
{ key: '--messages', data: '0' },
|
|
1421
|
-
],
|
|
1422
|
-
true,
|
|
1423
|
-
true,
|
|
1424
|
-
service,
|
|
1425
|
-
convId, // Use conversation ID from ensureConversation
|
|
1426
|
-
controller
|
|
1427
|
-
);
|
|
1428
|
-
|
|
1429
|
-
setLastPrompt(initialPrompt);
|
|
1430
|
-
setLastMessages([]);
|
|
1431
|
-
setLastKey(promptKey);
|
|
1432
|
-
|
|
1433
|
-
// Notify parent of new conversation ID AFTER send() has started
|
|
1434
|
-
if (convId && onConversationCreated) {
|
|
1435
|
-
setTimeout(() => {
|
|
1436
|
-
onConversationCreated(convId);
|
|
1437
|
-
}, 100);
|
|
1438
|
-
}
|
|
1439
|
-
});
|
|
1393
|
+
if (initialPrompt && initialPrompt !== '' && !initialPromptSentRef.current) {
|
|
1394
|
+
initialPromptSentRef.current = true;
|
|
1395
|
+
continueChat(initialPrompt);
|
|
1440
1396
|
}
|
|
1441
|
-
}, [initialPrompt,
|
|
1397
|
+
}, [initialPrompt, continueChat]);
|
|
1442
1398
|
|
|
1443
1399
|
// ============================================================================
|
|
1444
1400
|
// Render Helpers
|