@clubmed/usg-chat-ui 1.5.0 → 1.6.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/README.md +6 -3
- package/assets/style.css +1 -1
- package/chunks/ChatApiClient.js +1 -1
- package/chunks/ChatApiClient.js.map +1 -1
- package/chunks/index.js.map +1 -1
- package/chunks/index3.js.map +1 -1
- package/chunks/index5.js +3 -3
- package/chunks/index5.js.map +1 -1
- package/chunks/index7.js +1 -5
- package/chunks/index7.js.map +1 -1
- package/chunks/react.esm.js +1 -0
- package/chunks/react.esm.js.map +1 -1
- package/chunks/react.js.map +1 -1
- package/chunks/useCollaboration.js +6 -6
- package/contexts/ChatJiraContext.js +3 -3
- package/molecules/AiElements/Conversation.js +3 -3
- package/molecules/AiElements/Conversation.js.map +1 -1
- package/molecules/AiElements/PromptInput.js +4 -4
- package/molecules/AiElements/Response.js.map +1 -1
- package/molecules/Collapsibles/Collapsible.js +5 -5
- package/molecules/Collapsibles/Collapsible.js.map +1 -1
- package/molecules/Labels/Label.js.map +1 -1
- package/molecules/RichText/EditorWithAI.js +3752 -3736
- package/molecules/RichText/EditorWithAI.js.map +1 -1
- package/molecules/Tabs/Tabs.js +1 -1
- package/molecules/Tabs/Tabs.js.map +1 -1
- package/organisms/canvas/CanvasLayout.js +950 -928
- package/organisms/canvas/CanvasLayout.js.map +1 -1
- package/organisms/chat/hooks/useChat.js +74 -74
- package/organisms/chat/hooks/useChat.js.map +1 -1
- package/organisms/chat/hooks/useChat.test.d.ts +1 -0
- package/organisms/chat/hooks/useChat.test.js +218 -0
- package/organisms/chat/hooks/useChat.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState as
|
|
2
|
+
import { useState as k, useCallback as T } from "react";
|
|
3
3
|
import { parseChatCommand as V, shouldHandleCommand as B, getCommandHelp as G } from "../../../utils/chat-commands.js";
|
|
4
4
|
import { useToast as X } from "../../../molecules/Notifications/useToast.js";
|
|
5
5
|
import { useCanvasStore as Y } from "../../../utils/canvas-store.js";
|
|
@@ -9,40 +9,40 @@ import { useChatJira as se } from "../../../contexts/ChatJiraContext.js";
|
|
|
9
9
|
import { useChatPreferences as re } from "./useChatPreferences.js";
|
|
10
10
|
import { useChatSyncUserSettings as ne } from "./useChatSyncUserSettings.js";
|
|
11
11
|
import { useChatKeyboardsShortcuts as oe } from "./useChatKeyboardsShortcuts.js";
|
|
12
|
-
const ae = (e) => e == null ? void 0 : e.map((
|
|
13
|
-
href:
|
|
14
|
-
title:
|
|
12
|
+
const ae = (e) => e == null ? void 0 : e.map((s) => ({
|
|
13
|
+
href: s.href || s.url || "#",
|
|
14
|
+
title: s.title || "Source"
|
|
15
15
|
})), ie = (e) => {
|
|
16
16
|
if (e)
|
|
17
17
|
return typeof e == "string" ? { content: e, duration: 0 } : {
|
|
18
18
|
content: e.content ?? "",
|
|
19
19
|
duration: e.duration ?? 0
|
|
20
20
|
};
|
|
21
|
-
},
|
|
21
|
+
}, K = (e) => {
|
|
22
22
|
if (e.response_type === "auth_required")
|
|
23
23
|
throw new Error("Cannot build assistant response for auth-required payload");
|
|
24
|
-
const
|
|
25
|
-
id:
|
|
24
|
+
const s = `assistant-${Date.now()}`, f = {
|
|
25
|
+
id: s,
|
|
26
26
|
content: e.content || "Aucune réponse disponible",
|
|
27
27
|
responseType: e.response_type,
|
|
28
28
|
canvasData: e.canvas_data,
|
|
29
29
|
followupQuestions: e.followup_questions
|
|
30
30
|
};
|
|
31
31
|
return {
|
|
32
|
-
key:
|
|
33
|
-
version:
|
|
32
|
+
key: s,
|
|
33
|
+
version: f,
|
|
34
34
|
sources: ae(e.sources),
|
|
35
35
|
reasoning: ie(e.reasoning)
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
38
|
function ye() {
|
|
39
|
-
const { toast: e } = X(),
|
|
40
|
-
user:
|
|
39
|
+
const { toast: e } = X(), s = Z(), { setJiraConfigured: f, setJiraAuthSettings: w } = se(), {
|
|
40
|
+
user: q,
|
|
41
41
|
dbUserId: C
|
|
42
|
-
} = ee(), [A,
|
|
43
|
-
chatMessages:
|
|
44
|
-
setChatMessages:
|
|
45
|
-
currentConversationId:
|
|
42
|
+
} = ee(), [A, S] = k(!1), [D, N] = k(!1), [R, v] = k(""), {
|
|
43
|
+
chatMessages: c,
|
|
44
|
+
setChatMessages: h,
|
|
45
|
+
currentConversationId: u,
|
|
46
46
|
sidebarRefreshTrigger: U,
|
|
47
47
|
isLoadingMessage: x,
|
|
48
48
|
setIsLoadingMessage: o,
|
|
@@ -59,15 +59,15 @@ function ye() {
|
|
|
59
59
|
canvasWidth: O,
|
|
60
60
|
isResizing: z,
|
|
61
61
|
resizeWidth: F
|
|
62
|
-
} = Y(), J =
|
|
63
|
-
async (
|
|
62
|
+
} = Y(), J = T(
|
|
63
|
+
async (d) => {
|
|
64
64
|
var y;
|
|
65
|
-
if (!((y =
|
|
65
|
+
if (!((y = d.text) != null && y.trim()))
|
|
66
66
|
return;
|
|
67
|
-
const a =
|
|
67
|
+
const a = d.text.trim(), i = V(a);
|
|
68
68
|
if (B(i)) {
|
|
69
69
|
if (i.command === "settings") {
|
|
70
|
-
|
|
70
|
+
S(!0);
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
if (i.command === "help") {
|
|
@@ -84,11 +84,11 @@ function ye() {
|
|
|
84
84
|
avatar: "https://github.com/openai.png",
|
|
85
85
|
name: "Assistant"
|
|
86
86
|
};
|
|
87
|
-
|
|
87
|
+
h((l) => [...l, t]), v("");
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
if (i.command === "clear") {
|
|
91
|
-
|
|
91
|
+
h([]), e({
|
|
92
92
|
title: "Cleared",
|
|
93
93
|
description: "Conversation history cleared"
|
|
94
94
|
}), v("");
|
|
@@ -107,7 +107,7 @@ function ye() {
|
|
|
107
107
|
avatar: "https://github.com/haydenbleasel.png",
|
|
108
108
|
name: "User"
|
|
109
109
|
};
|
|
110
|
-
|
|
110
|
+
h((t) => [...t, I]), v(""), setTimeout(() => {
|
|
111
111
|
g();
|
|
112
112
|
}, 200), o(!0);
|
|
113
113
|
try {
|
|
@@ -115,36 +115,36 @@ function ye() {
|
|
|
115
115
|
projectKey: n.projectKey,
|
|
116
116
|
status: n.status,
|
|
117
117
|
boardId: n.boardId
|
|
118
|
-
} : void 0,
|
|
118
|
+
} : void 0, l = await s.chatCanvas({
|
|
119
119
|
message: a,
|
|
120
|
-
conversationHistory:
|
|
121
|
-
(
|
|
122
|
-
role:
|
|
120
|
+
conversationHistory: c.flatMap(
|
|
121
|
+
(r) => r.versions.map((Q) => ({
|
|
122
|
+
role: r.from,
|
|
123
123
|
content: Q.content
|
|
124
124
|
}))
|
|
125
125
|
),
|
|
126
126
|
projectKey: b ?? void 0,
|
|
127
127
|
userId: C ?? void 0,
|
|
128
|
-
conversationId:
|
|
128
|
+
conversationId: u ?? void 0,
|
|
129
129
|
releaseNoteSettings: t
|
|
130
130
|
});
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
authUrl:
|
|
134
|
-
threadId:
|
|
131
|
+
if (l.response_type === "auth_required") {
|
|
132
|
+
S(!0), w({
|
|
133
|
+
authUrl: l.auth_url ?? "",
|
|
134
|
+
threadId: u || void 0
|
|
135
135
|
}), o(!1);
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
|
-
const { key:
|
|
139
|
-
key:
|
|
138
|
+
const { key: p, version: _, sources: M, reasoning: j } = K(l), m = {
|
|
139
|
+
key: p,
|
|
140
140
|
from: "assistant",
|
|
141
|
-
versions: [
|
|
141
|
+
versions: [_],
|
|
142
142
|
avatar: "https://github.com/openai.png",
|
|
143
143
|
name: "Assistant",
|
|
144
|
-
sources:
|
|
145
|
-
reasoning:
|
|
144
|
+
sources: M,
|
|
145
|
+
reasoning: j
|
|
146
146
|
};
|
|
147
|
-
|
|
147
|
+
h((r) => [...r, m]), o(!1), setTimeout(() => {
|
|
148
148
|
g();
|
|
149
149
|
}, 100);
|
|
150
150
|
} catch (t) {
|
|
@@ -156,23 +156,23 @@ function ye() {
|
|
|
156
156
|
}
|
|
157
157
|
},
|
|
158
158
|
[
|
|
159
|
-
|
|
159
|
+
s,
|
|
160
|
+
c,
|
|
160
161
|
u,
|
|
161
|
-
d,
|
|
162
162
|
C,
|
|
163
163
|
b,
|
|
164
164
|
n,
|
|
165
165
|
g,
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
w,
|
|
167
|
+
f,
|
|
168
168
|
e
|
|
169
169
|
]
|
|
170
|
-
), L =
|
|
171
|
-
async (
|
|
170
|
+
), L = T(
|
|
171
|
+
async (d) => {
|
|
172
172
|
var y;
|
|
173
|
-
const a =
|
|
173
|
+
const a = c.findIndex((t) => t.key === d);
|
|
174
174
|
if (a === -1) return;
|
|
175
|
-
const i = a > 0 ?
|
|
175
|
+
const i = a > 0 ? c[a - 1] : null, I = ((y = i == null ? void 0 : i.versions[0]) == null ? void 0 : y.content) || "";
|
|
176
176
|
if (!I) {
|
|
177
177
|
e({
|
|
178
178
|
title: "Erreur",
|
|
@@ -187,34 +187,34 @@ function ye() {
|
|
|
187
187
|
projectKey: n.projectKey,
|
|
188
188
|
status: n.status,
|
|
189
189
|
boardId: n.boardId
|
|
190
|
-
} : void 0,
|
|
191
|
-
(
|
|
192
|
-
role:
|
|
193
|
-
content:
|
|
190
|
+
} : void 0, l = c.slice(0, a).flatMap(
|
|
191
|
+
(m) => m.versions.map((r) => ({
|
|
192
|
+
role: m.from,
|
|
193
|
+
content: r.content
|
|
194
194
|
}))
|
|
195
|
-
),
|
|
195
|
+
), p = await s.chatCanvas({
|
|
196
196
|
message: I,
|
|
197
|
-
conversationHistory:
|
|
197
|
+
conversationHistory: l,
|
|
198
198
|
projectKey: b ?? void 0,
|
|
199
199
|
userId: C ?? void 0,
|
|
200
|
-
conversationId:
|
|
200
|
+
conversationId: u ?? void 0,
|
|
201
201
|
releaseNoteSettings: t
|
|
202
202
|
});
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
authUrl:
|
|
206
|
-
threadId:
|
|
203
|
+
if (p.response_type === "auth_required") {
|
|
204
|
+
p.error === "jira_oauth_required" && f(!1), w({
|
|
205
|
+
authUrl: p.auth_url ?? "",
|
|
206
|
+
threadId: u || void 0
|
|
207
207
|
}), o(!1);
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
|
-
const { version:
|
|
211
|
-
|
|
212
|
-
(
|
|
213
|
-
...
|
|
214
|
-
versions: [...
|
|
215
|
-
sources:
|
|
216
|
-
reasoning:
|
|
217
|
-
} :
|
|
210
|
+
const { version: _, sources: M, reasoning: j } = K(p);
|
|
211
|
+
h(
|
|
212
|
+
(m) => m.map((r) => r.key === d ? {
|
|
213
|
+
...r,
|
|
214
|
+
versions: [...r.versions, _],
|
|
215
|
+
sources: M,
|
|
216
|
+
reasoning: j
|
|
217
|
+
} : r)
|
|
218
218
|
), o(!1), setTimeout(() => {
|
|
219
219
|
g();
|
|
220
220
|
}, 100);
|
|
@@ -227,28 +227,28 @@ function ye() {
|
|
|
227
227
|
}
|
|
228
228
|
},
|
|
229
229
|
[
|
|
230
|
-
|
|
230
|
+
s,
|
|
231
|
+
c,
|
|
231
232
|
u,
|
|
232
|
-
d,
|
|
233
233
|
C,
|
|
234
234
|
b,
|
|
235
235
|
n,
|
|
236
236
|
g,
|
|
237
|
-
|
|
237
|
+
f,
|
|
238
238
|
e
|
|
239
239
|
]
|
|
240
|
-
), W =
|
|
241
|
-
v(
|
|
240
|
+
), W = T((d) => {
|
|
241
|
+
v(d);
|
|
242
242
|
}, []);
|
|
243
243
|
return {
|
|
244
|
-
user:
|
|
245
|
-
chatMessages:
|
|
244
|
+
user: q,
|
|
245
|
+
chatMessages: c,
|
|
246
246
|
settingsOpen: A,
|
|
247
|
-
setSettingsOpen:
|
|
247
|
+
setSettingsOpen: S,
|
|
248
248
|
sidebarOpen: D,
|
|
249
249
|
setSidebarOpen: N,
|
|
250
250
|
sidebarRefreshTrigger: U,
|
|
251
|
-
currentConversationId:
|
|
251
|
+
currentConversationId: u,
|
|
252
252
|
loadConversation: P,
|
|
253
253
|
handleNewConversation: $,
|
|
254
254
|
isLoadingMessage: x,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChat.js","sources":["../../../../lib/organisms/chat/hooks/useChat.ts"],"sourcesContent":["\"use client\";\n\nimport {useCallback, useState} from \"react\";\nimport {getCommandHelp, parseChatCommand, shouldHandleCommand} from \"../../../utils/chat-commands\";\nimport {useToast} from \"../../../molecules/Notifications/useToast\";\nimport type {PromptInputMessage} from \"@clubmed/usg-chat-ui/molecules/AiElements/PromptInput\";\nimport {useCanvasStore} from \"../../../utils/canvas-store\";\nimport type {ChatMessage} from \"../types\";\nimport type {ChatCanvasResponse} from \"@clubmed/usg-chat-ui/core/interfaces/ChatCanvas\";\nimport {useChatApiClient, useChatConfig} from \"../../../contexts/ChatContext\";\nimport {useConversations} from \"./useConversations\";\nimport {useChatJira} from \"@clubmed/usg-chat-ui/contexts/ChatJiraContext\";\nimport {useChatPreferences} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatPreferences\";\nimport {useChatSyncUserSettings} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatSyncUserSettings\";\nimport {useChatKeyboardsShortcuts} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatKeyboardsShortcuts\";\n\nconst mapCanvasSources = (sources: ChatCanvasResponse[\"sources\"]) =>\n sources?.map((source) => ({\n href: source.href || source.url || \"#\",\n title: source.title || \"Source\",\n }));\n\nconst mapCanvasReasoning = (reasoning: ChatCanvasResponse[\"reasoning\"]) => {\n if (!reasoning) {\n return undefined;\n }\n\n if (typeof reasoning === \"string\") {\n return {content: reasoning, duration: 0};\n }\n\n return {\n content: reasoning.content ?? \"\",\n duration: reasoning.duration ?? 0,\n };\n};\n\nconst buildAssistantResponseParts = (data: ChatCanvasResponse) => {\n if (data.response_type === \"auth_required\") {\n throw new Error(\"Cannot build assistant response for auth-required payload\");\n }\n\n const id = `assistant-${Date.now()}`;\n const version: ChatMessage[\"versions\"][number] = {\n id,\n content: data.content || \"Aucune réponse disponible\",\n responseType: data.response_type,\n canvasData: data.canvas_data,\n followupQuestions: data.followup_questions,\n };\n\n return {\n key: id,\n version,\n sources: mapCanvasSources(data.sources),\n reasoning: mapCanvasReasoning(data.reasoning),\n };\n};\n\n\nexport function useChat() {\n const {toast} = useToast();\n const apiClient = useChatApiClient();\n const {setJiraConfigured, setJiraAuthSettings} = useChatJira();\n\n const {\n user,\n dbUserId,\n } = useChatConfig();\n\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [localInput, setLocalInput] = useState(\"\");\n\n const {\n chatMessages,\n setChatMessages,\n currentConversationId,\n sidebarRefreshTrigger,\n isLoadingMessage,\n setIsLoadingMessage,\n loadConversation,\n handleNewConversation,\n saveConversation,\n } = useConversations();\n\n useChatSyncUserSettings();\n useChatKeyboardsShortcuts();\n useChatPreferences();\n\n const {\n canvasType,\n projectKey,\n releaseNoteSettings,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n } = useCanvasStore();\n\n const handleSubmit = useCallback(\n async (message: PromptInputMessage) => {\n\n if (!message.text?.trim()) {\n return;\n }\n\n const userMessage = message.text.trim();\n const parsed = parseChatCommand(userMessage);\n\n if (shouldHandleCommand(parsed)) {\n if (parsed.command === \"settings\") {\n setSettingsOpen(true);\n return;\n }\n\n if (parsed.command === \"help\") {\n const helpMessage: ChatMessage = {\n key: `assistant-${Date.now()}`,\n from: \"assistant\",\n versions: [\n {\n id: `assistant-${Date.now()}`,\n content: getCommandHelp(),\n responseType: \"message\",\n },\n ],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n };\n setChatMessages((prev) => [...prev, helpMessage]);\n setLocalInput(\"\");\n return;\n }\n\n if (parsed.command === \"clear\") {\n setChatMessages([]);\n toast({\n title: \"Cleared\",\n description: \"Conversation history cleared\",\n });\n setLocalInput(\"\");\n return;\n }\n }\n\n const newUserMessage: ChatMessage = {\n key: `user-${Date.now()}`,\n from: \"user\",\n versions: [\n {\n id: `user-${Date.now()}`,\n content: userMessage,\n },\n ],\n avatar: \"https://github.com/haydenbleasel.png\",\n name: \"User\",\n };\n setChatMessages((prev) => [...prev, newUserMessage]);\n setLocalInput(\"\");\n\n setTimeout(() => {\n saveConversation();\n }, 200);\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: chatMessages.flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n ),\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setChatMessages((prev) => prev.slice(0, -1));\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {key, version, sources, reasoning} = buildAssistantResponseParts(data);\n\n const assistantMessage: ChatMessage = {\n key,\n from: \"assistant\",\n versions: [version],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n sources,\n reasoning,\n };\n\n setChatMessages((prev) => [...prev, assistantMessage]);\n setIsLoadingMessage(false);\n\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Chat error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Error\",\n description: \"Failed to get response. Please try again.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraAuthSettings,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleRegenerate = useCallback(\n async (messageKey: string) => {\n const messageIndex = chatMessages.findIndex((msg) => msg.key === messageKey);\n if (messageIndex === -1) return;\n\n const previousMessage = messageIndex > 0 ? chatMessages[messageIndex - 1] : null;\n const userMessage = previousMessage?.versions[0]?.content || \"\";\n\n if (!userMessage) {\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer : aucun message précédent trouvé\",\n variant: \"destructive\",\n });\n return;\n }\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const history = chatMessages.slice(0, messageIndex).flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n );\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: history,\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {version, sources, reasoning} = buildAssistantResponseParts(data);\n\n setChatMessages((prev) =>\n prev.map((msg) => {\n if (msg.key === messageKey) {\n return {\n ...msg,\n versions: [...msg.versions, version],\n sources,\n reasoning,\n };\n }\n return msg;\n })\n );\n\n setIsLoadingMessage(false);\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Regenerate error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer la réponse. Veuillez réessayer.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleFollowupClick = useCallback((question: string) => {\n setLocalInput(question);\n }, []);\n\n return {\n user,\n chatMessages,\n settingsOpen,\n setSettingsOpen,\n sidebarOpen,\n setSidebarOpen,\n sidebarRefreshTrigger,\n currentConversationId,\n loadConversation,\n handleNewConversation,\n isLoadingMessage,\n canvasType,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n handleFollowupClick,\n handleSubmit,\n handleRegenerate,\n localInput,\n setLocalInput,\n };\n}\n"],"names":["mapCanvasSources","sources","source","mapCanvasReasoning","reasoning","buildAssistantResponseParts","data","id","version","useChat","toast","useToast","apiClient","useChatApiClient","setJiraConfigured","setJiraAuthSettings","useChatJira","user","dbUserId","useChatConfig","settingsOpen","setSettingsOpen","useState","sidebarOpen","setSidebarOpen","localInput","setLocalInput","chatMessages","setChatMessages","currentConversationId","sidebarRefreshTrigger","isLoadingMessage","setIsLoadingMessage","loadConversation","handleNewConversation","saveConversation","useConversations","useChatSyncUserSettings","useChatKeyboardsShortcuts","useChatPreferences","canvasType","projectKey","releaseNoteSettings","isFullscreen","canvasWidth","isResizing","resizeWidth","useCanvasStore","handleSubmit","useCallback","message","_a","userMessage","parsed","parseChatCommand","shouldHandleCommand","helpMessage","getCommandHelp","prev","newUserMessage","releaseNotePayload","m","v","key","assistantMessage","error","handleRegenerate","messageKey","messageIndex","msg","previousMessage","history","handleFollowupClick","question"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useChat.js","sources":["../../../../lib/organisms/chat/hooks/useChat.ts"],"sourcesContent":["\"use client\";\n\nimport {useCallback, useState} from \"react\";\nimport {getCommandHelp, parseChatCommand, shouldHandleCommand} from \"../../../utils/chat-commands\";\nimport {useToast} from \"../../../molecules/Notifications/useToast\";\nimport type {PromptInputMessage} from \"@clubmed/usg-chat-ui/molecules/AiElements/PromptInput\";\nimport {useCanvasStore} from \"../../../utils/canvas-store\";\nimport type {ChatMessage} from \"../types\";\nimport type {ChatCanvasResponse} from \"@clubmed/usg-chat-ui/core/interfaces/ChatCanvas\";\nimport {useChatApiClient, useChatConfig} from \"../../../contexts/ChatContext\";\nimport {useConversations} from \"./useConversations\";\nimport {useChatJira} from \"@clubmed/usg-chat-ui/contexts/ChatJiraContext\";\nimport {useChatPreferences} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatPreferences\";\nimport {useChatSyncUserSettings} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatSyncUserSettings\";\nimport {useChatKeyboardsShortcuts} from \"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatKeyboardsShortcuts\";\n\nconst mapCanvasSources = (sources: ChatCanvasResponse[\"sources\"]) =>\n sources?.map((source) => ({\n href: source.href || source.url || \"#\",\n title: source.title || \"Source\",\n }));\n\nconst mapCanvasReasoning = (reasoning: ChatCanvasResponse[\"reasoning\"]) => {\n if (!reasoning) {\n return undefined;\n }\n\n if (typeof reasoning === \"string\") {\n return {content: reasoning, duration: 0};\n }\n\n return {\n content: reasoning.content ?? \"\",\n duration: reasoning.duration ?? 0,\n };\n};\n\nconst buildAssistantResponseParts = (data: ChatCanvasResponse) => {\n if (data.response_type === \"auth_required\") {\n throw new Error(\"Cannot build assistant response for auth-required payload\");\n }\n\n const id = `assistant-${Date.now()}`;\n const version: ChatMessage[\"versions\"][number] = {\n id,\n content: data.content || \"Aucune réponse disponible\",\n responseType: data.response_type,\n canvasData: data.canvas_data,\n followupQuestions: data.followup_questions,\n };\n\n return {\n key: id,\n version,\n sources: mapCanvasSources(data.sources),\n reasoning: mapCanvasReasoning(data.reasoning),\n };\n};\n\n\nexport function useChat() {\n const {toast} = useToast();\n const apiClient = useChatApiClient();\n const {setJiraConfigured, setJiraAuthSettings} = useChatJira();\n\n const {\n user,\n dbUserId,\n } = useChatConfig();\n\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n const [localInput, setLocalInput] = useState(\"\");\n\n const {\n chatMessages,\n setChatMessages,\n currentConversationId,\n sidebarRefreshTrigger,\n isLoadingMessage,\n setIsLoadingMessage,\n loadConversation,\n handleNewConversation,\n saveConversation,\n } = useConversations();\n\n useChatSyncUserSettings();\n useChatKeyboardsShortcuts();\n useChatPreferences();\n\n const {\n canvasType,\n projectKey,\n releaseNoteSettings,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n } = useCanvasStore();\n\n const handleSubmit = useCallback(\n async (message: PromptInputMessage) => {\n\n if (!message.text?.trim()) {\n return;\n }\n\n const userMessage = message.text.trim();\n const parsed = parseChatCommand(userMessage);\n\n if (shouldHandleCommand(parsed)) {\n if (parsed.command === \"settings\") {\n setSettingsOpen(true);\n return;\n }\n\n if (parsed.command === \"help\") {\n const helpMessage: ChatMessage = {\n key: `assistant-${Date.now()}`,\n from: \"assistant\",\n versions: [\n {\n id: `assistant-${Date.now()}`,\n content: getCommandHelp(),\n responseType: \"message\",\n },\n ],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n };\n setChatMessages((prev) => [...prev, helpMessage]);\n setLocalInput(\"\");\n return;\n }\n\n if (parsed.command === \"clear\") {\n setChatMessages([]);\n toast({\n title: \"Cleared\",\n description: \"Conversation history cleared\",\n });\n setLocalInput(\"\");\n return;\n }\n }\n\n const newUserMessage: ChatMessage = {\n key: `user-${Date.now()}`,\n from: \"user\",\n versions: [\n {\n id: `user-${Date.now()}`,\n content: userMessage,\n },\n ],\n avatar: \"https://github.com/haydenbleasel.png\",\n name: \"User\",\n };\n setChatMessages((prev) => [...prev, newUserMessage]);\n setLocalInput(\"\");\n\n setTimeout(() => {\n saveConversation();\n }, 200);\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: chatMessages.flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n ),\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n // if (data.error === \"jira_oauth_required\") {\n // setJiraConfigured(false);\n // }\n\n setSettingsOpen(true);\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {key, version, sources, reasoning} = buildAssistantResponseParts(data);\n\n const assistantMessage: ChatMessage = {\n key,\n from: \"assistant\",\n versions: [version],\n avatar: \"https://github.com/openai.png\",\n name: \"Assistant\",\n sources,\n reasoning,\n };\n\n setChatMessages((prev) => [...prev, assistantMessage]);\n setIsLoadingMessage(false);\n\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Chat error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Error\",\n description: \"Failed to get response. Please try again.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraAuthSettings,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleRegenerate = useCallback(\n async (messageKey: string) => {\n const messageIndex = chatMessages.findIndex((msg) => msg.key === messageKey);\n if (messageIndex === -1) return;\n\n const previousMessage = messageIndex > 0 ? chatMessages[messageIndex - 1] : null;\n const userMessage = previousMessage?.versions[0]?.content || \"\";\n\n if (!userMessage) {\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer : aucun message précédent trouvé\",\n variant: \"destructive\",\n });\n return;\n }\n\n setIsLoadingMessage(true);\n\n try {\n const releaseNotePayload = releaseNoteSettings\n ? {\n projectKey: releaseNoteSettings.projectKey,\n status: releaseNoteSettings.status,\n boardId: releaseNoteSettings.boardId,\n }\n : undefined;\n\n const history = chatMessages.slice(0, messageIndex).flatMap((m) =>\n m.versions.map((v: ChatMessage[\"versions\"][number]) => ({\n role: m.from,\n content: v.content,\n }))\n );\n\n const data = await apiClient.chatCanvas({\n message: userMessage,\n conversationHistory: history,\n projectKey: projectKey ?? undefined,\n userId: dbUserId ?? undefined,\n conversationId: currentConversationId ?? undefined,\n releaseNoteSettings: releaseNotePayload,\n });\n\n if (data.response_type === \"auth_required\") {\n if (data.error === \"jira_oauth_required\") {\n setJiraConfigured(false);\n }\n\n setJiraAuthSettings({\n authUrl: data.auth_url ?? \"\",\n threadId: currentConversationId || undefined,\n });\n\n setIsLoadingMessage(false);\n return;\n }\n\n const {version, sources, reasoning} = buildAssistantResponseParts(data);\n\n setChatMessages((prev) =>\n prev.map((msg) => {\n if (msg.key === messageKey) {\n return {\n ...msg,\n versions: [...msg.versions, version],\n sources,\n reasoning,\n };\n }\n return msg;\n })\n );\n\n setIsLoadingMessage(false);\n setTimeout(() => {\n saveConversation();\n }, 100);\n } catch (error) {\n console.error(\"Regenerate error:\", error);\n setIsLoadingMessage(false);\n toast({\n title: \"Erreur\",\n description: \"Impossible de régénérer la réponse. Veuillez réessayer.\",\n variant: \"destructive\",\n });\n }\n },\n [\n apiClient,\n chatMessages,\n currentConversationId,\n dbUserId,\n projectKey,\n releaseNoteSettings,\n saveConversation,\n setJiraConfigured,\n toast,\n ]\n );\n\n const handleFollowupClick = useCallback((question: string) => {\n setLocalInput(question);\n }, []);\n\n return {\n user,\n chatMessages,\n settingsOpen,\n setSettingsOpen,\n sidebarOpen,\n setSidebarOpen,\n sidebarRefreshTrigger,\n currentConversationId,\n loadConversation,\n handleNewConversation,\n isLoadingMessage,\n canvasType,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n handleFollowupClick,\n handleSubmit,\n handleRegenerate,\n localInput,\n setLocalInput,\n };\n}\n"],"names":["mapCanvasSources","sources","source","mapCanvasReasoning","reasoning","buildAssistantResponseParts","data","id","version","useChat","toast","useToast","apiClient","useChatApiClient","setJiraConfigured","setJiraAuthSettings","useChatJira","user","dbUserId","useChatConfig","settingsOpen","setSettingsOpen","useState","sidebarOpen","setSidebarOpen","localInput","setLocalInput","chatMessages","setChatMessages","currentConversationId","sidebarRefreshTrigger","isLoadingMessage","setIsLoadingMessage","loadConversation","handleNewConversation","saveConversation","useConversations","useChatSyncUserSettings","useChatKeyboardsShortcuts","useChatPreferences","canvasType","projectKey","releaseNoteSettings","isFullscreen","canvasWidth","isResizing","resizeWidth","useCanvasStore","handleSubmit","useCallback","message","_a","userMessage","parsed","parseChatCommand","shouldHandleCommand","helpMessage","getCommandHelp","prev","newUserMessage","releaseNotePayload","m","v","key","assistantMessage","error","handleRegenerate","messageKey","messageIndex","msg","previousMessage","history","handleFollowupClick","question"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { r as l, b as o } from "../../../chunks/react.esm.js";
|
|
2
|
+
import { useChat as u } from "./useChat.js";
|
|
3
|
+
import { getCommandHelp as R } from "../../../utils/chat-commands.js";
|
|
4
|
+
import { v as s, d as T, b as A, a as j, i as h, g as t } from "../../../chunks/vi.2VT5v0um.js";
|
|
5
|
+
const H = s.fn(), r = s.fn(), I = s.fn(), w = s.fn(), k = s.fn(), p = s.fn(), K = s.fn(), W = s.fn();
|
|
6
|
+
let n = [];
|
|
7
|
+
const C = "conversation-1", i = {
|
|
8
|
+
canvasType: "story",
|
|
9
|
+
projectKey: "PROJ-1",
|
|
10
|
+
releaseNoteSettings: {
|
|
11
|
+
projectKey: "REL-1",
|
|
12
|
+
status: "Done",
|
|
13
|
+
boardId: 99
|
|
14
|
+
},
|
|
15
|
+
isFullscreen: !1,
|
|
16
|
+
canvasWidth: 420,
|
|
17
|
+
isResizing: !1,
|
|
18
|
+
resizeWidth: null
|
|
19
|
+
}, N = (e) => {
|
|
20
|
+
typeof e == "function" ? n = e(n) : n = e;
|
|
21
|
+
}, S = s.fn(N);
|
|
22
|
+
s.mock("../../../molecules/Notifications/useToast", () => ({
|
|
23
|
+
useToast: () => ({ toast: H })
|
|
24
|
+
}));
|
|
25
|
+
s.mock("../../../contexts/ChatContext", () => ({
|
|
26
|
+
useChatApiClient: () => ({ chatCanvas: r }),
|
|
27
|
+
useChatConfig: () => ({ user: { id: "user-1" }, dbUserId: "db-user" })
|
|
28
|
+
}));
|
|
29
|
+
s.mock("@clubmed/usg-chat-ui/contexts/ChatJiraContext", () => ({
|
|
30
|
+
useChatJira: () => ({
|
|
31
|
+
setJiraConfigured: I,
|
|
32
|
+
setJiraAuthSettings: w
|
|
33
|
+
})
|
|
34
|
+
}));
|
|
35
|
+
s.mock("../../../utils/canvas-store", () => ({
|
|
36
|
+
useCanvasStore: () => i
|
|
37
|
+
}));
|
|
38
|
+
s.mock("@clubmed/usg-chat-ui/organisms/chat/hooks/useChatSyncUserSettings", () => ({
|
|
39
|
+
useChatSyncUserSettings: () => {
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
s.mock("@clubmed/usg-chat-ui/organisms/chat/hooks/useChatKeyboardsShortcuts", () => ({
|
|
43
|
+
useChatKeyboardsShortcuts: () => {
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
s.mock("@clubmed/usg-chat-ui/organisms/chat/hooks/useChatPreferences", () => ({
|
|
47
|
+
useChatPreferences: () => {
|
|
48
|
+
}
|
|
49
|
+
}));
|
|
50
|
+
s.mock("./useConversations", () => ({
|
|
51
|
+
useConversations: () => ({
|
|
52
|
+
chatMessages: n,
|
|
53
|
+
setChatMessages: S,
|
|
54
|
+
currentConversationId: C,
|
|
55
|
+
sidebarRefreshTrigger: 0,
|
|
56
|
+
isLoadingMessage: !1,
|
|
57
|
+
setIsLoadingMessage: k,
|
|
58
|
+
loadConversation: K,
|
|
59
|
+
handleNewConversation: W,
|
|
60
|
+
saveConversation: p
|
|
61
|
+
})
|
|
62
|
+
}));
|
|
63
|
+
const v = (e) => ({ text: e }), f = (e, a = "user-1") => ({
|
|
64
|
+
key: a,
|
|
65
|
+
from: "user",
|
|
66
|
+
versions: [{ id: a, content: e }],
|
|
67
|
+
avatar: "user.png",
|
|
68
|
+
name: "User"
|
|
69
|
+
}), B = (e, a = "assistant-1") => ({
|
|
70
|
+
key: a,
|
|
71
|
+
from: "assistant",
|
|
72
|
+
versions: [
|
|
73
|
+
{
|
|
74
|
+
id: a,
|
|
75
|
+
content: e,
|
|
76
|
+
responseType: "message"
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
avatar: "assistant.png",
|
|
80
|
+
name: "Assistant"
|
|
81
|
+
}), y = (e = {}) => ({
|
|
82
|
+
content: "Assistant response",
|
|
83
|
+
response_type: "message",
|
|
84
|
+
canvas_data: { foo: "bar" },
|
|
85
|
+
followup_questions: ["What next?"],
|
|
86
|
+
sources: [{ href: "https://docs", title: "Docs" }],
|
|
87
|
+
reasoning: {
|
|
88
|
+
content: "Because",
|
|
89
|
+
duration: 1
|
|
90
|
+
},
|
|
91
|
+
...e
|
|
92
|
+
});
|
|
93
|
+
T("useChat", () => {
|
|
94
|
+
A(() => {
|
|
95
|
+
s.clearAllMocks(), n = [], S.mockImplementation(N);
|
|
96
|
+
}), j(() => {
|
|
97
|
+
s.useRealTimers();
|
|
98
|
+
}), h("opens settings without hitting the API when /settings is submitted", async () => {
|
|
99
|
+
const { result: e } = l(() => u());
|
|
100
|
+
await o(async () => {
|
|
101
|
+
await e.current.handleSubmit(v("/settings"));
|
|
102
|
+
}), t(e.current.settingsOpen).toBe(!0), t(r).not.toHaveBeenCalled(), t(S).not.toHaveBeenCalled();
|
|
103
|
+
}), h("pushes an inline help message for /help", async () => {
|
|
104
|
+
var c;
|
|
105
|
+
n = [f("Earlier message")];
|
|
106
|
+
const { result: e } = l(() => u());
|
|
107
|
+
await o(async () => {
|
|
108
|
+
await e.current.handleSubmit(v("/help"));
|
|
109
|
+
}), t(r).not.toHaveBeenCalled();
|
|
110
|
+
const a = n.at(-1);
|
|
111
|
+
t(a == null ? void 0 : a.from).toBe("assistant"), t((c = a == null ? void 0 : a.versions[0]) == null ? void 0 : c.content).toBe(R());
|
|
112
|
+
}), h("clears the conversation when /clear is used", async () => {
|
|
113
|
+
n = [f("To clear")];
|
|
114
|
+
const { result: e } = l(() => u());
|
|
115
|
+
await o(async () => {
|
|
116
|
+
await e.current.handleSubmit(v("/clear"));
|
|
117
|
+
}), t(r).not.toHaveBeenCalled(), t(n).toHaveLength(0), t(H).toHaveBeenCalledWith({
|
|
118
|
+
title: "Cleared",
|
|
119
|
+
description: "Conversation history cleared"
|
|
120
|
+
});
|
|
121
|
+
}), h("saves the user message and assistant response when the API succeeds", async () => {
|
|
122
|
+
var c, d, m, g;
|
|
123
|
+
s.useFakeTimers();
|
|
124
|
+
const e = y({ content: "All done" });
|
|
125
|
+
r.mockResolvedValueOnce(e);
|
|
126
|
+
const { result: a } = l(() => u());
|
|
127
|
+
await o(async () => {
|
|
128
|
+
await a.current.handleSubmit(v("Hello there"));
|
|
129
|
+
}), t(r).toHaveBeenCalledWith({
|
|
130
|
+
message: "Hello there",
|
|
131
|
+
conversationHistory: [],
|
|
132
|
+
projectKey: i.projectKey,
|
|
133
|
+
userId: "db-user",
|
|
134
|
+
conversationId: C,
|
|
135
|
+
releaseNoteSettings: {
|
|
136
|
+
projectKey: (c = i.releaseNoteSettings) == null ? void 0 : c.projectKey,
|
|
137
|
+
status: (d = i.releaseNoteSettings) == null ? void 0 : d.status,
|
|
138
|
+
boardId: (m = i.releaseNoteSettings) == null ? void 0 : m.boardId
|
|
139
|
+
}
|
|
140
|
+
}), t(n).toHaveLength(2), t(n[0].from).toBe("user"), t((g = n[1].versions.at(-1)) == null ? void 0 : g.content).toBe("All done"), t(k).toHaveBeenNthCalledWith(1, !0), t(k).toHaveBeenLastCalledWith(!1), await o(() => {
|
|
141
|
+
s.runAllTimers();
|
|
142
|
+
}), t(p).toHaveBeenCalledTimes(2);
|
|
143
|
+
}), h("opens settings when the API demands authentication", async () => {
|
|
144
|
+
s.useFakeTimers();
|
|
145
|
+
const e = y({
|
|
146
|
+
response_type: "auth_required",
|
|
147
|
+
auth_url: "https://auth",
|
|
148
|
+
content: ""
|
|
149
|
+
});
|
|
150
|
+
r.mockResolvedValueOnce(e);
|
|
151
|
+
const { result: a } = l(() => u());
|
|
152
|
+
await o(async () => {
|
|
153
|
+
await a.current.handleSubmit(v("Needs auth"));
|
|
154
|
+
}), t(a.current.settingsOpen).toBe(!0), t(w).toHaveBeenCalledWith({
|
|
155
|
+
authUrl: "https://auth",
|
|
156
|
+
threadId: C
|
|
157
|
+
}), t(k).toHaveBeenLastCalledWith(!1), await o(() => {
|
|
158
|
+
s.runAllTimers();
|
|
159
|
+
}), t(p).toHaveBeenCalledTimes(1);
|
|
160
|
+
}), h("regenerates an assistant message with the latest version appended", async () => {
|
|
161
|
+
var d, m, g, b;
|
|
162
|
+
s.useFakeTimers(), n = [
|
|
163
|
+
f("Rephrase", "user-1"),
|
|
164
|
+
B("Old", "assistant-1")
|
|
165
|
+
];
|
|
166
|
+
const e = y({ content: "Better", sources: [{ url: "https://docs" }] });
|
|
167
|
+
r.mockResolvedValueOnce(e);
|
|
168
|
+
const { result: a } = l(() => u());
|
|
169
|
+
await o(async () => {
|
|
170
|
+
await a.current.handleRegenerate("assistant-1");
|
|
171
|
+
}), t(r).toHaveBeenCalledWith({
|
|
172
|
+
message: "Rephrase",
|
|
173
|
+
conversationHistory: [
|
|
174
|
+
{
|
|
175
|
+
role: "user",
|
|
176
|
+
content: "Rephrase"
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
projectKey: i.projectKey,
|
|
180
|
+
userId: "db-user",
|
|
181
|
+
conversationId: C,
|
|
182
|
+
releaseNoteSettings: {
|
|
183
|
+
projectKey: (d = i.releaseNoteSettings) == null ? void 0 : d.projectKey,
|
|
184
|
+
status: (m = i.releaseNoteSettings) == null ? void 0 : m.status,
|
|
185
|
+
boardId: (g = i.releaseNoteSettings) == null ? void 0 : g.boardId
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
const c = n[1];
|
|
189
|
+
t(c.versions).toHaveLength(2), t((b = c.versions.at(-1)) == null ? void 0 : b.content).toBe("Better"), await o(() => {
|
|
190
|
+
s.runAllTimers();
|
|
191
|
+
}), t(p).toHaveBeenCalledTimes(1);
|
|
192
|
+
}), h("syncs Jira state when regeneration needs authentication", async () => {
|
|
193
|
+
n = [
|
|
194
|
+
f("Need auth", "user-1"),
|
|
195
|
+
B("Old", "assistant-1")
|
|
196
|
+
];
|
|
197
|
+
const e = y({
|
|
198
|
+
response_type: "auth_required",
|
|
199
|
+
content: "",
|
|
200
|
+
error: "jira_oauth_required",
|
|
201
|
+
auth_url: "https://jira-auth"
|
|
202
|
+
});
|
|
203
|
+
r.mockResolvedValueOnce(e);
|
|
204
|
+
const { result: a } = l(() => u());
|
|
205
|
+
await o(async () => {
|
|
206
|
+
await a.current.handleRegenerate("assistant-1");
|
|
207
|
+
}), t(I).toHaveBeenCalledWith(!1), t(w).toHaveBeenCalledWith({
|
|
208
|
+
authUrl: "https://jira-auth",
|
|
209
|
+
threadId: C
|
|
210
|
+
}), t(n[1].versions).toHaveLength(1), t(p).not.toHaveBeenCalled();
|
|
211
|
+
}), h("prefills the input when a follow-up question is clicked", () => {
|
|
212
|
+
const { result: e } = l(() => u());
|
|
213
|
+
o(() => {
|
|
214
|
+
e.current.handleFollowupClick("Next question?");
|
|
215
|
+
}), t(e.current.localInput).toBe("Next question?");
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=useChat.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChat.test.js","sources":["../../../../lib/organisms/chat/hooks/useChat.test.ts"],"sourcesContent":["import {renderHook, act} from \"@testing-library/react\";\nimport {describe, it, expect, beforeEach, afterEach, vi} from \"vitest\";\nimport {useChat} from \"./useChat\";\nimport type {ChatMessage} from \"../types\";\nimport {getCommandHelp} from \"../../../utils/chat-commands\";\nimport type {PromptInputMessage} from \"@clubmed/usg-chat-ui/molecules/AiElements/PromptInput\";\nimport type {ChatCanvasResponse} from \"@clubmed/usg-chat-ui/core/interfaces/ChatCanvas\";\n\ntype ChatMessagesUpdater = ChatMessage[] | ((prev: ChatMessage[]) => ChatMessage[]);\n\nconst mockToast = vi.fn();\nconst mockChatCanvas = vi.fn();\nconst mockSetJiraConfigured = vi.fn();\nconst mockSetJiraAuthSettings = vi.fn();\nconst mockSetIsLoadingMessage = vi.fn();\nconst mockSaveConversation = vi.fn();\nconst mockLoadConversation = vi.fn();\nconst mockHandleNewConversation = vi.fn();\n\nlet mockChatMessages: ChatMessage[] = [];\nconst mockConversationId = \"conversation-1\";\nconst mockCanvasStoreState = {\n canvasType: \"story\" as const,\n projectKey: \"PROJ-1\",\n releaseNoteSettings: {\n projectKey: \"REL-1\",\n status: \"Done\",\n boardId: 99,\n },\n isFullscreen: false,\n canvasWidth: 420,\n isResizing: false,\n resizeWidth: null as number | null,\n};\n\nconst applyChatMessagesUpdate = (update: ChatMessagesUpdater) => {\n if (typeof update === \"function\") {\n mockChatMessages = update(mockChatMessages);\n } else {\n mockChatMessages = update;\n }\n};\n\nconst mockSetChatMessages = vi.fn(applyChatMessagesUpdate);\n\nvi.mock(\"../../../molecules/Notifications/useToast\", () => ({\n useToast: () => ({toast: mockToast}),\n}));\n\nvi.mock(\"../../../contexts/ChatContext\", () => ({\n useChatApiClient: () => ({chatCanvas: mockChatCanvas}),\n useChatConfig: () => ({user: {id: \"user-1\"}, dbUserId: \"db-user\"}),\n}));\n\nvi.mock(\"@clubmed/usg-chat-ui/contexts/ChatJiraContext\", () => ({\n useChatJira: () => ({\n setJiraConfigured: mockSetJiraConfigured,\n setJiraAuthSettings: mockSetJiraAuthSettings,\n }),\n}));\n\nvi.mock(\"../../../utils/canvas-store\", () => ({\n useCanvasStore: () => mockCanvasStoreState,\n}));\n\nvi.mock(\"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatSyncUserSettings\", () => ({\n useChatSyncUserSettings: () => {},\n}));\n\nvi.mock(\"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatKeyboardsShortcuts\", () => ({\n useChatKeyboardsShortcuts: () => {},\n}));\n\nvi.mock(\"@clubmed/usg-chat-ui/organisms/chat/hooks/useChatPreferences\", () => ({\n useChatPreferences: () => {},\n}));\n\nvi.mock(\"./useConversations\", () => ({\n useConversations: () => ({\n chatMessages: mockChatMessages,\n setChatMessages: mockSetChatMessages,\n currentConversationId: mockConversationId,\n sidebarRefreshTrigger: 0,\n isLoadingMessage: false,\n setIsLoadingMessage: mockSetIsLoadingMessage,\n loadConversation: mockLoadConversation,\n handleNewConversation: mockHandleNewConversation,\n saveConversation: mockSaveConversation,\n }),\n}));\n\nconst createPrompt = (text: string): PromptInputMessage => ({text});\n\nconst createUserMessage = (content: string, key = \"user-1\"): ChatMessage => ({\n key,\n from: \"user\",\n versions: [{id: key, content}],\n avatar: \"user.png\",\n name: \"User\",\n});\n\nconst createAssistantMessage = (content: string, key = \"assistant-1\"): ChatMessage => ({\n key,\n from: \"assistant\",\n versions: [\n {\n id: key,\n content,\n responseType: \"message\",\n },\n ],\n avatar: \"assistant.png\",\n name: \"Assistant\",\n});\n\nconst buildResponse = (overrides: Partial<ChatCanvasResponse> = {}): ChatCanvasResponse => ({\n content: \"Assistant response\",\n response_type: \"message\",\n canvas_data: {foo: \"bar\"},\n followup_questions: [\"What next?\"],\n sources: [{href: \"https://docs\", title: \"Docs\"}],\n reasoning: {\n content: \"Because\",\n duration: 1,\n },\n ...overrides,\n});\n\ndescribe(\"useChat\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n mockChatMessages = [];\n mockSetChatMessages.mockImplementation(applyChatMessagesUpdate);\n });\n\n afterEach(() => {\n vi.useRealTimers();\n });\n\n it(\"opens settings without hitting the API when /settings is submitted\", async () => {\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleSubmit(createPrompt(\"/settings\"));\n });\n\n expect(result.current.settingsOpen).toBe(true);\n expect(mockChatCanvas).not.toHaveBeenCalled();\n expect(mockSetChatMessages).not.toHaveBeenCalled();\n });\n\n it(\"pushes an inline help message for /help\", async () => {\n mockChatMessages = [createUserMessage(\"Earlier message\")];\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleSubmit(createPrompt(\"/help\"));\n });\n\n expect(mockChatCanvas).not.toHaveBeenCalled();\n const lastMessage = mockChatMessages.at(-1);\n expect(lastMessage?.from).toBe(\"assistant\");\n expect(lastMessage?.versions[0]?.content).toBe(getCommandHelp());\n });\n\n it(\"clears the conversation when /clear is used\", async () => {\n mockChatMessages = [createUserMessage(\"To clear\")];\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleSubmit(createPrompt(\"/clear\"));\n });\n\n expect(mockChatCanvas).not.toHaveBeenCalled();\n expect(mockChatMessages).toHaveLength(0);\n expect(mockToast).toHaveBeenCalledWith({\n title: \"Cleared\",\n description: \"Conversation history cleared\",\n });\n });\n\n it(\"saves the user message and assistant response when the API succeeds\", async () => {\n vi.useFakeTimers();\n const response = buildResponse({content: \"All done\"});\n mockChatCanvas.mockResolvedValueOnce(response);\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleSubmit(createPrompt(\"Hello there\"));\n });\n\n expect(mockChatCanvas).toHaveBeenCalledWith({\n message: \"Hello there\",\n conversationHistory: [],\n projectKey: mockCanvasStoreState.projectKey,\n userId: \"db-user\",\n conversationId: mockConversationId,\n releaseNoteSettings: {\n projectKey: mockCanvasStoreState.releaseNoteSettings?.projectKey,\n status: mockCanvasStoreState.releaseNoteSettings?.status,\n boardId: mockCanvasStoreState.releaseNoteSettings?.boardId,\n },\n });\n\n expect(mockChatMessages).toHaveLength(2);\n expect(mockChatMessages[0].from).toBe(\"user\");\n expect(mockChatMessages[1].versions.at(-1)?.content).toBe(\"All done\");\n expect(mockSetIsLoadingMessage).toHaveBeenNthCalledWith(1, true);\n expect(mockSetIsLoadingMessage).toHaveBeenLastCalledWith(false);\n\n await act(() => {\n vi.runAllTimers();\n });\n expect(mockSaveConversation).toHaveBeenCalledTimes(2);\n });\n\n it(\"opens settings when the API demands authentication\", async () => {\n vi.useFakeTimers();\n const authResponse = buildResponse({\n response_type: \"auth_required\",\n auth_url: \"https://auth\",\n content: \"\",\n });\n mockChatCanvas.mockResolvedValueOnce(authResponse);\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleSubmit(createPrompt(\"Needs auth\"));\n });\n\n expect(result.current.settingsOpen).toBe(true);\n expect(mockSetJiraAuthSettings).toHaveBeenCalledWith({\n authUrl: \"https://auth\",\n threadId: mockConversationId,\n });\n expect(mockSetIsLoadingMessage).toHaveBeenLastCalledWith(false);\n\n await act(() => {\n vi.runAllTimers();\n });\n expect(mockSaveConversation).toHaveBeenCalledTimes(1);\n });\n\n it(\"regenerates an assistant message with the latest version appended\", async () => {\n vi.useFakeTimers();\n mockChatMessages = [\n createUserMessage(\"Rephrase\", \"user-1\"),\n createAssistantMessage(\"Old\", \"assistant-1\"),\n ];\n const regenerated = buildResponse({content: \"Better\", sources: [{url: \"https://docs\"}]});\n mockChatCanvas.mockResolvedValueOnce(regenerated);\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleRegenerate(\"assistant-1\");\n });\n\n expect(mockChatCanvas).toHaveBeenCalledWith({\n message: \"Rephrase\",\n conversationHistory: [\n {\n role: \"user\",\n content: \"Rephrase\",\n },\n ],\n projectKey: mockCanvasStoreState.projectKey,\n userId: \"db-user\",\n conversationId: mockConversationId,\n releaseNoteSettings: {\n projectKey: mockCanvasStoreState.releaseNoteSettings?.projectKey,\n status: mockCanvasStoreState.releaseNoteSettings?.status,\n boardId: mockCanvasStoreState.releaseNoteSettings?.boardId,\n },\n });\n\n const assistant = mockChatMessages[1];\n expect(assistant.versions).toHaveLength(2);\n expect(assistant.versions.at(-1)?.content).toBe(\"Better\");\n\n await act(() => {\n vi.runAllTimers();\n });\n expect(mockSaveConversation).toHaveBeenCalledTimes(1);\n });\n\n it(\"syncs Jira state when regeneration needs authentication\", async () => {\n mockChatMessages = [\n createUserMessage(\"Need auth\", \"user-1\"),\n createAssistantMessage(\"Old\", \"assistant-1\"),\n ];\n const authResponse = buildResponse({\n response_type: \"auth_required\",\n content: \"\",\n error: \"jira_oauth_required\",\n auth_url: \"https://jira-auth\",\n });\n mockChatCanvas.mockResolvedValueOnce(authResponse);\n const {result} = renderHook(() => useChat());\n\n await act(async () => {\n await result.current.handleRegenerate(\"assistant-1\");\n });\n\n expect(mockSetJiraConfigured).toHaveBeenCalledWith(false);\n expect(mockSetJiraAuthSettings).toHaveBeenCalledWith({\n authUrl: \"https://jira-auth\",\n threadId: mockConversationId,\n });\n expect(mockChatMessages[1].versions).toHaveLength(1);\n expect(mockSaveConversation).not.toHaveBeenCalled();\n });\n\n it(\"prefills the input when a follow-up question is clicked\", () => {\n const {result} = renderHook(() => useChat());\n\n act(() => {\n result.current.handleFollowupClick(\"Next question?\");\n });\n\n expect(result.current.localInput).toBe(\"Next question?\");\n });\n});\n"],"names":["mockToast","vi","mockChatCanvas","mockSetJiraConfigured","mockSetJiraAuthSettings","mockSetIsLoadingMessage","mockSaveConversation","mockLoadConversation","mockHandleNewConversation","mockChatMessages","mockConversationId","mockCanvasStoreState","applyChatMessagesUpdate","update","mockSetChatMessages","createPrompt","text","createUserMessage","content","key","createAssistantMessage","buildResponse","overrides","describe","beforeEach","afterEach","it","result","renderHook","useChat","act","expect","lastMessage","_a","getCommandHelp","response","_b","_c","_d","authResponse","regenerated","assistant"],"mappings":"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"}
|