@aws-amplify/ui-react-ai 1.5.1 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,13 @@ import { isFunction } from '@aws-amplify/ui';
4
4
  import { contentFromEvents } from './contentFromEvents.mjs';
5
5
  import { exhaustivelyListMessages } from './exhaustivelyListMessages.mjs';
6
6
 
7
+ // Synthetic ids used for the messages optimistically added by
8
+ // `handleSendMessage` before the backend assigns real ids. The streamed
9
+ // assistant events carry the real message id, so the first event of a turn
10
+ // won't match by id; we use this to swap the placeholder in place instead of
11
+ // appending a second (empty) assistant bubble.
12
+ const OPTIMISTIC_USER_MESSAGE_ID = 'temp-id';
13
+ const OPTIMISTIC_ASSISTANT_MESSAGE_ID = 'temp-id-2';
7
14
  function hasStarted(state) {
8
15
  return ['initialLoading', 'initialized'].includes(state);
9
16
  }
@@ -192,13 +199,20 @@ function createUseAIConversation(client) {
192
199
  role: 'assistant',
193
200
  isLoading: true,
194
201
  };
195
- // Match by message ID instead of assuming last message
202
+ // Match by real message ID (handles out-of-order / duplicate
203
+ // events for a message we've already started rendering). On the
204
+ // first event of a turn there is no match yet, so fall back to the
205
+ // optimistic assistant placeholder added by handleSendMessage;
206
+ // replacing it in place avoids leaving an empty assistant bubble.
196
207
  const existingIndex = prev.data.messages.findIndex((m) => m.id === id);
197
- const updatedMessages = existingIndex >= 0
208
+ const targetIndex = existingIndex >= 0
209
+ ? existingIndex
210
+ : prev.data.messages.findIndex((m) => m.id === OPTIMISTIC_ASSISTANT_MESSAGE_ID);
211
+ const updatedMessages = targetIndex >= 0
198
212
  ? [
199
- ...prev.data.messages.slice(0, existingIndex),
213
+ ...prev.data.messages.slice(0, targetIndex),
200
214
  message,
201
- ...prev.data.messages.slice(existingIndex + 1),
215
+ ...prev.data.messages.slice(targetIndex + 1),
202
216
  ]
203
217
  : [...prev.data.messages, message];
204
218
  return {
@@ -244,14 +258,14 @@ function createUseAIConversation(client) {
244
258
  content,
245
259
  role: 'user',
246
260
  createdAt: new Date().toISOString(),
247
- id: 'temp-id',
261
+ id: OPTIMISTIC_USER_MESSAGE_ID,
248
262
  conversationId: conversation.id ?? '',
249
263
  },
250
264
  {
251
265
  content: [{ text: ' ' }],
252
266
  role: 'assistant',
253
267
  createdAt: new Date().toISOString(),
254
- id: 'temp-id-2',
268
+ id: OPTIMISTIC_ASSISTANT_MESSAGE_ID,
255
269
  conversationId: conversation.id ?? '',
256
270
  isLoading: true,
257
271
  },
@@ -1,3 +1,3 @@
1
- const VERSION = '1.5.1';
1
+ const VERSION = '1.5.2';
2
2
 
3
3
  export { VERSION };
package/dist/index.js CHANGED
@@ -1230,7 +1230,7 @@ const PromptList = ({ setInput, suggestedPrompts = [], }) => {
1230
1230
  })));
1231
1231
  };
1232
1232
 
1233
- const VERSION = '1.5.1';
1233
+ const VERSION = '1.5.2';
1234
1234
 
1235
1235
  function AIConversationBase({ avatars, controls, messages, ...rest }) {
1236
1236
  uiReactCore.useSetUserAgent({
@@ -1341,6 +1341,13 @@ async function exhaustivelyListMessages({ conversation, messages = [], nextToken
1341
1341
  };
1342
1342
  }
1343
1343
 
1344
+ // Synthetic ids used for the messages optimistically added by
1345
+ // `handleSendMessage` before the backend assigns real ids. The streamed
1346
+ // assistant events carry the real message id, so the first event of a turn
1347
+ // won't match by id; we use this to swap the placeholder in place instead of
1348
+ // appending a second (empty) assistant bubble.
1349
+ const OPTIMISTIC_USER_MESSAGE_ID = 'temp-id';
1350
+ const OPTIMISTIC_ASSISTANT_MESSAGE_ID = 'temp-id-2';
1344
1351
  function hasStarted(state) {
1345
1352
  return ['initialLoading', 'initialized'].includes(state);
1346
1353
  }
@@ -1529,13 +1536,20 @@ function createUseAIConversation(client) {
1529
1536
  role: 'assistant',
1530
1537
  isLoading: true,
1531
1538
  };
1532
- // Match by message ID instead of assuming last message
1539
+ // Match by real message ID (handles out-of-order / duplicate
1540
+ // events for a message we've already started rendering). On the
1541
+ // first event of a turn there is no match yet, so fall back to the
1542
+ // optimistic assistant placeholder added by handleSendMessage;
1543
+ // replacing it in place avoids leaving an empty assistant bubble.
1533
1544
  const existingIndex = prev.data.messages.findIndex((m) => m.id === id);
1534
- const updatedMessages = existingIndex >= 0
1545
+ const targetIndex = existingIndex >= 0
1546
+ ? existingIndex
1547
+ : prev.data.messages.findIndex((m) => m.id === OPTIMISTIC_ASSISTANT_MESSAGE_ID);
1548
+ const updatedMessages = targetIndex >= 0
1535
1549
  ? [
1536
- ...prev.data.messages.slice(0, existingIndex),
1550
+ ...prev.data.messages.slice(0, targetIndex),
1537
1551
  message,
1538
- ...prev.data.messages.slice(existingIndex + 1),
1552
+ ...prev.data.messages.slice(targetIndex + 1),
1539
1553
  ]
1540
1554
  : [...prev.data.messages, message];
1541
1555
  return {
@@ -1581,14 +1595,14 @@ function createUseAIConversation(client) {
1581
1595
  content,
1582
1596
  role: 'user',
1583
1597
  createdAt: new Date().toISOString(),
1584
- id: 'temp-id',
1598
+ id: OPTIMISTIC_USER_MESSAGE_ID,
1585
1599
  conversationId: conversation.id ?? '',
1586
1600
  },
1587
1601
  {
1588
1602
  content: [{ text: ' ' }],
1589
1603
  role: 'assistant',
1590
1604
  createdAt: new Date().toISOString(),
1591
- id: 'temp-id-2',
1605
+ id: OPTIMISTIC_ASSISTANT_MESSAGE_ID,
1592
1606
  conversationId: conversation.id ?? '',
1593
1607
  isLoading: true,
1594
1608
  },
@@ -1 +1 @@
1
- export declare const VERSION = "1.5.1";
1
+ export declare const VERSION = "1.5.2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-amplify/ui-react-ai",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/esm/index.mjs",
6
6
  "exports": {
@@ -48,9 +48,9 @@
48
48
  "react-dom": "^16.14 || ^17 || ^18 || ^19"
49
49
  },
50
50
  "dependencies": {
51
- "@aws-amplify/ui": "^6.15.2",
52
- "@aws-amplify/ui-react": "^6.15.2",
53
- "@aws-amplify/ui-react-core": "^3.6.2"
51
+ "@aws-amplify/ui": "^6.15.6",
52
+ "@aws-amplify/ui-react": "^6.15.6",
53
+ "@aws-amplify/ui-react-core": "^3.6.6"
54
54
  },
55
55
  "size-limit": [
56
56
  {