@clubmed/usg-chat-ui 1.2.6 → 1.3.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.
Files changed (60) hide show
  1. package/README.md +36 -0
  2. package/assets/style.css +1 -1
  3. package/chunks/react.esm.js +2012 -1997
  4. package/chunks/react.esm.js.map +1 -1
  5. package/chunks/vi.2VT5v0um.js +1 -0
  6. package/config/chatLabels.d.ts +43 -0
  7. package/config/chatLabels.js +2 -0
  8. package/config/chatLabels.js.map +1 -0
  9. package/contexts/ChatLabelsContext.d.ts +13 -0
  10. package/contexts/ChatLabelsContext.js +24 -0
  11. package/contexts/ChatLabelsContext.js.map +1 -0
  12. package/contexts/ChatLabelsContext.test.d.ts +1 -0
  13. package/contexts/ChatLabelsContext.test.js +23 -0
  14. package/contexts/ChatLabelsContext.test.js.map +1 -0
  15. package/molecules/AiElements/Branch.js +45 -44
  16. package/molecules/AiElements/Branch.js.map +1 -1
  17. package/molecules/AiElements/PromptInput.js +60 -58
  18. package/molecules/AiElements/PromptInput.js.map +1 -1
  19. package/molecules/RichText/useCollaboration.test.js +1 -1
  20. package/organisms/canvas/CanvasLayout.d.ts +2 -1
  21. package/organisms/canvas/CanvasLayout.js +1249 -1248
  22. package/organisms/canvas/CanvasLayout.js.map +1 -1
  23. package/organisms/chat/Chat.d.ts +7 -1
  24. package/organisms/chat/Chat.js +67 -67
  25. package/organisms/chat/Chat.js.map +1 -1
  26. package/organisms/chat/ChatHeader.d.ts +4 -4
  27. package/organisms/chat/ChatHeader.js +41 -39
  28. package/organisms/chat/ChatHeader.js.map +1 -1
  29. package/organisms/chat/ChatHeader.test.d.ts +1 -0
  30. package/organisms/chat/ChatHeader.test.js +18 -0
  31. package/organisms/chat/ChatHeader.test.js.map +1 -0
  32. package/organisms/chat/ChatMessageList.d.ts +1 -2
  33. package/organisms/chat/ChatMessageList.js +73 -58
  34. package/organisms/chat/ChatMessageList.js.map +1 -1
  35. package/organisms/chat/ChatMessageList.test.d.ts +1 -0
  36. package/organisms/chat/ChatMessageList.test.js +67 -0
  37. package/organisms/chat/ChatMessageList.test.js.map +1 -0
  38. package/organisms/chat/ChatSettingsButton.d.ts +2 -0
  39. package/organisms/chat/ChatSettingsButton.js +24 -0
  40. package/organisms/chat/ChatSettingsButton.js.map +1 -0
  41. package/organisms/chat/ChatSettingsButton.test.d.ts +1 -0
  42. package/organisms/chat/ChatSettingsButton.test.js +16 -0
  43. package/organisms/chat/ChatSettingsButton.test.js.map +1 -0
  44. package/organisms/chat/ConversationSidebar.js +44 -43
  45. package/organisms/chat/ConversationSidebar.js.map +1 -1
  46. package/organisms/chat/MessageActions.js +104 -103
  47. package/organisms/chat/MessageActions.js.map +1 -1
  48. package/organisms/chat/MessageRenderers.js +1 -1
  49. package/organisms/chat/SidebarToggleButton.js +9 -7
  50. package/organisms/chat/SidebarToggleButton.js.map +1 -1
  51. package/organisms/chat/hooks/useChat.d.ts +1 -1
  52. package/organisms/chat/hooks/useChat.js +83 -83
  53. package/organisms/chat/hooks/useChat.js.map +1 -1
  54. package/package.json +1 -1
  55. package/utils/interpolate.d.ts +5 -0
  56. package/utils/interpolate.js +13 -0
  57. package/utils/interpolate.js.map +1 -0
  58. package/utils/interpolate.test.d.ts +1 -0
  59. package/utils/interpolate.test.js +21 -0
  60. package/utils/interpolate.test.js.map +1 -0
@@ -1,18 +1,18 @@
1
1
  "use client";
2
- import { useState as k, useCallback as N } from "react";
3
- import { parseChatCommand as Q, shouldHandleCommand as V, getCommandHelp as X } from "../../../utils/chat-commands.js";
4
- import { useToast as Y } from "../../../molecules/Notifications/useToast.js";
5
- import { useCanvasStore as Z } from "../../../utils/canvas-store.js";
6
- import { useChatApiClient as ee, useChatConfig as te } from "../../../contexts/ChatContext.js";
7
- import { useConversations as se } from "./useConversations.js";
8
- import { useChatJira as re } from "../../../contexts/ChatJiraContext.js";
9
- import { useChatPreferences as oe } from "./useChatPreferences.js";
2
+ import { useState as j, useCallback as k } from "react";
3
+ import { parseChatCommand as V, shouldHandleCommand as B, getCommandHelp as G } from "../../../utils/chat-commands.js";
4
+ import { useToast as X } from "../../../molecules/Notifications/useToast.js";
5
+ import { useCanvasStore as Y } from "../../../utils/canvas-store.js";
6
+ import { useChatApiClient as Z, useChatConfig as ee } from "../../../contexts/ChatContext.js";
7
+ import { useConversations as te } from "./useConversations.js";
8
+ import { useChatJira as se } from "../../../contexts/ChatJiraContext.js";
9
+ import { useChatPreferences as re } from "./useChatPreferences.js";
10
10
  import { useChatSyncUserSettings as ne } from "./useChatSyncUserSettings.js";
11
- import { useChatKeyboardsShortcuts as ae } from "./useChatKeyboardsShortcuts.js";
12
- const ie = (e) => e == null ? void 0 : e.map((r) => ({
11
+ import { useChatKeyboardsShortcuts as oe } from "./useChatKeyboardsShortcuts.js";
12
+ const ae = (e) => e == null ? void 0 : e.map((r) => ({
13
13
  href: r.href || r.url || "#",
14
14
  title: r.title || "Source"
15
- })), ce = (e) => {
15
+ })), ie = (e) => {
16
16
  if (e)
17
17
  return typeof e == "string" ? { content: e, duration: 0 } : {
18
18
  content: e.content ?? "",
@@ -31,41 +31,41 @@ const ie = (e) => e == null ? void 0 : e.map((r) => ({
31
31
  return {
32
32
  key: r,
33
33
  version: p,
34
- sources: ie(e.sources),
35
- reasoning: ce(e.reasoning)
34
+ sources: ae(e.sources),
35
+ reasoning: ie(e.reasoning)
36
36
  };
37
37
  };
38
- function Ce() {
39
- const { toast: e } = Y(), r = ee(), { setJiraConfigured: p, setJiraAuthSettings: _ } = re(), {
40
- user: C,
41
- dbUserId: b
42
- } = te(), [K, T] = k(!1), [A, D] = k(!1), [R, h] = k(""), {
38
+ function ye() {
39
+ const { toast: e } = X(), r = Z(), { setJiraConfigured: p, setJiraAuthSettings: _ } = se(), {
40
+ user: K,
41
+ dbUserId: C
42
+ } = ee(), [A, T] = j(!1), [D, N] = j(!1), [R, v] = j(""), {
43
43
  chatMessages: u,
44
44
  setChatMessages: m,
45
45
  currentConversationId: d,
46
46
  sidebarRefreshTrigger: U,
47
- isLoadingMessage: $,
48
- setIsLoadingMessage: n,
49
- loadConversation: x,
50
- handleNewConversation: P,
47
+ isLoadingMessage: x,
48
+ setIsLoadingMessage: o,
49
+ loadConversation: P,
50
+ handleNewConversation: $,
51
51
  saveConversation: g
52
- } = se();
53
- ne(), ae(), oe();
52
+ } = te();
53
+ ne(), oe(), re();
54
54
  const {
55
55
  canvasType: E,
56
- projectKey: I,
57
- releaseNoteSettings: o,
56
+ projectKey: b,
57
+ releaseNoteSettings: n,
58
58
  isFullscreen: H,
59
59
  canvasWidth: O,
60
60
  isResizing: z,
61
61
  resizeWidth: F
62
- } = Z(), J = N(
62
+ } = Y(), J = k(
63
63
  async (l) => {
64
64
  var y;
65
65
  if (!((y = l.text) != null && y.trim()))
66
66
  return;
67
- const a = l.text.trim(), i = Q(a);
68
- if (V(i)) {
67
+ const a = l.text.trim(), i = V(a);
68
+ if (B(i)) {
69
69
  if (i.command === "settings") {
70
70
  T(!0);
71
71
  return;
@@ -77,25 +77,25 @@ function Ce() {
77
77
  versions: [
78
78
  {
79
79
  id: `assistant-${Date.now()}`,
80
- content: X(),
80
+ content: G(),
81
81
  responseType: "message"
82
82
  }
83
83
  ],
84
84
  avatar: "https://github.com/openai.png",
85
85
  name: "Assistant"
86
86
  };
87
- m((c) => [...c, t]), h("");
87
+ m((c) => [...c, t]), v("");
88
88
  return;
89
89
  }
90
90
  if (i.command === "clear") {
91
91
  m([]), e({
92
92
  title: "Cleared",
93
93
  description: "Conversation history cleared"
94
- }), h("");
94
+ }), v("");
95
95
  return;
96
96
  }
97
97
  }
98
- const S = {
98
+ const I = {
99
99
  key: `user-${Date.now()}`,
100
100
  from: "user",
101
101
  versions: [
@@ -107,24 +107,24 @@ function Ce() {
107
107
  avatar: "https://github.com/haydenbleasel.png",
108
108
  name: "User"
109
109
  };
110
- m((t) => [...t, S]), h(""), setTimeout(() => {
110
+ m((t) => [...t, I]), v(""), setTimeout(() => {
111
111
  g();
112
- }, 200), n(!0);
112
+ }, 200), o(!0);
113
113
  try {
114
- const t = o ? {
115
- projectKey: o.projectKey,
116
- status: o.status,
117
- boardId: o.boardId
114
+ const t = n ? {
115
+ projectKey: n.projectKey,
116
+ status: n.status,
117
+ boardId: n.boardId
118
118
  } : void 0, c = await r.chatCanvas({
119
119
  message: a,
120
120
  conversationHistory: u.flatMap(
121
- (s) => s.versions.map((G) => ({
121
+ (s) => s.versions.map((Q) => ({
122
122
  role: s.from,
123
- content: G.content
123
+ content: Q.content
124
124
  }))
125
125
  ),
126
- projectKey: I ?? void 0,
127
- userId: b ?? void 0,
126
+ projectKey: b ?? void 0,
127
+ userId: C ?? void 0,
128
128
  conversationId: d ?? void 0,
129
129
  releaseNoteSettings: t
130
130
  });
@@ -132,23 +132,23 @@ function Ce() {
132
132
  c.error === "jira_oauth_required" && p(!1), m((s) => s.slice(0, -1)), _({
133
133
  authUrl: c.auth_url ?? "",
134
134
  threadId: d || void 0
135
- }), n(!1);
135
+ }), o(!1);
136
136
  return;
137
137
  }
138
- const { key: f, version: w, sources: j, reasoning: M } = q(c), v = {
138
+ const { key: f, version: w, sources: S, reasoning: M } = q(c), h = {
139
139
  key: f,
140
140
  from: "assistant",
141
141
  versions: [w],
142
142
  avatar: "https://github.com/openai.png",
143
143
  name: "Assistant",
144
- sources: j,
144
+ sources: S,
145
145
  reasoning: M
146
146
  };
147
- m((s) => [...s, v]), n(!1), setTimeout(() => {
147
+ m((s) => [...s, h]), o(!1), setTimeout(() => {
148
148
  g();
149
149
  }, 100);
150
150
  } catch (t) {
151
- console.error("Chat error:", t), n(!1), e({
151
+ console.error("Chat error:", t), o(!1), e({
152
152
  title: "Error",
153
153
  description: "Failed to get response. Please try again.",
154
154
  variant: "destructive"
@@ -159,21 +159,21 @@ function Ce() {
159
159
  r,
160
160
  u,
161
161
  d,
162
+ C,
162
163
  b,
163
- I,
164
- o,
164
+ n,
165
165
  g,
166
166
  _,
167
167
  p,
168
168
  e
169
169
  ]
170
- ), L = N(
170
+ ), L = k(
171
171
  async (l) => {
172
172
  var y;
173
173
  const a = u.findIndex((t) => t.key === l);
174
174
  if (a === -1) return;
175
- const i = a > 0 ? u[a - 1] : null, S = ((y = i == null ? void 0 : i.versions[0]) == null ? void 0 : y.content) || "";
176
- if (!S) {
175
+ const i = a > 0 ? u[a - 1] : null, I = ((y = i == null ? void 0 : i.versions[0]) == null ? void 0 : y.content) || "";
176
+ if (!I) {
177
177
  e({
178
178
  title: "Erreur",
179
179
  description: "Impossible de régénérer : aucun message précédent trouvé",
@@ -181,22 +181,22 @@ function Ce() {
181
181
  });
182
182
  return;
183
183
  }
184
- n(!0);
184
+ o(!0);
185
185
  try {
186
- const t = o ? {
187
- projectKey: o.projectKey,
188
- status: o.status,
189
- boardId: o.boardId
186
+ const t = n ? {
187
+ projectKey: n.projectKey,
188
+ status: n.status,
189
+ boardId: n.boardId
190
190
  } : void 0, c = u.slice(0, a).flatMap(
191
- (v) => v.versions.map((s) => ({
192
- role: v.from,
191
+ (h) => h.versions.map((s) => ({
192
+ role: h.from,
193
193
  content: s.content
194
194
  }))
195
195
  ), f = await r.chatCanvas({
196
- message: S,
196
+ message: I,
197
197
  conversationHistory: c,
198
- projectKey: I ?? void 0,
199
- userId: b ?? void 0,
198
+ projectKey: b ?? void 0,
199
+ userId: C ?? void 0,
200
200
  conversationId: d ?? void 0,
201
201
  releaseNoteSettings: t
202
202
  });
@@ -204,22 +204,22 @@ function Ce() {
204
204
  f.error === "jira_oauth_required" && p(!1), _({
205
205
  authUrl: f.auth_url ?? "",
206
206
  threadId: d || void 0
207
- }), n(!1);
207
+ }), o(!1);
208
208
  return;
209
209
  }
210
- const { version: w, sources: j, reasoning: M } = q(f);
210
+ const { version: w, sources: S, reasoning: M } = q(f);
211
211
  m(
212
- (v) => v.map((s) => s.key === l ? {
212
+ (h) => h.map((s) => s.key === l ? {
213
213
  ...s,
214
214
  versions: [...s.versions, w],
215
- sources: j,
215
+ sources: S,
216
216
  reasoning: M
217
217
  } : s)
218
- ), n(!1), setTimeout(() => {
218
+ ), o(!1), setTimeout(() => {
219
219
  g();
220
220
  }, 100);
221
221
  } catch (t) {
222
- console.error("Regenerate error:", t), n(!1), e({
222
+ console.error("Regenerate error:", t), o(!1), e({
223
223
  title: "Erreur",
224
224
  description: "Impossible de régénérer la réponse. Veuillez réessayer.",
225
225
  variant: "destructive"
@@ -230,27 +230,28 @@ function Ce() {
230
230
  r,
231
231
  u,
232
232
  d,
233
+ C,
233
234
  b,
234
- I,
235
- o,
235
+ n,
236
236
  g,
237
237
  p,
238
238
  e
239
239
  ]
240
- ), W = N((l) => {
241
- h(l);
242
- }, []), B = C != null && C.userName ? `Bonjour ${C.userName.split(" ")[0]} 👋` : void 0;
240
+ ), W = k((l) => {
241
+ v(l);
242
+ }, []);
243
243
  return {
244
+ user: K,
244
245
  chatMessages: u,
245
- settingsOpen: K,
246
+ settingsOpen: A,
246
247
  setSettingsOpen: T,
247
- sidebarOpen: A,
248
- setSidebarOpen: D,
248
+ sidebarOpen: D,
249
+ setSidebarOpen: N,
249
250
  sidebarRefreshTrigger: U,
250
251
  currentConversationId: d,
251
- loadConversation: x,
252
- handleNewConversation: P,
253
- isLoadingMessage: $,
252
+ loadConversation: P,
253
+ handleNewConversation: $,
254
+ isLoadingMessage: x,
254
255
  canvasType: E,
255
256
  isFullscreen: H,
256
257
  canvasWidth: O,
@@ -260,11 +261,10 @@ function Ce() {
260
261
  handleSubmit: J,
261
262
  handleRegenerate: L,
262
263
  localInput: R,
263
- setLocalInput: h,
264
- emptyStateGreeting: B
264
+ setLocalInput: v
265
265
  };
266
266
  }
267
267
  export {
268
- Ce as useChat
268
+ ye as useChat
269
269
  };
270
270
  //# sourceMappingURL=useChat.js.map
@@ -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\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 const emptyStateGreeting = user?.userName\n ? `Bonjour ${user.userName.split(\" \")[0]} 👋`\n : undefined;\n\n return {\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 emptyStateGreeting\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","emptyStateGreeting"],"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 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubmed/usg-chat-ui",
3
- "version": "1.2.6",
3
+ "version": "1.3.0",
4
4
  "description": "Reusable ClubMed USG chat experience",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -0,0 +1,5 @@
1
+ type InterpolateValues = Record<string, string | number | null | undefined>;
2
+ export declare const interpolate: (template: string, values?: InterpolateValues, { preserveWhitespace }?: {
3
+ preserveWhitespace?: boolean;
4
+ }) => string | undefined;
5
+ export {};
@@ -0,0 +1,13 @@
1
+ const c = /{{\s*([\w.-]+)\s*}}/g, i = (t) => t.replace(/\s{2,}/g, " ").trim(), a = (t, o = {}, { preserveWhitespace: n = !1 } = {}) => {
2
+ if (!t)
3
+ return;
4
+ const r = t.replace(c, (l, s) => {
5
+ const e = o[s];
6
+ return e == null ? "" : String(e);
7
+ });
8
+ return (n ? r.trim() : i(r)) || void 0;
9
+ };
10
+ export {
11
+ a as interpolate
12
+ };
13
+ //# sourceMappingURL=interpolate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interpolate.js","sources":["../../lib/utils/interpolate.ts"],"sourcesContent":["const PLACEHOLDER_PATTERN = /{{\\s*([\\w.-]+)\\s*}}/g;\n\ntype InterpolateValues = Record<string, string | number | null | undefined>;\n\nconst normalizeWhitespace = (value: string) => value.replace(/\\s{2,}/g, \" \").trim();\n\nexport const interpolate = (\n template: string,\n values: InterpolateValues = {},\n {preserveWhitespace = false}: {preserveWhitespace?: boolean} = {}\n) => {\n if (!template) {\n return undefined;\n }\n\n const replaced = template.replace(PLACEHOLDER_PATTERN, (_, key: string) => {\n const value = values[key];\n return value === null || value === undefined ? \"\" : String(value);\n });\n\n const output = preserveWhitespace ? replaced.trim() : normalizeWhitespace(replaced);\n\n return output || undefined;\n};\n"],"names":["PLACEHOLDER_PATTERN","normalizeWhitespace","value","interpolate","template","values","preserveWhitespace","replaced","_","key"],"mappings":"AAAA,MAAMA,IAAsB,wBAItBC,IAAsB,CAACC,MAAkBA,EAAM,QAAQ,WAAW,GAAG,EAAE,KAAA,GAEhEC,IAAc,CACzBC,GACAC,IAA4B,CAAA,GAC5B,EAAC,oBAAAC,IAAqB,GAAA,IAAyC,OAC5D;AACH,MAAI,CAACF;AACH;AAGF,QAAMG,IAAWH,EAAS,QAAQJ,GAAqB,CAACQ,GAAGC,MAAgB;AACzE,UAAMP,IAAQG,EAAOI,CAAG;AACxB,WAAOP,KAAU,OAA8B,KAAK,OAAOA,CAAK;AAAA,EAClE,CAAC;AAID,UAFeI,IAAqBC,EAAS,KAAA,IAASN,EAAoBM,CAAQ,MAEjE;AACnB;"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { interpolate as e } from "./interpolate.js";
2
+ import { d as o, i as s, g as t } from "../chunks/vi.2VT5v0um.js";
3
+ o("interpolate", () => {
4
+ s("replaces tokens and collapses whitespace by default", () => {
5
+ const n = e(" Hello {{name}} {{emoji}} ", {
6
+ name: "Ava",
7
+ emoji: "👋"
8
+ });
9
+ t(n).toBe("Hello Ava 👋");
10
+ }), s("returns undefined when template is falsy or resolves to empty content", () => {
11
+ t(e("", { name: "Ava" })).toBeUndefined(), t(e("{{missing}}", { missing: "" })).toBeUndefined();
12
+ }), s("preserves intentional spacing when requested", () => {
13
+ const n = e(
14
+ "Hello {{name}} ",
15
+ { name: "Ben" },
16
+ { preserveWhitespace: !0 }
17
+ );
18
+ t(n).toBe("Hello Ben");
19
+ });
20
+ });
21
+ //# sourceMappingURL=interpolate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interpolate.test.js","sources":["../../lib/utils/interpolate.test.ts"],"sourcesContent":["import {describe, expect, it} from \"vitest\";\nimport {interpolate} from \"./interpolate\";\n\ndescribe(\"interpolate\", () => {\n it(\"replaces tokens and collapses whitespace by default\", () => {\n const result = interpolate(\" Hello {{name}} {{emoji}} \", {\n name: \"Ava\",\n emoji: \"👋\",\n });\n expect(result).toBe(\"Hello Ava 👋\");\n });\n\n it(\"returns undefined when template is falsy or resolves to empty content\", () => {\n expect(interpolate(\"\", {name: \"Ava\"})).toBeUndefined();\n expect(interpolate(\"{{missing}}\", {missing: \"\"})).toBeUndefined();\n });\n\n it(\"preserves intentional spacing when requested\", () => {\n const result = interpolate(\n \"Hello {{name}} \",\n {name: \"Ben\"},\n {preserveWhitespace: true}\n );\n expect(result).toBe(\"Hello Ben\");\n });\n});\n"],"names":["describe","it","result","interpolate","expect"],"mappings":";;AAGAA,EAAS,eAAe,MAAM;AAC5B,EAAAC,EAAG,uDAAuD,MAAM;AAC9D,UAAMC,IAASC,EAAY,+BAA+B;AAAA,MACxD,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AACDC,IAAAA,EAAOF,CAAM,EAAE,KAAK,cAAc;AAAA,EACpC,CAAC,GAEDD,EAAG,yEAAyE,MAAM;AAChFG,IAAAA,EAAOD,EAAY,IAAI,EAAC,MAAM,OAAM,CAAC,EAAE,cAAA,GACvCC,EAAOD,EAAY,eAAe,EAAC,SAAS,IAAG,CAAC,EAAE,cAAA;AAAA,EACpD,CAAC,GAEDF,EAAG,gDAAgD,MAAM;AACvD,UAAMC,IAASC;AAAA,MACb;AAAA,MACA,EAAC,MAAM,MAAA;AAAA,MACP,EAAC,oBAAoB,GAAA;AAAA,IAAI;AAE3BC,IAAAA,EAAOF,CAAM,EAAE,KAAK,aAAa;AAAA,EACnC,CAAC;AACH,CAAC;"}