@liveblocks/react-ui 2.25.0-aiprivatebeta7 → 2.25.0-aiprivatebeta8

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 (70) hide show
  1. package/dist/_private/index.cjs +10 -4
  2. package/dist/_private/index.cjs.map +1 -1
  3. package/dist/_private/index.d.cts +76 -10
  4. package/dist/_private/index.d.ts +76 -10
  5. package/dist/_private/index.js +4 -2
  6. package/dist/_private/index.js.map +1 -1
  7. package/dist/components/AiChat.cjs +24 -27
  8. package/dist/components/AiChat.cjs.map +1 -1
  9. package/dist/components/AiChat.js +24 -27
  10. package/dist/components/AiChat.js.map +1 -1
  11. package/dist/components/AiToolDebugger.cjs +74 -0
  12. package/dist/components/AiToolDebugger.cjs.map +1 -0
  13. package/dist/components/AiToolDebugger.js +72 -0
  14. package/dist/components/AiToolDebugger.js.map +1 -0
  15. package/dist/components/Thread.cjs +3 -3
  16. package/dist/components/Thread.cjs.map +1 -1
  17. package/dist/components/Thread.js +3 -3
  18. package/dist/components/Thread.js.map +1 -1
  19. package/dist/components/internal/AiChatAssistantMessage.cjs +127 -147
  20. package/dist/components/internal/AiChatAssistantMessage.cjs.map +1 -1
  21. package/dist/components/internal/AiChatAssistantMessage.js +129 -149
  22. package/dist/components/internal/AiChatAssistantMessage.js.map +1 -1
  23. package/dist/components/internal/AiChatComposer.cjs +28 -16
  24. package/dist/components/internal/AiChatComposer.cjs.map +1 -1
  25. package/dist/components/internal/AiChatComposer.js +28 -16
  26. package/dist/components/internal/AiChatComposer.js.map +1 -1
  27. package/dist/icon.cjs +2 -0
  28. package/dist/icon.cjs.map +1 -1
  29. package/dist/icon.js +1 -0
  30. package/dist/icon.js.map +1 -1
  31. package/dist/icons/{Resolve.cjs → CheckCircle.cjs} +3 -3
  32. package/dist/icons/CheckCircle.cjs.map +1 -0
  33. package/dist/icons/{Resolve.js → CheckCircle.js} +3 -3
  34. package/dist/icons/CheckCircle.js.map +1 -0
  35. package/dist/icons/{Resolved.cjs → CheckCircleFill.cjs} +3 -3
  36. package/dist/icons/CheckCircleFill.cjs.map +1 -0
  37. package/dist/icons/{Resolved.js → CheckCircleFill.js} +3 -3
  38. package/dist/icons/CheckCircleFill.js.map +1 -0
  39. package/dist/icons/index.cjs +4 -4
  40. package/dist/icons/index.js +2 -2
  41. package/dist/index.cjs +2 -0
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.d.cts +27 -14
  44. package/dist/index.d.ts +27 -14
  45. package/dist/index.js +1 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/overrides.cjs +0 -4
  48. package/dist/overrides.cjs.map +1 -1
  49. package/dist/overrides.js +0 -4
  50. package/dist/overrides.js.map +1 -1
  51. package/dist/primitives/AiChatComposer/index.cjs +1 -2
  52. package/dist/primitives/AiChatComposer/index.cjs.map +1 -1
  53. package/dist/primitives/AiChatComposer/index.js +1 -2
  54. package/dist/primitives/AiChatComposer/index.js.map +1 -1
  55. package/dist/primitives/index.d.cts +0 -4
  56. package/dist/primitives/index.d.ts +0 -4
  57. package/dist/primitives/internal/Markdown.cjs +56 -25
  58. package/dist/primitives/internal/Markdown.cjs.map +1 -1
  59. package/dist/primitives/internal/Markdown.js +56 -25
  60. package/dist/primitives/internal/Markdown.js.map +1 -1
  61. package/dist/version.cjs +1 -1
  62. package/dist/version.js +1 -1
  63. package/package.json +5 -5
  64. package/src/styles/index.css +105 -61
  65. package/styles.css +1 -1
  66. package/styles.css.map +1 -1
  67. package/dist/icons/Resolve.cjs.map +0 -1
  68. package/dist/icons/Resolve.js.map +0 -1
  69. package/dist/icons/Resolved.cjs.map +0 -1
  70. package/dist/icons/Resolved.js.map +0 -1
@@ -1,67 +1,32 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { kInternal } from '@liveblocks/core';
3
3
  import { useClient } from '@liveblocks/react';
4
4
  import { useSignal } from '@liveblocks/react/_private';
5
5
  import { Lexer } from 'marked';
6
- import { memo, forwardRef, useState, useEffect, useMemo } from 'react';
7
- import { Button } from './Button.js';
8
- import { Tooltip } from './Tooltip.js';
6
+ import { memo, forwardRef, useMemo, useState, useRef, useEffect, useCallback } from 'react';
7
+ import '../../_private/index.js';
8
+ import { useComponents } from '../../components.js';
9
9
  import { CheckIcon } from '../../icons/Check.js';
10
- import { ChevronDownIcon } from '../../icons/ChevronDown.js';
11
10
  import { ChevronRightIcon } from '../../icons/ChevronRight.js';
12
11
  import { CopyIcon } from '../../icons/Copy.js';
13
- import { RetryIcon } from '../../icons/Retry.js';
14
12
  import { WarningIcon } from '../../icons/Warning.js';
15
13
  import { useOverrides } from '../../overrides.js';
16
14
  import { Root, Trigger, Content } from '../../primitives/internal/Collapsible/index.js';
17
15
  import { BlockTokenComp } from '../../primitives/internal/Markdown.js';
18
16
  import { classNames } from '../../utils/class-names.js';
19
- import { TooltipProvider } from '@radix-ui/react-tooltip';
17
+ import { Button } from './Button.js';
20
18
 
21
19
  const AiChatAssistantMessage = memo(
22
20
  forwardRef(
23
- ({
24
- message,
25
- showActions = false,
26
- showRegenerate = false,
27
- copilotId,
28
- className,
29
- overrides,
30
- ...props
31
- }, forwardedRef) => {
21
+ ({ message, className, overrides, components, ...props }, forwardedRef) => {
32
22
  const $ = useOverrides(overrides);
33
23
  let children = null;
34
- function MessageActions({ text }) {
35
- if (!showActions)
36
- return null;
37
- return /* @__PURE__ */ jsxs("div", {
38
- className: "lb-ai-chat-message-actions",
39
- children: [
40
- /* @__PURE__ */ jsx(Tooltip, {
41
- content: $.AI_CHAT_MESSAGE_COPY,
42
- children: /* @__PURE__ */ jsx(CopyTextButton, {
43
- text,
44
- label: $.AI_CHAT_MESSAGE_COPY
45
- })
46
- }),
47
- showRegenerate && /* @__PURE__ */ jsx(Tooltip, {
48
- content: $.AI_CHAT_MESSAGE_TRY_AGAIN,
49
- children: /* @__PURE__ */ jsx(RegenerateMessageButton, {
50
- chatId: message.chatId,
51
- messageId: message.id,
52
- copilotId,
53
- label: $.AI_CHAT_MESSAGE_TRY_AGAIN
54
- })
55
- })
56
- ]
57
- });
58
- }
59
24
  if (message.deletedAt !== void 0) {
60
25
  children = /* @__PURE__ */ jsx("div", {
61
26
  className: "lb-ai-chat-message-deleted",
62
27
  children: $.AI_CHAT_MESSAGE_DELETED
63
28
  });
64
- } else if (message.status === "pending") {
29
+ } else if (message.status === "generating" || message.status === "awaiting-tool") {
65
30
  if (message.contentSoFar.length === 0) {
66
31
  children = /* @__PURE__ */ jsx("div", {
67
32
  className: "lb-ai-chat-message-thinking lb-ai-chat-pending",
@@ -70,52 +35,34 @@ const AiChatAssistantMessage = memo(
70
35
  } else {
71
36
  children = /* @__PURE__ */ jsx(AssistantMessageContent, {
72
37
  content: message.contentSoFar,
73
- chatId: message.chatId
38
+ chatId: message.chatId,
39
+ messageId: message.id,
40
+ components
74
41
  });
75
42
  }
76
43
  } else if (message.status === "completed") {
77
- const text = message.content.reduce((acc, part) => {
78
- if (part.type === "text") {
79
- return acc + part.text;
80
- }
81
- return acc;
82
- }, "");
83
- children = /* @__PURE__ */ jsxs(Fragment, {
84
- children: [
85
- /* @__PURE__ */ jsx(AssistantMessageContent, {
86
- content: message.content,
87
- chatId: message.chatId
88
- }),
89
- /* @__PURE__ */ jsx(MessageActions, {
90
- text
91
- })
92
- ]
44
+ children = /* @__PURE__ */ jsx(AssistantMessageContent, {
45
+ content: message.content,
46
+ chatId: message.chatId,
47
+ messageId: message.id,
48
+ components
93
49
  });
94
50
  } else if (message.status === "failed") {
95
- const text = message.contentSoFar.reduce((acc, part) => {
96
- if (part.type === "text") {
97
- return acc + part.text;
98
- }
99
- return acc;
100
- }, "");
101
51
  if (message.errorReason === "Aborted by user") {
102
- children = /* @__PURE__ */ jsxs(Fragment, {
103
- children: [
104
- /* @__PURE__ */ jsx(AssistantMessageContent, {
105
- content: message.contentSoFar,
106
- chatId: message.chatId
107
- }),
108
- /* @__PURE__ */ jsx(MessageActions, {
109
- text
110
- })
111
- ]
52
+ children = /* @__PURE__ */ jsx(AssistantMessageContent, {
53
+ content: message.contentSoFar,
54
+ chatId: message.chatId,
55
+ messageId: message.id,
56
+ components
112
57
  });
113
58
  } else {
114
59
  children = /* @__PURE__ */ jsxs(Fragment, {
115
60
  children: [
116
61
  /* @__PURE__ */ jsx(AssistantMessageContent, {
117
62
  content: message.contentSoFar,
118
- chatId: message.chatId
63
+ chatId: message.chatId,
64
+ messageId: message.id,
65
+ components
119
66
  }),
120
67
  /* @__PURE__ */ jsxs("div", {
121
68
  className: "lb-ai-chat-message-error",
@@ -126,71 +73,28 @@ const AiChatAssistantMessage = memo(
126
73
  }),
127
74
  message.errorReason
128
75
  ]
129
- }),
130
- /* @__PURE__ */ jsx(MessageActions, {
131
- text
132
76
  })
133
77
  ]
134
78
  });
135
79
  }
136
80
  }
137
- return /* @__PURE__ */ jsx(TooltipProvider, {
138
- children: /* @__PURE__ */ jsx("div", {
139
- className: classNames(
140
- "lb-ai-chat-message lb-ai-chat-assistant-message",
141
- showActions === "hover" && "lb-ai-chat-message:show-actions-hover",
142
- className
143
- ),
144
- ...props,
145
- ref: forwardedRef,
146
- children
147
- })
81
+ return /* @__PURE__ */ jsx("div", {
82
+ className: classNames(
83
+ "lb-ai-chat-message lb-ai-chat-assistant-message",
84
+ className
85
+ ),
86
+ ...props,
87
+ ref: forwardedRef,
88
+ children
148
89
  });
149
90
  }
150
91
  )
151
92
  );
152
- function CopyTextButton({ text, label }) {
153
- const [isCopied, setIsCopied] = useState(false);
154
- useEffect(() => {
155
- const timeoutId = setTimeout(() => {
156
- setIsCopied(false);
157
- }, 2e3);
158
- return () => {
159
- clearTimeout(timeoutId);
160
- };
161
- }, [isCopied]);
162
- return /* @__PURE__ */ jsx(Button, {
163
- onClick: function() {
164
- navigator.clipboard.writeText(text);
165
- setIsCopied(true);
166
- },
167
- className: "lb-ai-chat-message-action",
168
- "aria-label": label,
169
- icon: isCopied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
170
- });
171
- }
172
- function RegenerateMessageButton({
173
- chatId,
174
- messageId,
175
- copilotId,
176
- label
177
- }) {
178
- const client = useClient();
179
- return /* @__PURE__ */ jsx(Button, {
180
- onClick: function() {
181
- client[kInternal].ai.regenerateMessage(chatId, messageId, {
182
- copilotId,
183
- stream: true
184
- });
185
- },
186
- className: "lb-ai-chat-message-action",
187
- "aria-label": label,
188
- icon: /* @__PURE__ */ jsx(RetryIcon, {})
189
- });
190
- }
191
93
  function AssistantMessageContent({
192
94
  content,
193
- chatId
95
+ chatId,
96
+ messageId,
97
+ components
194
98
  }) {
195
99
  const isReasoning = content.some((part) => part.type === "reasoning") && content.every((part) => part.type === "reasoning");
196
100
  return /* @__PURE__ */ jsx("div", {
@@ -200,20 +104,22 @@ function AssistantMessageContent({
200
104
  case "text": {
201
105
  return /* @__PURE__ */ jsx(TextPart, {
202
106
  text: part.text,
107
+ components,
203
108
  className: "lb-ai-chat-message-text"
204
109
  }, index);
205
110
  }
206
- case "tool-call": {
207
- return /* @__PURE__ */ jsx(ToolCallPart, {
111
+ case "tool-invocation": {
112
+ return /* @__PURE__ */ jsx(ToolInvocationPart, {
208
113
  chatId,
209
- name: part.toolName,
210
- args: part.args
114
+ messageId,
115
+ part
211
116
  }, index);
212
117
  }
213
118
  case "reasoning": {
214
119
  return /* @__PURE__ */ jsx(ReasoningPart, {
215
120
  text: part.text,
216
- isPending: isReasoning
121
+ isPending: isReasoning,
122
+ components
217
123
  }, index);
218
124
  }
219
125
  default: {
@@ -224,7 +130,7 @@ function AssistantMessageContent({
224
130
  });
225
131
  }
226
132
  const TextPart = forwardRef(
227
- ({ text, ...props }, forwardedRef) => {
133
+ ({ text, components, ...props }, forwardedRef) => {
228
134
  const tokens = useMemo(() => {
229
135
  return new Lexer().lex(text);
230
136
  }, [text]);
@@ -233,16 +139,72 @@ const TextPart = forwardRef(
233
139
  ...props,
234
140
  children: tokens.map((token, index) => {
235
141
  return /* @__PURE__ */ jsx(MemoizedBlockTokenComp, {
236
- token
142
+ token,
143
+ components
237
144
  }, index);
238
145
  })
239
146
  });
240
147
  }
241
148
  );
149
+ function CodeBlock({
150
+ language,
151
+ code
152
+ }) {
153
+ const [isCopied, setCopied] = useState(false);
154
+ const timeoutRef = useRef(null);
155
+ useEffect(() => {
156
+ if (isCopied) {
157
+ timeoutRef.current = setTimeout(() => {
158
+ setCopied(false);
159
+ }, 1e3);
160
+ }
161
+ return () => {
162
+ if (timeoutRef.current) {
163
+ clearTimeout(timeoutRef.current);
164
+ }
165
+ };
166
+ }, [isCopied]);
167
+ return /* @__PURE__ */ jsxs("div", {
168
+ className: "lb-code-block",
169
+ children: [
170
+ /* @__PURE__ */ jsxs("div", {
171
+ className: "lb-code-block-header",
172
+ children: [
173
+ /* @__PURE__ */ jsx("span", {
174
+ className: "lb-code-block-title",
175
+ children: language ?? "Plain text"
176
+ }),
177
+ /* @__PURE__ */ jsx("div", {
178
+ className: "lb-code-block-header-actions",
179
+ children: /* @__PURE__ */ jsx(Button, {
180
+ className: "lb-code-block-header-action",
181
+ icon: isCopied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}),
182
+ onClick: () => {
183
+ setCopied(true);
184
+ navigator.clipboard.writeText(code);
185
+ }
186
+ })
187
+ })
188
+ ]
189
+ }),
190
+ /* @__PURE__ */ jsx("pre", {
191
+ className: "lb-code-block-content",
192
+ children: /* @__PURE__ */ jsx("code", {
193
+ children: code
194
+ })
195
+ })
196
+ ]
197
+ });
198
+ }
242
199
  const MemoizedBlockTokenComp = memo(
243
- function BlockTokenComp$1({ token }) {
200
+ function BlockTokenComp$1({
201
+ token,
202
+ components
203
+ }) {
204
+ const { Anchor } = useComponents(components);
244
205
  return /* @__PURE__ */ jsx(BlockTokenComp, {
245
- token
206
+ token,
207
+ components: { CodeBlock, Anchor }
246
208
  });
247
209
  },
248
210
  (prevProps, nextProps) => {
@@ -257,27 +219,42 @@ const MemoizedBlockTokenComp = memo(
257
219
  return prevToken.raw === nextToken.raw;
258
220
  }
259
221
  );
260
- function ToolCallPart({
222
+ function noop() {
223
+ }
224
+ function ToolInvocationPart({
261
225
  chatId,
262
- name,
263
- args
226
+ messageId,
227
+ part
264
228
  }) {
265
229
  const client = useClient();
266
- const tool = useSignal(
267
- client[kInternal].ai.signals.getToolDefinition\u03A3(chatId, name)
230
+ const ai = client[kInternal].ai;
231
+ const tool = useSignal(ai.signals.getToolDefinition\u03A3(chatId, part.toolName));
232
+ const respond = useCallback(
233
+ (result) => {
234
+ ai.setToolResult(
235
+ chatId,
236
+ messageId,
237
+ part.toolCallId,
238
+ result
239
+ );
240
+ },
241
+ [ai, chatId, messageId, part.toolCallId]
268
242
  );
269
243
  if (tool === void 0 || tool.render === void 0)
270
244
  return null;
245
+ const { type: _, ...rest } = part;
271
246
  return /* @__PURE__ */ jsx("div", {
272
247
  className: "lb-ai-chat-message-tool",
273
248
  children: /* @__PURE__ */ jsx(tool.render, {
274
- args
249
+ ...rest,
250
+ respond: part.status === "executing" ? respond : noop
275
251
  })
276
252
  });
277
253
  }
278
254
  function ReasoningPart({
279
255
  text,
280
- isPending
256
+ isPending,
257
+ components
281
258
  }) {
282
259
  const [isOpen, setIsOpen] = useState(false);
283
260
  return /* @__PURE__ */ jsxs(Root, {
@@ -293,14 +270,17 @@ function ReasoningPart({
293
270
  children: [
294
271
  "Reasoning",
295
272
  /* @__PURE__ */ jsx("span", {
296
- className: "lb-icon-container",
297
- children: isOpen ? /* @__PURE__ */ jsx(ChevronDownIcon, {}) : /* @__PURE__ */ jsx(ChevronRightIcon, {})
273
+ className: "lb-ai-chat-message-collapsible-chevron lb-icon-container",
274
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
298
275
  })
299
276
  ]
300
277
  }),
301
278
  /* @__PURE__ */ jsx(Content, {
302
279
  className: "lb-ai-chat-message-collapsible-content",
303
- children: text
280
+ children: /* @__PURE__ */ jsx(TextPart, {
281
+ text,
282
+ components
283
+ })
304
284
  })
305
285
  ]
306
286
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AiChatAssistantMessage.js","sources":["../../../src/components/internal/AiChatAssistantMessage.tsx"],"sourcesContent":["import {\n type AiAssistantContentPart,\n type CopilotId,\n kInternal,\n type MessageId,\n type UiAssistantMessage,\n} from \"@liveblocks/core\";\nimport { useClient } from \"@liveblocks/react\";\nimport { useSignal } from \"@liveblocks/react/_private\";\nimport { Lexer } from \"marked\";\nimport {\n type ComponentProps,\n forwardRef,\n memo,\n type ReactNode,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\n\nimport { Button } from \"../../components/internal/Button\";\nimport { Tooltip, TooltipProvider } from \"../../components/internal/Tooltip\";\nimport { CheckIcon } from \"../../icons/Check\";\nimport { ChevronDownIcon } from \"../../icons/ChevronDown\";\nimport { ChevronRightIcon } from \"../../icons/ChevronRight\";\nimport { CopyIcon } from \"../../icons/Copy\";\nimport { RetryIcon } from \"../../icons/Retry\";\nimport { WarningIcon } from \"../../icons/Warning\";\nimport {\n type AiChatMessageOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../../overrides\";\nimport * as CollapsiblePrimitive from \"../../primitives/internal/Collapsible\";\nimport {\n type BlockToken,\n BlockTokenComp as BlockTokenCompPrimitive,\n} from \"../../primitives/internal/Markdown\";\nimport { classNames } from \"../../utils/class-names\";\n\n/* -------------------------------------------------------------------------------------------------\n * AiChatAssistantMessage\n * -----------------------------------------------------------------------------------------------*/\nexport interface AiChatAssistantMessageProps extends ComponentProps<\"div\"> {\n /**\n * The message to display.\n */\n message: UiAssistantMessage;\n /**\n * Whether to show or hide message actions.\n * @internal\n */\n showActions?: boolean | \"hover\";\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & AiChatMessageOverrides>;\n /**\n * @internal\n * Whether to show or hide the regenerate button.\n */\n showRegenerate?: boolean;\n /**\n * @internal\n * The id of the copilot to use to regenerate the message. Only used if `showRegenerate` is true.\n */\n copilotId?: CopilotId;\n}\n\nexport const AiChatAssistantMessage = memo(\n forwardRef<HTMLDivElement, AiChatAssistantMessageProps>(\n (\n {\n message,\n showActions = false,\n showRegenerate = false,\n copilotId,\n className,\n overrides,\n ...props\n },\n forwardedRef\n ) => {\n const $ = useOverrides(overrides);\n\n let children: ReactNode = null;\n\n function MessageActions({ text }: { text: string }) {\n if (!showActions) return null;\n\n return (\n <div className=\"lb-ai-chat-message-actions\">\n <Tooltip content={$.AI_CHAT_MESSAGE_COPY}>\n <CopyTextButton text={text} label={$.AI_CHAT_MESSAGE_COPY} />\n </Tooltip>\n\n {showRegenerate && (\n <Tooltip content={$.AI_CHAT_MESSAGE_TRY_AGAIN}>\n <RegenerateMessageButton\n chatId={message.chatId}\n messageId={message.id}\n copilotId={copilotId}\n label={$.AI_CHAT_MESSAGE_TRY_AGAIN}\n />\n </Tooltip>\n )}\n </div>\n );\n }\n\n if (message.deletedAt !== undefined) {\n children = (\n <div className=\"lb-ai-chat-message-deleted\">\n {$.AI_CHAT_MESSAGE_DELETED}\n </div>\n );\n } else if (message.status === \"pending\") {\n if (message.contentSoFar.length === 0) {\n children = (\n <div className=\"lb-ai-chat-message-thinking lb-ai-chat-pending\">\n {$.AI_CHAT_MESSAGE_THINKING}\n </div>\n );\n } else {\n children = (\n <AssistantMessageContent\n content={message.contentSoFar}\n chatId={message.chatId}\n />\n );\n }\n } else if (message.status === \"completed\") {\n const text: string = message.content.reduce((acc, part) => {\n if (part.type === \"text\") {\n return acc + part.text;\n }\n return acc;\n }, \"\");\n\n children = (\n <>\n <AssistantMessageContent\n content={message.content}\n chatId={message.chatId}\n />\n\n <MessageActions text={text} />\n </>\n );\n } else if (message.status === \"failed\") {\n const text: string = message.contentSoFar.reduce((acc, part) => {\n if (part.type === \"text\") {\n return acc + part.text;\n }\n return acc;\n }, \"\");\n\n // Do not include the error message if the user aborted the request.\n if (message.errorReason === \"Aborted by user\") {\n children = (\n <>\n <AssistantMessageContent\n content={message.contentSoFar}\n chatId={message.chatId}\n />\n <MessageActions text={text} />\n </>\n );\n } else {\n children = (\n <>\n <AssistantMessageContent\n content={message.contentSoFar}\n chatId={message.chatId}\n />\n\n <div className=\"lb-ai-chat-message-error\">\n <span className=\"lb-icon-container\">\n <WarningIcon />\n </span>\n {message.errorReason}\n </div>\n\n <MessageActions text={text} />\n </>\n );\n }\n }\n\n return (\n <TooltipProvider>\n <div\n className={classNames(\n \"lb-ai-chat-message lb-ai-chat-assistant-message\",\n showActions === \"hover\" &&\n \"lb-ai-chat-message:show-actions-hover\",\n className\n )}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </div>\n </TooltipProvider>\n );\n }\n )\n);\n\nfunction CopyTextButton({ text, label }: { text: string; label: string }) {\n const [isCopied, setIsCopied] = useState(false);\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n setIsCopied(false);\n }, 2000);\n return () => {\n clearTimeout(timeoutId);\n };\n }, [isCopied]);\n\n return (\n <Button\n onClick={function () {\n navigator.clipboard.writeText(text);\n setIsCopied(true);\n }}\n className=\"lb-ai-chat-message-action\"\n aria-label={label}\n icon={isCopied ? <CheckIcon /> : <CopyIcon />}\n />\n );\n}\n\nfunction RegenerateMessageButton({\n chatId,\n messageId,\n copilotId,\n label,\n}: {\n chatId: string;\n messageId: MessageId;\n copilotId?: CopilotId;\n label: string;\n}) {\n const client = useClient();\n\n return (\n <Button\n onClick={function () {\n client[kInternal].ai.regenerateMessage(chatId, messageId, {\n copilotId,\n stream: true,\n });\n }}\n className=\"lb-ai-chat-message-action\"\n aria-label={label}\n icon={<RetryIcon />}\n />\n );\n}\n\nfunction AssistantMessageContent({\n content,\n chatId,\n}: {\n content: AiAssistantContentPart[];\n chatId: string;\n}) {\n // A message is considered to be in \"reasoning\" state if it only contains reasoning parts and no other parts.\n const isReasoning =\n content.some((part) => part.type === \"reasoning\") &&\n content.every((part) => part.type === \"reasoning\");\n\n return (\n <div className=\"lb-ai-chat-message-content\">\n {content.map((part, index) => {\n switch (part.type) {\n case \"text\": {\n return (\n <TextPart\n key={index}\n text={part.text}\n className=\"lb-ai-chat-message-text\"\n />\n );\n }\n case \"tool-call\": {\n return (\n <ToolCallPart\n key={index}\n chatId={chatId}\n name={part.toolName}\n args={part.args}\n />\n );\n }\n case \"reasoning\": {\n return (\n <ReasoningPart\n key={index}\n text={part.text}\n isPending={isReasoning}\n />\n );\n }\n default: {\n return null;\n }\n }\n })}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TextPart\n * -----------------------------------------------------------------------------------------------*/\ninterface TextPartProps extends ComponentProps<\"div\"> {\n text: string;\n}\n\nconst TextPart = forwardRef<HTMLDivElement, TextPartProps>(\n ({ text, ...props }, forwardedRef) => {\n const tokens = useMemo(() => {\n return new Lexer().lex(text);\n }, [text]);\n\n return (\n <div ref={forwardedRef} {...props}>\n {tokens.map((token, index) => {\n return (\n <MemoizedBlockTokenComp token={token as BlockToken} key={index} />\n );\n })}\n </div>\n );\n }\n);\n\nconst MemoizedBlockTokenComp = memo(\n function BlockTokenComp({ token }: { token: BlockToken }) {\n return <BlockTokenCompPrimitive token={token} />;\n },\n (prevProps, nextProps) => {\n const prevToken = prevProps.token;\n const nextToken = nextProps.token;\n if (prevToken.raw.length !== nextToken.raw.length) {\n return false;\n }\n if (prevToken.type !== nextToken.type) {\n return false;\n }\n return prevToken.raw === nextToken.raw;\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * ToolCallPart\n * -----------------------------------------------------------------------------------------------*/\nfunction ToolCallPart({\n chatId,\n name,\n args,\n}: {\n chatId: string;\n name: string;\n args: any;\n}) {\n const client = useClient();\n\n const tool = useSignal(\n client[kInternal].ai.signals.getToolDefinitionΣ(chatId, name)\n );\n if (tool === undefined || tool.render === undefined) return null;\n\n return (\n <div className=\"lb-ai-chat-message-tool\">\n <tool.render args={args as unknown} />\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * ReasoningPart\n * -----------------------------------------------------------------------------------------------*/\nfunction ReasoningPart({\n text,\n isPending,\n}: {\n text: string;\n isPending: boolean;\n}) {\n const [isOpen, setIsOpen] = useState(false);\n return (\n <CollapsiblePrimitive.Root\n className=\"lb-ai-chat-message-collapsible lb-ai-chat-message-reasoning\"\n open={isOpen}\n onOpenChange={setIsOpen}\n >\n <CollapsiblePrimitive.Trigger\n className={classNames(\n \"lb-ai-chat-message-collapsible-trigger\",\n isPending && \"lb-ai-chat-pending\"\n )}\n >\n Reasoning\n <span className=\"lb-icon-container\">\n {isOpen ? <ChevronDownIcon /> : <ChevronRightIcon />}\n </span>\n </CollapsiblePrimitive.Trigger>\n\n <CollapsiblePrimitive.Content className=\"lb-ai-chat-message-collapsible-content\">\n {text}\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n );\n}\n"],"names":["BlockTokenComp","BlockTokenCompPrimitive","CollapsiblePrimitive.Root","CollapsiblePrimitive.Trigger","CollapsiblePrimitive.Content"],"mappings":"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"}
1
+ {"version":3,"file":"AiChatAssistantMessage.js","sources":["../../../src/components/internal/AiChatAssistantMessage.tsx"],"sourcesContent":["import type {\n AiAssistantContentPart,\n AiToolInvocationPart,\n Json,\n MessageId,\n UiAssistantMessage,\n} from \"@liveblocks/core\";\nimport { kInternal } from \"@liveblocks/core\";\nimport { useClient } from \"@liveblocks/react\";\nimport { useSignal } from \"@liveblocks/react/_private\";\nimport { Lexer } from \"marked\";\nimport {\n type ComponentProps,\n forwardRef,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../../_private\";\nimport { type GlobalComponents, useComponents } from \"../../components\";\nimport { CheckIcon } from \"../../icons/Check\";\nimport { ChevronRightIcon } from \"../../icons/ChevronRight\";\nimport { CopyIcon } from \"../../icons/Copy\";\nimport { WarningIcon } from \"../../icons/Warning\";\nimport {\n type AiChatMessageOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../../overrides\";\nimport * as CollapsiblePrimitive from \"../../primitives/internal/Collapsible\";\nimport {\n type BlockToken,\n BlockTokenComp as BlockTokenCompPrimitive,\n type MarkdownComponents,\n} from \"../../primitives/internal/Markdown\";\nimport { classNames } from \"../../utils/class-names\";\n\n/* -------------------------------------------------------------------------------------------------\n * AiChatAssistantMessage\n * -----------------------------------------------------------------------------------------------*/\nexport interface AiChatAssistantMessageProps extends ComponentProps<\"div\"> {\n /**\n * The message to display.\n */\n message: UiAssistantMessage;\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & AiChatMessageOverrides>;\n\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents>;\n}\n\nexport const AiChatAssistantMessage = memo(\n forwardRef<HTMLDivElement, AiChatAssistantMessageProps>(\n ({ message, className, overrides, components, ...props }, forwardedRef) => {\n const $ = useOverrides(overrides);\n\n let children: ReactNode = null;\n\n if (message.deletedAt !== undefined) {\n children = (\n <div className=\"lb-ai-chat-message-deleted\">\n {$.AI_CHAT_MESSAGE_DELETED}\n </div>\n );\n } else if (\n message.status === \"generating\" ||\n message.status === \"awaiting-tool\"\n ) {\n if (message.contentSoFar.length === 0) {\n children = (\n <div className=\"lb-ai-chat-message-thinking lb-ai-chat-pending\">\n {$.AI_CHAT_MESSAGE_THINKING}\n </div>\n );\n } else {\n children = (\n <AssistantMessageContent\n content={message.contentSoFar}\n chatId={message.chatId}\n messageId={message.id}\n components={components}\n />\n );\n }\n } else if (message.status === \"completed\") {\n children = (\n <AssistantMessageContent\n content={message.content}\n chatId={message.chatId}\n messageId={message.id}\n components={components}\n />\n );\n } else if (message.status === \"failed\") {\n // Do not include the error message if the user aborted the request.\n if (message.errorReason === \"Aborted by user\") {\n children = (\n <AssistantMessageContent\n content={message.contentSoFar}\n chatId={message.chatId}\n messageId={message.id}\n components={components}\n />\n );\n } else {\n children = (\n <>\n <AssistantMessageContent\n content={message.contentSoFar}\n chatId={message.chatId}\n messageId={message.id}\n components={components}\n />\n\n <div className=\"lb-ai-chat-message-error\">\n <span className=\"lb-icon-container\">\n <WarningIcon />\n </span>\n {message.errorReason}\n </div>\n </>\n );\n }\n }\n\n return (\n <div\n className={classNames(\n \"lb-ai-chat-message lb-ai-chat-assistant-message\",\n className\n )}\n {...props}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n }\n )\n);\n\nfunction AssistantMessageContent({\n content,\n chatId,\n messageId,\n components,\n}: {\n content: AiAssistantContentPart[];\n chatId: string;\n messageId: MessageId;\n components: Partial<GlobalComponents> | undefined;\n}) {\n // A message is considered to be in \"reasoning\" state if it only contains reasoning parts and no other parts.\n const isReasoning =\n content.some((part) => part.type === \"reasoning\") &&\n content.every((part) => part.type === \"reasoning\");\n\n return (\n <div className=\"lb-ai-chat-message-content\">\n {content.map((part, index) => {\n switch (part.type) {\n case \"text\": {\n return (\n <TextPart\n key={index}\n text={part.text}\n components={components}\n className=\"lb-ai-chat-message-text\"\n />\n );\n }\n case \"tool-invocation\": {\n return (\n <ToolInvocationPart\n key={index}\n chatId={chatId}\n messageId={messageId}\n part={part}\n />\n );\n }\n case \"reasoning\": {\n return (\n <ReasoningPart\n key={index}\n text={part.text}\n isPending={isReasoning}\n components={components}\n />\n );\n }\n default: {\n return null;\n }\n }\n })}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TextPart\n * -----------------------------------------------------------------------------------------------*/\ninterface TextPartProps extends ComponentProps<\"div\"> {\n text: string;\n components: Partial<GlobalComponents> | undefined;\n}\n\nconst TextPart = forwardRef<HTMLDivElement, TextPartProps>(\n ({ text, components, ...props }, forwardedRef) => {\n const tokens = useMemo(() => {\n return new Lexer().lex(text);\n }, [text]);\n\n return (\n <div ref={forwardedRef} {...props}>\n {tokens.map((token, index) => {\n return (\n <MemoizedBlockTokenComp\n token={token as BlockToken}\n key={index}\n components={components}\n />\n );\n })}\n </div>\n );\n }\n);\n\n// TODO: Improve (better copy handling, tooltips, etc)\nfunction CodeBlock({\n language,\n code,\n}: ComponentProps<MarkdownComponents[\"CodeBlock\"]>) {\n const [isCopied, setCopied] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (isCopied) {\n timeoutRef.current = setTimeout(() => {\n setCopied(false);\n }, 1000);\n }\n\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, [isCopied]);\n\n return (\n <div className=\"lb-code-block\">\n <div className=\"lb-code-block-header\">\n <span className=\"lb-code-block-title\">{language ?? \"Plain text\"}</span>\n <div className=\"lb-code-block-header-actions\">\n <Button\n className=\"lb-code-block-header-action\"\n icon={isCopied ? <CheckIcon /> : <CopyIcon />}\n onClick={() => {\n setCopied(true);\n navigator.clipboard.writeText(code);\n }}\n />\n </div>\n </div>\n <pre className=\"lb-code-block-content\">\n <code>{code}</code>\n </pre>\n </div>\n );\n}\n\nconst MemoizedBlockTokenComp = memo(\n function BlockTokenComp({\n token,\n components,\n }: {\n token: BlockToken;\n components?: Partial<GlobalComponents>;\n }) {\n const { Anchor } = useComponents(components);\n\n return (\n <BlockTokenCompPrimitive\n token={token}\n components={{ CodeBlock, Anchor }}\n />\n );\n },\n (prevProps, nextProps) => {\n const prevToken = prevProps.token;\n const nextToken = nextProps.token;\n if (prevToken.raw.length !== nextToken.raw.length) {\n return false;\n }\n if (prevToken.type !== nextToken.type) {\n return false;\n }\n return prevToken.raw === nextToken.raw;\n }\n);\n\nfunction noop() {\n // Do nothing\n}\n\n/* -------------------------------------------------------------------------------------------------\n * ToolInvocationPart\n * -----------------------------------------------------------------------------------------------*/\nfunction ToolInvocationPart({\n chatId,\n messageId,\n part,\n}: {\n chatId: string;\n messageId: MessageId;\n part: AiToolInvocationPart;\n}) {\n const client = useClient();\n const ai = client[kInternal].ai;\n const tool = useSignal(ai.signals.getToolDefinitionΣ(chatId, part.toolName));\n const respond = useCallback(\n (result: Json) => {\n ai.setToolResult(\n chatId,\n messageId,\n part.toolCallId,\n result\n // TODO Pass in AiGenerationOptions here?\n );\n },\n [ai, chatId, messageId, part.toolCallId]\n );\n\n if (tool === undefined || tool.render === undefined) return null;\n\n const { type: _, ...rest } = part;\n return (\n <div className=\"lb-ai-chat-message-tool\">\n <tool.render\n {...rest}\n respond={\n // It only makes sense and is safe to call `respond()` in \"executing\" state.\n part.status === \"executing\" ? respond : noop\n }\n />\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * ReasoningPart\n * -----------------------------------------------------------------------------------------------*/\nfunction ReasoningPart({\n text,\n isPending,\n components,\n}: {\n text: string;\n isPending: boolean;\n components: Partial<GlobalComponents> | undefined;\n}) {\n const [isOpen, setIsOpen] = useState(false);\n return (\n <CollapsiblePrimitive.Root\n className=\"lb-ai-chat-message-collapsible lb-ai-chat-message-reasoning\"\n open={isOpen}\n onOpenChange={setIsOpen}\n >\n <CollapsiblePrimitive.Trigger\n className={classNames(\n \"lb-ai-chat-message-collapsible-trigger\",\n isPending && \"lb-ai-chat-pending\"\n )}\n >\n {/* TODO: If `isPending` is true, show \"Reasoning…\"/\"Thinking…\", otherwise show \"Reasoned/thought for x seconds\"? */}\n Reasoning\n <span className=\"lb-ai-chat-message-collapsible-chevron lb-icon-container\">\n <ChevronRightIcon />\n </span>\n </CollapsiblePrimitive.Trigger>\n\n <CollapsiblePrimitive.Content className=\"lb-ai-chat-message-collapsible-content\">\n <TextPart text={text} components={components} />\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n );\n}\n"],"names":["BlockTokenComp","BlockTokenCompPrimitive","CollapsiblePrimitive.Root","CollapsiblePrimitive.Trigger","CollapsiblePrimitive.Content"],"mappings":"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"}
@@ -26,6 +26,7 @@ const AiChatComposer = react.forwardRef(
26
26
  branchId,
27
27
  copilotId,
28
28
  stream = true,
29
+ onUserMessageCreate,
29
30
  ...props
30
31
  }, forwardedRef) => {
31
32
  const $ = overrides.useOverrides(overrides$1);
@@ -36,32 +37,43 @@ const AiChatComposer = react.forwardRef(
36
37
  return null;
37
38
  return lastMessage.id;
38
39
  }, []);
39
- const getPendingMessage = react.useCallback((messages) => {
40
+ const getAbortableMessageId = react.useCallback((messages) => {
40
41
  return messages.find(
41
- (m) => m.role === "assistant" && m.status === "pending"
42
+ (m) => m.role === "assistant" && (m.status === "generating" || m.status === "awaiting-tool")
42
43
  )?.id;
43
44
  }, []);
44
- const pendingMessage = _private.useSignal(
45
- client[core.kInternal].ai.signals.getChatMessagesForBranch\u03A3(chatId, branchId),
46
- getPendingMessage
47
- );
48
- const lastMessageId = _private.useSignal(
49
- client[core.kInternal].ai.signals.getChatMessagesForBranch\u03A3(chatId, branchId),
50
- getLastMessageId
45
+ const messages\u03A3 = client[core.kInternal].ai.signals.getChatMessagesForBranch\u03A3(
46
+ chatId,
47
+ branchId
51
48
  );
49
+ const abortableMessageId = _private.useSignal(messages\u03A3, getAbortableMessageId);
50
+ const lastMessageId = _private.useSignal(messages\u03A3, getLastMessageId);
52
51
  const handleComposerSubmit = react.useCallback(
53
52
  (message, event) => {
54
- if (pendingMessage !== void 0) {
53
+ if (abortableMessageId !== void 0) {
55
54
  event.preventDefault();
56
55
  return;
57
56
  }
58
57
  onComposerSubmit?.(message, event);
59
58
  if (event.isDefaultPrevented())
60
59
  return;
61
- client[core.kInternal].ai.addUserMessageAndAsk(
60
+ const content = [{ type: "text", text: message.text }];
61
+ const newMessageId = client[core.kInternal].ai[core.kInternal].context.messagesStore.createOptimistically(
62
62
  chatId,
63
+ "user",
63
64
  lastMessageId,
64
- message.text,
65
+ content
66
+ );
67
+ onUserMessageCreate?.({ id: newMessageId });
68
+ const targetMessageId = client[core.kInternal].ai[core.kInternal].context.messagesStore.createOptimistically(
69
+ chatId,
70
+ "assistant",
71
+ newMessageId
72
+ );
73
+ client[core.kInternal].ai.askUserMessageInChat(
74
+ chatId,
75
+ { id: newMessageId, parentMessageId: lastMessageId, content },
76
+ targetMessageId,
65
77
  {
66
78
  stream,
67
79
  copilotId
@@ -70,10 +82,11 @@ const AiChatComposer = react.forwardRef(
70
82
  },
71
83
  [
72
84
  onComposerSubmit,
85
+ onUserMessageCreate,
73
86
  client,
74
87
  chatId,
75
88
  lastMessageId,
76
- pendingMessage,
89
+ abortableMessageId,
77
90
  stream,
78
91
  copilotId
79
92
  ]
@@ -84,7 +97,6 @@ const AiChatComposer = react.forwardRef(
84
97
  "lb-ai-chat-composer lb-ai-chat-composer-form",
85
98
  className
86
99
  ),
87
- chatId,
88
100
  dir: $.dir,
89
101
  ...props,
90
102
  disabled,
@@ -107,7 +119,7 @@ const AiChatComposer = react.forwardRef(
107
119
  }),
108
120
  /* @__PURE__ */ jsxRuntime.jsx("div", {
109
121
  className: "lb-ai-chat-composer-actions",
110
- children: pendingMessage === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip.ShortcutTooltip, {
122
+ children: abortableMessageId === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Tooltip.ShortcutTooltip, {
111
123
  content: $.AI_CHAT_COMPOSER_SEND,
112
124
  shortcut: "Enter",
113
125
  children: /* @__PURE__ */ jsxRuntime.jsx(index.AiChatComposerSubmit, {
@@ -127,7 +139,7 @@ const AiChatComposer = react.forwardRef(
127
139
  onPointerDown: (event) => event.preventDefault(),
128
140
  onClick: (event) => {
129
141
  event.stopPropagation();
130
- client[core.kInternal].ai.abort(pendingMessage);
142
+ client[core.kInternal].ai.abort(abortableMessageId);
131
143
  },
132
144
  className: "lb-ai-chat-composer-action",
133
145
  variant: "secondary",