@truedat/ai 8.7.0 → 8.7.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/package.json +3 -3
- package/src/components/ConceptSuggestions.js +10 -4
- package/src/components/StructureSuggestions.js +8 -9
- package/src/components/ThinkingOutLoud.js +5 -0
- package/src/components/TranslationModal.js +15 -15
- package/src/components/__tests__/ConceptSuggestions.spec.js +32 -20
- package/src/components/__tests__/StructureSuggestions.spec.js +25 -19
- package/src/components/__tests__/SuggestLinkButton.spec.js +3 -1
- package/src/components/__tests__/TranslationModal.spec.js +3 -3
- package/src/components/actions/ActionActions.js +2 -2
- package/src/components/actions/ActionDetail.js +1 -1
- package/src/components/actions/ActionEdit.js +2 -1
- package/src/components/actions/ActionForm.js +1 -1
- package/src/components/actions/ActionsContext.js +1 -1
- package/src/components/actions/ActionsTable.js +1 -1
- package/src/components/actions/__tests__/ActionsTable.spec.js +1 -1
- package/src/components/aiSandbox/AiSandbox.js +2 -2
- package/src/components/aiSandbox/RequestForm.js +1 -1
- package/src/components/assistant/Assistant.js +8 -6
- package/src/components/assistant/AssistantChat.js +4 -0
- package/src/components/assistant/AssistantConversations.js +1 -1
- package/src/components/assistant/AssistantPage.js +5 -5
- package/src/components/assistant/AssistantPageChat.js +31 -14
- package/src/components/assistant/__tests__/Assistant.spec.js +3 -3
- package/src/components/assistant/__tests__/AssistantChat.spec.js +15 -11
- package/src/components/assistant/__tests__/AssistantConversations.spec.js +12 -12
- package/src/components/assistant/hooks/useAgentConversation.js +2 -2
- package/src/components/assistant/hooks/useAssistantSocket.js +2 -0
- package/src/components/index.js +8 -1
- package/src/components/prompts/PromptEditor.js +7 -7
- package/src/components/prompts/Prompts.js +1 -1
- package/src/components/prompts/__tests__/PromptEditor.spec.js +8 -8
- package/src/components/providers/ProviderEditor.js +6 -10
- package/src/components/providers/Providers.js +5 -1
- package/src/components/providers/__tests__/ProviderEditor.spec.js +7 -7
- package/src/components/providers/providerProperties/Anthropic.js +1 -1
- package/src/components/providers/providerProperties/AzureOpenai.js +2 -2
- package/src/components/providers/providerProperties/BedrockClaude.js +2 -2
- package/src/components/providers/providerProperties/Gemini.js +1 -1
- package/src/components/providers/providerProperties/Openai.js +2 -2
- package/src/components/resourceMappings/ResourceMappingEditor.js +2 -2
- package/src/components/resourceMappings/ResourceMappingFields.js +1 -1
- package/src/components/resourceMappings/__tests__/ResourceMappingEditor.spec.js +7 -7
- package/src/components/resourceMappings/__tests__/ResourceMappings.spec.js +1 -1
- package/src/components/resourceMappings/selectors/DataStructureSelector.js +2 -2
- package/src/components/suggestions/__tests__/SuggestionsWidget.spec.js +9 -9
- package/src/hooks/__tests__/useAgentConversations.spec.js +10 -2
- package/src/hooks/useActions.js +1 -1
- package/src/hooks/useAgentConversations.js +4 -1
- package/src/hooks/useAgentLayerRun.js +1 -1
- package/src/hooks/useProviders.js +1 -1
- package/src/hooks/useResourceMappings.js +1 -1
- package/src/hooks/useSuggestions.js +1 -1
- package/src/hooks/useTranslations.js +2 -2
|
@@ -9,7 +9,7 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
9
9
|
import { useAgents } from "@truedat/auth/hooks/useUsers";
|
|
10
10
|
|
|
11
11
|
const SelectableDynamicForm = lazy(
|
|
12
|
-
() => import("@truedat/df/components/SelectableDynamicForm")
|
|
12
|
+
() => import("@truedat/df/components/SelectableDynamicForm"),
|
|
13
13
|
);
|
|
14
14
|
|
|
15
15
|
const ActionForm = ({
|
|
@@ -32,7 +32,7 @@ export const ActionsContextProvider = (props) => {
|
|
|
32
32
|
}, [defaultFilters]);
|
|
33
33
|
|
|
34
34
|
const searchData = _.flow(
|
|
35
|
-
_.orderBy([sortColumn], [sortDirection == "ascending" ? "asc" : "desc"])
|
|
35
|
+
_.orderBy([sortColumn], [sortDirection == "ascending" ? "asc" : "desc"]),
|
|
36
36
|
)(rawData);
|
|
37
37
|
|
|
38
38
|
const context = {
|
|
@@ -38,7 +38,7 @@ export default function AiSandbox() {
|
|
|
38
38
|
key: id,
|
|
39
39
|
text: `${name} - ${type}`,
|
|
40
40
|
value: id,
|
|
41
|
-
}))
|
|
41
|
+
})),
|
|
42
42
|
)(data);
|
|
43
43
|
|
|
44
44
|
return (
|
|
@@ -94,7 +94,7 @@ export default function AiSandbox() {
|
|
|
94
94
|
<CommentText>{content}</CommentText>
|
|
95
95
|
</CommentContent>
|
|
96
96
|
</Comment>
|
|
97
|
-
)
|
|
97
|
+
),
|
|
98
98
|
)}
|
|
99
99
|
</CommentGroup>
|
|
100
100
|
{selectedProvider ? (
|
|
@@ -31,7 +31,7 @@ export default function AiSandbox({ provider, messages, setMessages }) {
|
|
|
31
31
|
setMessages([
|
|
32
32
|
...requestMessages,
|
|
33
33
|
{ role: "assistant", content: data },
|
|
34
|
-
])
|
|
34
|
+
]),
|
|
35
35
|
)
|
|
36
36
|
.catch((response) => {
|
|
37
37
|
const content = _.propOr("Error", "response.data.error")(response);
|
|
@@ -5,9 +5,9 @@ import { useIntl } from "react-intl";
|
|
|
5
5
|
import { useNavigate } from "react-router";
|
|
6
6
|
import truedatLogo from "assets/truedat-logo-home-no-text.png";
|
|
7
7
|
|
|
8
|
+
import useAgentConversations from "../../hooks/useAgentConversations";
|
|
8
9
|
import useAssistantSocket from "./hooks/useAssistantSocket";
|
|
9
10
|
import useAgentConversation from "./hooks/useAgentConversation";
|
|
10
|
-
import useAgentConversations from "../../hooks/useAgentConversations";
|
|
11
11
|
import AssistantChat from "./AssistantChat";
|
|
12
12
|
|
|
13
13
|
const EMPTY_CONVERSATION = [];
|
|
@@ -30,7 +30,8 @@ const Assistant = () => {
|
|
|
30
30
|
const [isClosing, setIsClosing] = useState(false);
|
|
31
31
|
const { conversationId, startNewConversation, selectConversation } =
|
|
32
32
|
useAgentConversation(isOpen);
|
|
33
|
-
const { conversations, refresh: refreshConversations } =
|
|
33
|
+
const { conversations, refresh: refreshConversations } =
|
|
34
|
+
useAgentConversations();
|
|
34
35
|
const [conversation, setConversation] = useState(EMPTY_CONVERSATION);
|
|
35
36
|
const [conversationTitle, setConversationTitle] = useState(null);
|
|
36
37
|
|
|
@@ -59,7 +60,7 @@ const Assistant = () => {
|
|
|
59
60
|
if (conversationId != null) {
|
|
60
61
|
setConversation(EMPTY_CONVERSATION);
|
|
61
62
|
const fromList = conversations.find(
|
|
62
|
-
(c) => String(c.id) === String(conversationId)
|
|
63
|
+
(c) => String(c.id) === String(conversationId),
|
|
63
64
|
);
|
|
64
65
|
setConversationTitle(fromList?.title ?? null);
|
|
65
66
|
}
|
|
@@ -119,7 +120,7 @@ const Assistant = () => {
|
|
|
119
120
|
conversations.some((c) => String(c.id) === String(conversationId));
|
|
120
121
|
navigate(
|
|
121
122
|
AI_ASSISTANT_PATH,
|
|
122
|
-
isInteracted ? { state: { conversationId } } : undefined
|
|
123
|
+
isInteracted ? { state: { conversationId } } : undefined,
|
|
123
124
|
);
|
|
124
125
|
}, [navigate, conversationId, conversations]);
|
|
125
126
|
|
|
@@ -148,9 +149,10 @@ const Assistant = () => {
|
|
|
148
149
|
const currentTitle = useMemo(
|
|
149
150
|
() =>
|
|
150
151
|
conversationTitle ??
|
|
151
|
-
conversations.find((c) => String(c.id) === String(conversationId))
|
|
152
|
+
conversations.find((c) => String(c.id) === String(conversationId))
|
|
153
|
+
?.title ??
|
|
152
154
|
null,
|
|
153
|
-
[conversationTitle, conversationId, conversations]
|
|
155
|
+
[conversationTitle, conversationId, conversations],
|
|
154
156
|
);
|
|
155
157
|
const { socketReady, sendPrompt } = useAssistantSocket(disableTdAi, {
|
|
156
158
|
conversationId: effectiveConversationId,
|
|
@@ -92,6 +92,7 @@ function isThinkingStreamMessage(msg) {
|
|
|
92
92
|
* Converts a flat list of visible messages into render items:
|
|
93
93
|
* consecutive log messages (and inline thinking errors) are bundled into a "thinking-block".
|
|
94
94
|
*/
|
|
95
|
+
/* eslint-disable fp/no-let, fp/no-mutation */
|
|
95
96
|
function buildRenderItems(messages) {
|
|
96
97
|
const result = [];
|
|
97
98
|
let logBuffer = [];
|
|
@@ -132,6 +133,7 @@ function buildRenderItems(messages) {
|
|
|
132
133
|
}
|
|
133
134
|
return result;
|
|
134
135
|
}
|
|
136
|
+
/* eslint-enable fp/no-let, fp/no-mutation */
|
|
135
137
|
|
|
136
138
|
const AssistantChat = ({
|
|
137
139
|
conversation,
|
|
@@ -167,11 +169,13 @@ const AssistantChat = ({
|
|
|
167
169
|
// overflow:hidden means no scrollbar → stable width → reliable scrollHeight in one read.
|
|
168
170
|
// overflow:auto only once content exceeds the max line count, when height is already
|
|
169
171
|
// capped so the scrollbar cannot trigger further reflow.
|
|
172
|
+
/* eslint-disable fp/no-mutation */
|
|
170
173
|
el.style.overflowY = "hidden";
|
|
171
174
|
el.style.height = "auto";
|
|
172
175
|
const h = Math.min(el.scrollHeight, maxHeight);
|
|
173
176
|
el.style.height = `${h}px`;
|
|
174
177
|
el.style.overflowY = el.scrollHeight > maxHeight ? "auto" : "hidden";
|
|
178
|
+
/* eslint-enable fp/no-mutation */
|
|
175
179
|
|
|
176
180
|
setInputExpanded(h > lh + padY + 2);
|
|
177
181
|
}, []);
|
|
@@ -64,7 +64,7 @@ AssistantConversations.propTypes = {
|
|
|
64
64
|
updated_at: PropTypes.string,
|
|
65
65
|
title: PropTypes.string,
|
|
66
66
|
preview: PropTypes.string,
|
|
67
|
-
})
|
|
67
|
+
}),
|
|
68
68
|
).isRequired,
|
|
69
69
|
activeId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
70
70
|
onSelect: PropTypes.func.isRequired,
|
|
@@ -4,9 +4,9 @@ import { FormattedMessage } from "react-intl";
|
|
|
4
4
|
import { Icon } from "semantic-ui-react";
|
|
5
5
|
import { useWebContext } from "@truedat/core/webContext";
|
|
6
6
|
|
|
7
|
+
import useAgentConversations from "../../hooks/useAgentConversations";
|
|
7
8
|
import useAssistantSocket from "./hooks/useAssistantSocket";
|
|
8
9
|
import useAgentConversation from "./hooks/useAgentConversation";
|
|
9
|
-
import useAgentConversations from "../../hooks/useAgentConversations";
|
|
10
10
|
import AssistantPageChat from "./AssistantPageChat";
|
|
11
11
|
import AssistantConversations from "./AssistantConversations";
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ const historyToConversation = (messages) =>
|
|
|
25
25
|
streaming: false,
|
|
26
26
|
source: "history",
|
|
27
27
|
priority: 0,
|
|
28
|
-
}
|
|
28
|
+
},
|
|
29
29
|
);
|
|
30
30
|
|
|
31
31
|
const AssistantPage = () => {
|
|
@@ -71,14 +71,14 @@ const AssistantPage = () => {
|
|
|
71
71
|
}
|
|
72
72
|
serverMessageHandlerRef.current?.(event, payload);
|
|
73
73
|
},
|
|
74
|
-
[setConversation, refreshConversations]
|
|
74
|
+
[setConversation, refreshConversations],
|
|
75
75
|
);
|
|
76
76
|
|
|
77
77
|
const handleSelectConversation = useCallback(
|
|
78
78
|
(id) => {
|
|
79
79
|
selectConversation(id);
|
|
80
80
|
},
|
|
81
|
-
[selectConversation]
|
|
81
|
+
[selectConversation],
|
|
82
82
|
);
|
|
83
83
|
|
|
84
84
|
const handleNewConversation = useCallback(() => {
|
|
@@ -89,7 +89,7 @@ const AssistantPage = () => {
|
|
|
89
89
|
const handleContinueInPanel = useCallback(() => {
|
|
90
90
|
if (!conversationId) return;
|
|
91
91
|
window.dispatchEvent(
|
|
92
|
-
new CustomEvent("assistant:open", { detail: { conversationId } })
|
|
92
|
+
new CustomEvent("assistant:open", { detail: { conversationId } }),
|
|
93
93
|
);
|
|
94
94
|
}, [conversationId]);
|
|
95
95
|
|
|
@@ -41,7 +41,7 @@ function getContentFromPayload(event, payload) {
|
|
|
41
41
|
const err = payload.error;
|
|
42
42
|
const errMsg =
|
|
43
43
|
err && typeof err === "object"
|
|
44
|
-
? err.message ?? err.reason ?? JSON.stringify(err)
|
|
44
|
+
? (err.message ?? err.reason ?? JSON.stringify(err))
|
|
45
45
|
: String(err ?? "");
|
|
46
46
|
return { content: errMsg, isError: true, priority, source };
|
|
47
47
|
}
|
|
@@ -49,7 +49,7 @@ function getContentFromPayload(event, payload) {
|
|
|
49
49
|
const log = payload.content;
|
|
50
50
|
const logMsg =
|
|
51
51
|
log && typeof log === "object"
|
|
52
|
-
? log.message ?? log.level ?? JSON.stringify(log)
|
|
52
|
+
? (log.message ?? log.level ?? JSON.stringify(log))
|
|
53
53
|
: String(log ?? "");
|
|
54
54
|
return { content: logMsg, isError: false, priority, source };
|
|
55
55
|
}
|
|
@@ -89,10 +89,13 @@ function isThinkingStreamMessage(msg) {
|
|
|
89
89
|
|
|
90
90
|
function buildRenderItems(messages) {
|
|
91
91
|
const result = [];
|
|
92
|
+
// eslint-disable-next-line fp/no-let
|
|
92
93
|
let logBuffer = [];
|
|
94
|
+
// eslint-disable-next-line fp/no-let
|
|
93
95
|
let startIdx = null;
|
|
94
96
|
messages.forEach((msg) => {
|
|
95
97
|
if (isThinkingStreamMessage(msg)) {
|
|
98
|
+
// eslint-disable-next-line fp/no-mutation
|
|
96
99
|
if (startIdx === null) startIdx = msg.index;
|
|
97
100
|
logBuffer.push(msg);
|
|
98
101
|
} else {
|
|
@@ -106,7 +109,9 @@ function buildRenderItems(messages) {
|
|
|
106
109
|
collapsed: isFollowedByP0,
|
|
107
110
|
key: `thinking-${startIdx}`,
|
|
108
111
|
});
|
|
112
|
+
// eslint-disable-next-line fp/no-mutation
|
|
109
113
|
logBuffer = [];
|
|
114
|
+
// eslint-disable-next-line fp/no-mutation
|
|
110
115
|
startIdx = null;
|
|
111
116
|
}
|
|
112
117
|
result.push({
|
|
@@ -150,10 +155,14 @@ const AssistantPageChat = ({
|
|
|
150
155
|
const lh = parseFloat(style.lineHeight) || 20;
|
|
151
156
|
const padY = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
|
|
152
157
|
const maxHeight = lh * MAX_INPUT_LINES + padY;
|
|
158
|
+
// eslint-disable-next-line fp/no-mutation
|
|
153
159
|
el.style.overflowY = "hidden";
|
|
160
|
+
// eslint-disable-next-line fp/no-mutation
|
|
154
161
|
el.style.height = "auto";
|
|
155
162
|
const h = Math.min(el.scrollHeight, maxHeight);
|
|
163
|
+
// eslint-disable-next-line fp/no-mutation
|
|
156
164
|
el.style.height = `${h}px`;
|
|
165
|
+
// eslint-disable-next-line fp/no-mutation
|
|
157
166
|
el.style.overflowY = el.scrollHeight > maxHeight ? "auto" : "hidden";
|
|
158
167
|
setInputExpanded(h > lh + padY + 2);
|
|
159
168
|
}, []);
|
|
@@ -168,12 +177,12 @@ const AssistantPageChat = ({
|
|
|
168
177
|
ref.current = (event, payload) => {
|
|
169
178
|
const { content, isError, priority, source } = getContentFromPayload(
|
|
170
179
|
event,
|
|
171
|
-
payload
|
|
180
|
+
payload,
|
|
172
181
|
);
|
|
173
182
|
if (event === "stream") {
|
|
174
183
|
requestAnimationFrame(() => {
|
|
175
184
|
setConversation((prev) =>
|
|
176
|
-
appendStreamChunk(prev, source, content, priority)
|
|
185
|
+
appendStreamChunk(prev, source, content, priority),
|
|
177
186
|
);
|
|
178
187
|
});
|
|
179
188
|
} else if (event === "log") {
|
|
@@ -221,17 +230,17 @@ const AssistantPageChat = ({
|
|
|
221
230
|
|
|
222
231
|
const visibleMessages = useMemo(
|
|
223
232
|
() => getVisibleMessages(conversation),
|
|
224
|
-
[conversation]
|
|
233
|
+
[conversation],
|
|
225
234
|
);
|
|
226
235
|
|
|
227
236
|
const renderItems = useMemo(
|
|
228
237
|
() => buildRenderItems(visibleMessages),
|
|
229
|
-
[visibleMessages]
|
|
238
|
+
[visibleMessages],
|
|
230
239
|
);
|
|
231
240
|
|
|
232
241
|
const canSendMessages = useMemo(
|
|
233
242
|
() => conversation.some((m) => m.side === "agent"),
|
|
234
|
-
[conversation]
|
|
243
|
+
[conversation],
|
|
235
244
|
);
|
|
236
245
|
|
|
237
246
|
const handleSubmit = useCallback(
|
|
@@ -248,7 +257,7 @@ const AssistantPageChat = ({
|
|
|
248
257
|
setInputValue("");
|
|
249
258
|
if (typeof onSendMessage === "function") onSendMessage(text);
|
|
250
259
|
},
|
|
251
|
-
[inputValue, onSendMessage, canSendMessages, setConversation]
|
|
260
|
+
[inputValue, onSendMessage, canSendMessages, setConversation],
|
|
252
261
|
);
|
|
253
262
|
|
|
254
263
|
const handleKeyDown = useCallback(
|
|
@@ -259,7 +268,7 @@ const AssistantPageChat = ({
|
|
|
259
268
|
handleSubmit();
|
|
260
269
|
}
|
|
261
270
|
},
|
|
262
|
-
[handleSubmit, canSendMessages]
|
|
271
|
+
[handleSubmit, canSendMessages],
|
|
263
272
|
);
|
|
264
273
|
|
|
265
274
|
const scrollToBottom = useCallback(() => {
|
|
@@ -271,10 +280,17 @@ const AssistantPageChat = ({
|
|
|
271
280
|
const el = messagesRef.current;
|
|
272
281
|
if (!el) return;
|
|
273
282
|
const { scrollHeight, scrollTop, clientHeight } = el;
|
|
274
|
-
if (clientHeight < 2) {
|
|
283
|
+
if (clientHeight < 2) {
|
|
284
|
+
setShowScrollToBottom(false);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
275
287
|
const hasOverflow = scrollHeight > clientHeight + SCROLL_OVERFLOW_EPSILON;
|
|
276
|
-
if (!hasOverflow) {
|
|
277
|
-
|
|
288
|
+
if (!hasOverflow) {
|
|
289
|
+
setShowScrollToBottom(false);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const atBottom =
|
|
293
|
+
scrollHeight - scrollTop - clientHeight <= SCROLL_AT_BOTTOM_THRESHOLD;
|
|
278
294
|
setShowScrollToBottom(!atBottom);
|
|
279
295
|
}, []);
|
|
280
296
|
|
|
@@ -298,7 +314,7 @@ const AssistantPageChat = ({
|
|
|
298
314
|
if (!entry) return;
|
|
299
315
|
setShowScrollToBottom(!entry.isIntersecting);
|
|
300
316
|
},
|
|
301
|
-
{ root, threshold: 0 }
|
|
317
|
+
{ root, threshold: 0 },
|
|
302
318
|
);
|
|
303
319
|
io.observe(sentinel);
|
|
304
320
|
return () => io.disconnect();
|
|
@@ -337,7 +353,8 @@ const AssistantPageChat = ({
|
|
|
337
353
|
const { msg } = item;
|
|
338
354
|
const isP0 = msg.priority === 0;
|
|
339
355
|
const isErrorP0 = msg.isError && isP0;
|
|
340
|
-
const sourceLabel =
|
|
356
|
+
const sourceLabel =
|
|
357
|
+
isP0 && msg.source ? getSourceLabel(msg.source) : null;
|
|
341
358
|
return (
|
|
342
359
|
<div
|
|
343
360
|
key={item.key}
|
|
@@ -12,7 +12,7 @@ jest.mock("../hooks/useAssistantSocket", () =>
|
|
|
12
12
|
jest.fn(() => ({
|
|
13
13
|
socketReady: false,
|
|
14
14
|
sendPrompt: jest.fn(),
|
|
15
|
-
}))
|
|
15
|
+
})),
|
|
16
16
|
);
|
|
17
17
|
|
|
18
18
|
jest.mock("../hooks/useAgentConversation", () =>
|
|
@@ -20,7 +20,7 @@ jest.mock("../hooks/useAgentConversation", () =>
|
|
|
20
20
|
conversationId: null,
|
|
21
21
|
startNewConversation: jest.fn(),
|
|
22
22
|
selectConversation: jest.fn(),
|
|
23
|
-
}))
|
|
23
|
+
})),
|
|
24
24
|
);
|
|
25
25
|
|
|
26
26
|
jest.mock("../../../hooks/useAgentConversations", () =>
|
|
@@ -29,7 +29,7 @@ jest.mock("../../../hooks/useAgentConversations", () =>
|
|
|
29
29
|
loading: false,
|
|
30
30
|
error: null,
|
|
31
31
|
refresh: jest.fn(),
|
|
32
|
-
}))
|
|
32
|
+
})),
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
jest.mock("react-router", () => ({
|
|
@@ -27,7 +27,7 @@ describe("<AssistantChat />", () => {
|
|
|
27
27
|
|
|
28
28
|
it("shows the title in the header when provided", async () => {
|
|
29
29
|
const rendered = render(
|
|
30
|
-
<AssistantChat {...defaultProps} title="My Conversation Title"
|
|
30
|
+
<AssistantChat {...defaultProps} title="My Conversation Title" />,
|
|
31
31
|
);
|
|
32
32
|
await waitForLoad(rendered);
|
|
33
33
|
|
|
@@ -38,9 +38,7 @@ describe("<AssistantChat />", () => {
|
|
|
38
38
|
const rendered = render(<AssistantChat {...defaultProps} title={null} />);
|
|
39
39
|
await waitForLoad(rendered);
|
|
40
40
|
|
|
41
|
-
expect(
|
|
42
|
-
rendered.getByText("assistant.newConversation")
|
|
43
|
-
).toBeInTheDocument();
|
|
41
|
+
expect(rendered.getByText("assistant.newConversation")).toBeInTheDocument();
|
|
44
42
|
});
|
|
45
43
|
|
|
46
44
|
it("groups logs in a thinking block and auto-collapses when a priority-0 response arrives", async () => {
|
|
@@ -69,13 +67,19 @@ describe("<AssistantChat />", () => {
|
|
|
69
67
|
];
|
|
70
68
|
|
|
71
69
|
const rendered = render(
|
|
72
|
-
<AssistantChat {...defaultProps} conversation={conversation}
|
|
70
|
+
<AssistantChat {...defaultProps} conversation={conversation} />,
|
|
73
71
|
);
|
|
74
72
|
await waitForLoad(rendered);
|
|
75
73
|
|
|
76
|
-
expect(
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
expect(
|
|
75
|
+
rendered.container.querySelector(".thinking-block"),
|
|
76
|
+
).toBeInTheDocument();
|
|
77
|
+
expect(
|
|
78
|
+
rendered.container.querySelector(".thinking-section__body"),
|
|
79
|
+
).not.toBeInTheDocument();
|
|
80
|
+
expect(
|
|
81
|
+
rendered.container.querySelector(".thinking-section__header"),
|
|
82
|
+
).toBeInTheDocument();
|
|
79
83
|
});
|
|
80
84
|
|
|
81
85
|
it("shows source label for priority-0 response messages", async () => {
|
|
@@ -90,7 +94,7 @@ describe("<AssistantChat />", () => {
|
|
|
90
94
|
];
|
|
91
95
|
|
|
92
96
|
const rendered = render(
|
|
93
|
-
<AssistantChat {...defaultProps} conversation={conversation}
|
|
97
|
+
<AssistantChat {...defaultProps} conversation={conversation} />,
|
|
94
98
|
);
|
|
95
99
|
await waitForLoad(rendered);
|
|
96
100
|
|
|
@@ -111,12 +115,12 @@ describe("<AssistantChat />", () => {
|
|
|
111
115
|
];
|
|
112
116
|
|
|
113
117
|
const rendered = render(
|
|
114
|
-
<AssistantChat {...defaultProps} conversation={conversation}
|
|
118
|
+
<AssistantChat {...defaultProps} conversation={conversation} />,
|
|
115
119
|
);
|
|
116
120
|
await waitForLoad(rendered);
|
|
117
121
|
|
|
118
122
|
const errorMessage = rendered.container.querySelector(
|
|
119
|
-
".assistant-chat__message--error"
|
|
123
|
+
".assistant-chat__message--error",
|
|
120
124
|
);
|
|
121
125
|
expect(errorMessage).toBeInTheDocument();
|
|
122
126
|
expect(rendered.getByText("Workflow Normalizer")).toBeInTheDocument();
|
|
@@ -34,14 +34,14 @@ const defaultProps = {
|
|
|
34
34
|
|
|
35
35
|
describe("<AssistantConversations />", () => {
|
|
36
36
|
beforeAll(() => {
|
|
37
|
-
jest
|
|
38
|
-
|
|
37
|
+
jest
|
|
38
|
+
.spyOn(Date.prototype, "toLocaleString")
|
|
39
|
+
.mockImplementation(function (_, options) {
|
|
39
40
|
return new Intl.DateTimeFormat("en", {
|
|
40
41
|
...options,
|
|
41
42
|
timeZone: "UTC",
|
|
42
43
|
}).format(this);
|
|
43
|
-
}
|
|
44
|
-
);
|
|
44
|
+
});
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
afterAll(() => {
|
|
@@ -65,7 +65,7 @@ describe("<AssistantConversations />", () => {
|
|
|
65
65
|
expect(rendered.getByText("Data governance overview")).toBeInTheDocument();
|
|
66
66
|
expect(rendered.getByText("What is a data domain?")).toBeInTheDocument();
|
|
67
67
|
expect(
|
|
68
|
-
rendered.getByText("assistant.conversation.noPreview")
|
|
68
|
+
rendered.getByText("assistant.conversation.noPreview"),
|
|
69
69
|
).toBeInTheDocument();
|
|
70
70
|
});
|
|
71
71
|
|
|
@@ -74,7 +74,7 @@ describe("<AssistantConversations />", () => {
|
|
|
74
74
|
await waitForLoad(rendered);
|
|
75
75
|
|
|
76
76
|
const items = rendered.container.querySelectorAll(
|
|
77
|
-
".ai-conversation-list__item-preview"
|
|
77
|
+
".ai-conversation-list__item-preview",
|
|
78
78
|
);
|
|
79
79
|
expect(items[0]).toHaveTextContent("Data governance overview");
|
|
80
80
|
expect(items[1]).toHaveTextContent("What is a data domain?");
|
|
@@ -83,12 +83,12 @@ describe("<AssistantConversations />", () => {
|
|
|
83
83
|
|
|
84
84
|
it("marks the active conversation", async () => {
|
|
85
85
|
const rendered = render(
|
|
86
|
-
<AssistantConversations {...defaultProps} activeId={1}
|
|
86
|
+
<AssistantConversations {...defaultProps} activeId={1} />,
|
|
87
87
|
);
|
|
88
88
|
await waitForLoad(rendered);
|
|
89
89
|
|
|
90
90
|
const items = rendered.container.querySelectorAll(
|
|
91
|
-
".ai-conversation-list__item"
|
|
91
|
+
".ai-conversation-list__item",
|
|
92
92
|
);
|
|
93
93
|
expect(items[0]).toHaveClass("ai-conversation-list__item--active");
|
|
94
94
|
expect(items[1]).not.toHaveClass("ai-conversation-list__item--active");
|
|
@@ -97,12 +97,12 @@ describe("<AssistantConversations />", () => {
|
|
|
97
97
|
it("calls onSelect with conversation id when an item is clicked", async () => {
|
|
98
98
|
const onSelect = jest.fn();
|
|
99
99
|
const rendered = render(
|
|
100
|
-
<AssistantConversations {...defaultProps} onSelect={onSelect}
|
|
100
|
+
<AssistantConversations {...defaultProps} onSelect={onSelect} />,
|
|
101
101
|
);
|
|
102
102
|
await waitForLoad(rendered);
|
|
103
103
|
|
|
104
104
|
const items = rendered.container.querySelectorAll(
|
|
105
|
-
".ai-conversation-list__item"
|
|
105
|
+
".ai-conversation-list__item",
|
|
106
106
|
);
|
|
107
107
|
fireEvent.click(items[0]);
|
|
108
108
|
expect(onSelect).toHaveBeenCalledWith(1);
|
|
@@ -114,12 +114,12 @@ describe("<AssistantConversations />", () => {
|
|
|
114
114
|
<AssistantConversations
|
|
115
115
|
{...defaultProps}
|
|
116
116
|
onNewConversation={onNewConversation}
|
|
117
|
-
|
|
117
|
+
/>,
|
|
118
118
|
);
|
|
119
119
|
await waitForLoad(rendered);
|
|
120
120
|
|
|
121
121
|
fireEvent.click(
|
|
122
|
-
rendered.container.querySelector(".ai-conversation-list__new")
|
|
122
|
+
rendered.container.querySelector(".ai-conversation-list__new"),
|
|
123
123
|
);
|
|
124
124
|
expect(onNewConversation).toHaveBeenCalled();
|
|
125
125
|
});
|
|
@@ -6,7 +6,7 @@ import { API_AGENT_LAYER_CONVERSATION } from "../../../api";
|
|
|
6
6
|
|
|
7
7
|
const useAgentConversation = (isOpen, initialId = null) => {
|
|
8
8
|
const [conversationId, setConversationId] = useState(
|
|
9
|
-
initialId != null ? String(initialId) : null
|
|
9
|
+
initialId != null ? String(initialId) : null,
|
|
10
10
|
);
|
|
11
11
|
|
|
12
12
|
useEffect(() => {
|
|
@@ -27,7 +27,7 @@ const useAgentConversation = (isOpen, initialId = null) => {
|
|
|
27
27
|
: null;
|
|
28
28
|
if (id != null) setConversationId(id);
|
|
29
29
|
})
|
|
30
|
-
.catch(() => {
|
|
30
|
+
.catch(() => {});
|
|
31
31
|
}, [isOpen, conversationId]);
|
|
32
32
|
|
|
33
33
|
const startNewConversation = useCallback(() => {
|
|
@@ -38,6 +38,7 @@ const useAssistantSocket = (disabled = false, options = {}) => {
|
|
|
38
38
|
socketRef.current = socket;
|
|
39
39
|
|
|
40
40
|
const disconnectRequestedRef = { current: false };
|
|
41
|
+
/* eslint-disable fp/no-let, fp/no-mutation */
|
|
41
42
|
let reconnectTimeoutId = null;
|
|
42
43
|
let connectTimeoutId = null;
|
|
43
44
|
|
|
@@ -67,6 +68,7 @@ const useAssistantSocket = (disabled = false, options = {}) => {
|
|
|
67
68
|
}
|
|
68
69
|
setSocketReady(false);
|
|
69
70
|
};
|
|
71
|
+
/* eslint-enable fp/no-let, fp/no-mutation */
|
|
70
72
|
}, [disabled]);
|
|
71
73
|
|
|
72
74
|
useEffect(() => {
|
package/src/components/index.js
CHANGED
|
@@ -3,4 +3,11 @@ import TranslationModal from "./TranslationModal";
|
|
|
3
3
|
import Assistant from "./assistant/Assistant";
|
|
4
4
|
import AssistantPage from "./assistant/AssistantPage";
|
|
5
5
|
import ThinkingOutLoud, { getSourceLabel } from "./ThinkingOutLoud";
|
|
6
|
-
export {
|
|
6
|
+
export {
|
|
7
|
+
AiRoutes,
|
|
8
|
+
TranslationModal,
|
|
9
|
+
Assistant,
|
|
10
|
+
AssistantPage,
|
|
11
|
+
ThinkingOutLoud,
|
|
12
|
+
getSourceLabel,
|
|
13
|
+
};
|
|
@@ -29,7 +29,7 @@ export default function PromptEditor({
|
|
|
29
29
|
const resourceTypeOptions = usePromptResourceTypeOptions();
|
|
30
30
|
const { defaultLang, enabledLangs } = useLanguage();
|
|
31
31
|
const [isTranslationPrompt, setIsTranslationPrompt] = useState(
|
|
32
|
-
selectedPrompt?.resource_type === "translation"
|
|
32
|
+
selectedPrompt?.resource_type === "translation",
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
const localeOptions = _.map((key) => ({
|
|
@@ -83,7 +83,7 @@ export default function PromptEditor({
|
|
|
83
83
|
prop: formatMessage({
|
|
84
84
|
id: "prompts.form.name",
|
|
85
85
|
}),
|
|
86
|
-
}
|
|
86
|
+
},
|
|
87
87
|
),
|
|
88
88
|
}}
|
|
89
89
|
render={({
|
|
@@ -116,7 +116,7 @@ export default function PromptEditor({
|
|
|
116
116
|
prop: formatMessage({
|
|
117
117
|
id: "prompts.form.resource_type",
|
|
118
118
|
}),
|
|
119
|
-
}
|
|
119
|
+
},
|
|
120
120
|
),
|
|
121
121
|
}}
|
|
122
122
|
render={({ field: { onBlur, onChange, value } }) => (
|
|
@@ -148,7 +148,7 @@ export default function PromptEditor({
|
|
|
148
148
|
prop: formatMessage({
|
|
149
149
|
id: "prompts.form.language",
|
|
150
150
|
}),
|
|
151
|
-
}
|
|
151
|
+
},
|
|
152
152
|
),
|
|
153
153
|
}}
|
|
154
154
|
render={({ field: { onBlur, onChange, value } }) => (
|
|
@@ -190,7 +190,7 @@ export default function PromptEditor({
|
|
|
190
190
|
prop: formatMessage({
|
|
191
191
|
id: "prompts.form.system_prompt",
|
|
192
192
|
}),
|
|
193
|
-
}
|
|
193
|
+
},
|
|
194
194
|
),
|
|
195
195
|
}}
|
|
196
196
|
render={({
|
|
@@ -223,7 +223,7 @@ export default function PromptEditor({
|
|
|
223
223
|
prop: formatMessage({
|
|
224
224
|
id: "prompts.form.user_prompt_template",
|
|
225
225
|
}),
|
|
226
|
-
}
|
|
226
|
+
},
|
|
227
227
|
),
|
|
228
228
|
}}
|
|
229
229
|
render={({
|
|
@@ -256,7 +256,7 @@ export default function PromptEditor({
|
|
|
256
256
|
prop: formatMessage({
|
|
257
257
|
id: "prompts.form.provider",
|
|
258
258
|
}),
|
|
259
|
-
}
|
|
259
|
+
},
|
|
260
260
|
),
|
|
261
261
|
}}
|
|
262
262
|
render={({ field: { onBlur, onChange, value } }) => (
|
|
@@ -44,7 +44,7 @@ export default function Prompts() {
|
|
|
44
44
|
|
|
45
45
|
const providersOptions = _.flow(
|
|
46
46
|
_.prop("data"),
|
|
47
|
-
_.map(({ id, name }) => ({ key: id, value: id, text: name }))
|
|
47
|
+
_.map(({ id, name }) => ({ key: id, value: id, text: name })),
|
|
48
48
|
)(providers);
|
|
49
49
|
|
|
50
50
|
const setStateNewPrompt = () => setSelectedPrompt(NEW_PROMPT);
|