@truedat/ai 8.6.7 → 8.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/package.json +3 -3
  2. package/src/components/ConceptSuggestions.js +10 -4
  3. package/src/components/StructureSuggestions.js +8 -9
  4. package/src/components/ThinkingOutLoud.js +5 -0
  5. package/src/components/TranslationModal.js +15 -15
  6. package/src/components/__tests__/ConceptSuggestions.spec.js +32 -20
  7. package/src/components/__tests__/StructureSuggestions.spec.js +25 -19
  8. package/src/components/__tests__/SuggestLinkButton.spec.js +3 -1
  9. package/src/components/__tests__/TranslationModal.spec.js +3 -3
  10. package/src/components/actions/ActionActions.js +2 -2
  11. package/src/components/actions/ActionDetail.js +1 -1
  12. package/src/components/actions/ActionEdit.js +2 -1
  13. package/src/components/actions/ActionForm.js +1 -1
  14. package/src/components/actions/ActionsContext.js +1 -1
  15. package/src/components/actions/ActionsTable.js +1 -1
  16. package/src/components/actions/__tests__/ActionsTable.spec.js +1 -1
  17. package/src/components/aiSandbox/AiSandbox.js +2 -2
  18. package/src/components/aiSandbox/RequestForm.js +1 -1
  19. package/src/components/assistant/Assistant.js +8 -6
  20. package/src/components/assistant/AssistantChat.js +4 -0
  21. package/src/components/assistant/AssistantConversations.js +1 -1
  22. package/src/components/assistant/AssistantPage.js +5 -5
  23. package/src/components/assistant/AssistantPageChat.js +31 -14
  24. package/src/components/assistant/__tests__/Assistant.spec.js +3 -3
  25. package/src/components/assistant/__tests__/AssistantChat.spec.js +15 -11
  26. package/src/components/assistant/__tests__/AssistantConversations.spec.js +12 -12
  27. package/src/components/assistant/hooks/useAgentConversation.js +2 -2
  28. package/src/components/assistant/hooks/useAssistantSocket.js +2 -0
  29. package/src/components/index.js +8 -1
  30. package/src/components/prompts/PromptEditor.js +7 -7
  31. package/src/components/prompts/Prompts.js +1 -1
  32. package/src/components/prompts/__tests__/PromptEditor.spec.js +8 -8
  33. package/src/components/providers/ProviderEditor.js +6 -10
  34. package/src/components/providers/Providers.js +5 -1
  35. package/src/components/providers/__tests__/ProviderEditor.spec.js +7 -7
  36. package/src/components/providers/providerProperties/Anthropic.js +1 -1
  37. package/src/components/providers/providerProperties/AzureOpenai.js +2 -2
  38. package/src/components/providers/providerProperties/BedrockClaude.js +2 -2
  39. package/src/components/providers/providerProperties/Gemini.js +1 -1
  40. package/src/components/providers/providerProperties/Openai.js +2 -2
  41. package/src/components/resourceMappings/ResourceMappingEditor.js +2 -2
  42. package/src/components/resourceMappings/ResourceMappingFields.js +1 -1
  43. package/src/components/resourceMappings/__tests__/ResourceMappingEditor.spec.js +7 -7
  44. package/src/components/resourceMappings/__tests__/ResourceMappings.spec.js +1 -1
  45. package/src/components/resourceMappings/selectors/DataStructureSelector.js +2 -2
  46. package/src/components/suggestions/__tests__/SuggestionsWidget.spec.js +9 -9
  47. package/src/hooks/__tests__/useAgentConversations.spec.js +10 -2
  48. package/src/hooks/useActions.js +1 -1
  49. package/src/hooks/useAgentConversations.js +4 -1
  50. package/src/hooks/useAgentLayerRun.js +1 -1
  51. package/src/hooks/useProviders.js +1 -1
  52. package/src/hooks/useResourceMappings.js +1 -1
  53. package/src/hooks/useSuggestions.js +1 -1
  54. 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 = {
@@ -95,7 +95,7 @@ export const ActionsTable = () => {
95
95
  setSortDirection,
96
96
  setSortColumn,
97
97
  sortDirection,
98
- sortColumn
98
+ sortColumn,
99
99
  )
100
100
  }
101
101
  />
@@ -45,7 +45,7 @@ describe("<ActionsTable />", () => {
45
45
  const { container } = render(
46
46
  <ActionsContextProvider {...searchProps}>
47
47
  <ActionsTable />
48
- </ActionsContextProvider>
48
+ </ActionsContextProvider>,
49
49
  );
50
50
  expect(container).toMatchSnapshot();
51
51
  });
@@ -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 } = useAgentConversations();
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))?.title ??
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) { setShowScrollToBottom(false); return; }
283
+ if (clientHeight < 2) {
284
+ setShowScrollToBottom(false);
285
+ return;
286
+ }
275
287
  const hasOverflow = scrollHeight > clientHeight + SCROLL_OVERFLOW_EPSILON;
276
- if (!hasOverflow) { setShowScrollToBottom(false); return; }
277
- const atBottom = scrollHeight - scrollTop - clientHeight <= SCROLL_AT_BOTTOM_THRESHOLD;
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 = isP0 && msg.source ? getSourceLabel(msg.source) : null;
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(rendered.container.querySelector(".thinking-block")).toBeInTheDocument();
77
- expect(rendered.container.querySelector(".thinking-section__body")).not.toBeInTheDocument();
78
- expect(rendered.container.querySelector(".thinking-section__header")).toBeInTheDocument();
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.spyOn(Date.prototype, "toLocaleString").mockImplementation(
38
- function (_, options) {
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(() => {
@@ -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 { AiRoutes, TranslationModal, Assistant, AssistantPage, ThinkingOutLoud, getSourceLabel };
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);