@letta-ai/letta-react 0.0.5 → 0.0.7

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.
@@ -35,6 +35,25 @@ function extendContent(content, nextContent) {
35
35
  }
36
36
  }
37
37
  }
38
+ function dedupeMessages(messages) {
39
+ const messageIndex = new Set(messages.map((message) => `${message.id}${message.messageType}`));
40
+ return messages.filter((message) => {
41
+ // if we have seen this message before, return false
42
+ if (messageIndex.has(`${message.id}${message.messageType}`)) {
43
+ messageIndex.delete(`${message.id}${message.messageType}`);
44
+ return true;
45
+ }
46
+ return false;
47
+ }, []);
48
+ }
49
+ function messageCreateToMessageUnion(messages) {
50
+ return messages.map((message, idx) => ({
51
+ messageType: message.role === 'user' ? 'user_message' : 'system_message',
52
+ content: message.content,
53
+ date: new Date(),
54
+ id: `autogenerated_${Date.now()}_${idx}`,
55
+ }));
56
+ }
38
57
  export function useAgentMessages(options) {
39
58
  const { client = {}, method = 'stream', messageOptions = {}, limit = 20, agentId, } = options;
40
59
  const localClient = useLettaClient(client);
@@ -49,26 +68,39 @@ export function useAgentMessages(options) {
49
68
  const [sendingError, setSendingError] = useState(null);
50
69
  const sendNonStreamedMessage = useCallback(function sendNonStreamedMessage(sendMessagePayload) {
51
70
  return __awaiter(this, void 0, void 0, function* () {
71
+ let originalMessageState = localMessages;
52
72
  try {
53
73
  setIsSending(true);
54
74
  setSendingError(null);
75
+ const newMessages = messageCreateToMessageUnion(sendMessagePayload.messages);
76
+ setLocalMessages((prevState) => {
77
+ originalMessageState = prevState;
78
+ return Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...newMessages] });
79
+ });
55
80
  const response = yield localClient.agents.messages.create(agentId, Object.assign(Object.assign({}, sendMessagePayload), messageOptions));
56
- setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...response.messages, ...prevState.messages] })));
81
+ setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...response.messages] })));
57
82
  }
58
83
  catch (e) {
84
+ setLocalMessages(originalMessageState);
59
85
  setSendingError(e);
60
86
  }
61
87
  finally {
62
88
  setIsSending(false);
63
89
  }
64
90
  });
65
- }, [localClient]);
91
+ }, [localClient, localMessages]);
66
92
  const sendStreamedMessage = useCallback(function sendStreamedMessage(sendMessagePayload) {
67
93
  return __awaiter(this, void 0, void 0, function* () {
68
94
  var _a, e_1, _b, _c;
95
+ let originalMessageState = localMessages;
69
96
  try {
70
97
  setIsSending(true);
71
98
  setSendingError(null);
99
+ const newMessages = messageCreateToMessageUnion(sendMessagePayload.messages);
100
+ setLocalMessages((prevState) => {
101
+ originalMessageState = prevState;
102
+ return Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...newMessages] });
103
+ });
72
104
  const response = yield localClient.agents.messages.createStream(agentId, Object.assign(Object.assign(Object.assign({}, sendMessagePayload), messageOptions), { streamTokens: true }));
73
105
  try {
74
106
  for (var _d = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = yield response_1.next(), _a = response_1_1.done, !_a; _d = true) {
@@ -156,13 +188,17 @@ export function useAgentMessages(options) {
156
188
  });
157
189
  }, [localClient]);
158
190
  const sendMessage = useCallback(function sendMessage(payload) {
191
+ const filteredPayload = Object.assign(Object.assign({}, payload), { messages: payload.messages.filter((e) => !!e.content) });
192
+ if (filteredPayload.messages.length === 0) {
193
+ return;
194
+ }
159
195
  if (isSending) {
160
196
  return;
161
197
  }
162
198
  if (method === 'stream') {
163
- return sendStreamedMessage(payload);
199
+ return sendStreamedMessage(filteredPayload);
164
200
  }
165
- return sendNonStreamedMessage(payload);
201
+ return sendNonStreamedMessage(filteredPayload);
166
202
  }, [method, isSending, sendStreamedMessage, sendNonStreamedMessage]);
167
203
  const getMessages = useCallback(function getMessages(before) {
168
204
  return __awaiter(this, void 0, void 0, function* () {
@@ -175,7 +211,7 @@ export function useAgentMessages(options) {
175
211
  const messages = yield localClient.agents.messages.list(agentId, Object.assign({ before, limit: limit + 1 }, messageOptions));
176
212
  const messagesToAdd = messages.slice(1, messages.length);
177
213
  const nextCursor = messages.length > limit ? messages[0] : undefined;
178
- setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...messagesToAdd, ...prevState.messages], nextCursor: nextCursor === null || nextCursor === void 0 ? void 0 : nextCursor.id })));
214
+ setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: dedupeMessages([...messagesToAdd, ...prevState.messages]), nextCursor: nextCursor === null || nextCursor === void 0 ? void 0 : nextCursor.id })));
179
215
  }
180
216
  catch (e) {
181
217
  setLoadingError(e);
@@ -57,7 +57,6 @@ function App() {
57
57
  return (
58
58
  <li key={`${message.id}${message.messageType}`}>
59
59
  {message.content}
60
- {message.id}
61
60
  </li>
62
61
  );
63
62
  }
@@ -35,6 +35,25 @@ function extendContent(content, nextContent) {
35
35
  }
36
36
  }
37
37
  }
38
+ function dedupeMessages(messages) {
39
+ const messageIndex = new Set(messages.map((message) => `${message.id}${message.messageType}`));
40
+ return messages.filter((message) => {
41
+ // if we have seen this message before, return false
42
+ if (messageIndex.has(`${message.id}${message.messageType}`)) {
43
+ messageIndex.delete(`${message.id}${message.messageType}`);
44
+ return true;
45
+ }
46
+ return false;
47
+ }, []);
48
+ }
49
+ function messageCreateToMessageUnion(messages) {
50
+ return messages.map((message, idx) => ({
51
+ messageType: message.role === 'user' ? 'user_message' : 'system_message',
52
+ content: message.content,
53
+ date: new Date(),
54
+ id: `autogenerated_${Date.now()}_${idx}`,
55
+ }));
56
+ }
38
57
  export function useAgentMessages(options) {
39
58
  const { client = {}, method = 'stream', messageOptions = {}, limit = 20, agentId, } = options;
40
59
  const localClient = useLettaClient(client);
@@ -49,26 +68,39 @@ export function useAgentMessages(options) {
49
68
  const [sendingError, setSendingError] = useState(null);
50
69
  const sendNonStreamedMessage = useCallback(function sendNonStreamedMessage(sendMessagePayload) {
51
70
  return __awaiter(this, void 0, void 0, function* () {
71
+ let originalMessageState = localMessages;
52
72
  try {
53
73
  setIsSending(true);
54
74
  setSendingError(null);
75
+ const newMessages = messageCreateToMessageUnion(sendMessagePayload.messages);
76
+ setLocalMessages((prevState) => {
77
+ originalMessageState = prevState;
78
+ return Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...newMessages] });
79
+ });
55
80
  const response = yield localClient.agents.messages.create(agentId, Object.assign(Object.assign({}, sendMessagePayload), messageOptions));
56
- setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...response.messages, ...prevState.messages] })));
81
+ setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...response.messages] })));
57
82
  }
58
83
  catch (e) {
84
+ setLocalMessages(originalMessageState);
59
85
  setSendingError(e);
60
86
  }
61
87
  finally {
62
88
  setIsSending(false);
63
89
  }
64
90
  });
65
- }, [localClient]);
91
+ }, [localClient, localMessages]);
66
92
  const sendStreamedMessage = useCallback(function sendStreamedMessage(sendMessagePayload) {
67
93
  return __awaiter(this, void 0, void 0, function* () {
68
94
  var _a, e_1, _b, _c;
95
+ let originalMessageState = localMessages;
69
96
  try {
70
97
  setIsSending(true);
71
98
  setSendingError(null);
99
+ const newMessages = messageCreateToMessageUnion(sendMessagePayload.messages);
100
+ setLocalMessages((prevState) => {
101
+ originalMessageState = prevState;
102
+ return Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...newMessages] });
103
+ });
72
104
  const response = yield localClient.agents.messages.createStream(agentId, Object.assign(Object.assign(Object.assign({}, sendMessagePayload), messageOptions), { streamTokens: true }));
73
105
  try {
74
106
  for (var _d = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = yield response_1.next(), _a = response_1_1.done, !_a; _d = true) {
@@ -156,13 +188,17 @@ export function useAgentMessages(options) {
156
188
  });
157
189
  }, [localClient]);
158
190
  const sendMessage = useCallback(function sendMessage(payload) {
191
+ const filteredPayload = Object.assign(Object.assign({}, payload), { messages: payload.messages.filter((e) => !!e.content) });
192
+ if (filteredPayload.messages.length === 0) {
193
+ return;
194
+ }
159
195
  if (isSending) {
160
196
  return;
161
197
  }
162
198
  if (method === 'stream') {
163
- return sendStreamedMessage(payload);
199
+ return sendStreamedMessage(filteredPayload);
164
200
  }
165
- return sendNonStreamedMessage(payload);
201
+ return sendNonStreamedMessage(filteredPayload);
166
202
  }, [method, isSending, sendStreamedMessage, sendNonStreamedMessage]);
167
203
  const getMessages = useCallback(function getMessages(before) {
168
204
  return __awaiter(this, void 0, void 0, function* () {
@@ -175,7 +211,7 @@ export function useAgentMessages(options) {
175
211
  const messages = yield localClient.agents.messages.list(agentId, Object.assign({ before, limit: limit + 1 }, messageOptions));
176
212
  const messagesToAdd = messages.slice(1, messages.length);
177
213
  const nextCursor = messages.length > limit ? messages[0] : undefined;
178
- setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...messagesToAdd, ...prevState.messages], nextCursor: nextCursor === null || nextCursor === void 0 ? void 0 : nextCursor.id })));
214
+ setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: dedupeMessages([...messagesToAdd, ...prevState.messages]), nextCursor: nextCursor === null || nextCursor === void 0 ? void 0 : nextCursor.id })));
179
215
  }
180
216
  catch (e) {
181
217
  setLoadingError(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-react",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Letta's react library",
5
5
  "private": false,
6
6
  "main": "./index.js",
@@ -6,6 +6,7 @@ import { useGlobalLettaConfig } from '../useGlobalLettaConfig/useGlobalLettaConf
6
6
  import type { LocalMessagesState } from '../../types';
7
7
  import { useCachedState } from '../useCachedState/useCachedState';
8
8
  import { useLettaClient } from '../useLettaClient/useLettaClient';
9
+ import { LettaMessageUnion, MessageCreate } from '@letta-ai/letta-client/api';
9
10
 
10
11
  interface UseAgentOptions {
11
12
  client?: LettaClient.Options;
@@ -34,6 +35,35 @@ function extendContent(
34
35
  }
35
36
  }
36
37
 
38
+ function dedupeMessages(
39
+ messages: LocalMessagesState['messages']
40
+ ): LocalMessagesState['messages'] {
41
+ const messageIndex = new Set(
42
+ messages.map((message) => `${message.id}${message.messageType}`)
43
+ );
44
+
45
+ return messages.filter((message) => {
46
+ // if we have seen this message before, return false
47
+ if (messageIndex.has(`${message.id}${message.messageType}`)) {
48
+ messageIndex.delete(`${message.id}${message.messageType}`);
49
+ return true;
50
+ }
51
+
52
+ return false;
53
+ }, []);
54
+ }
55
+
56
+ function messageCreateToMessageUnion(
57
+ messages: MessageCreate[]
58
+ ): LettaMessageUnion[] {
59
+ return messages.map((message, idx) => ({
60
+ messageType: message.role === 'user' ? 'user_message' : 'system_message',
61
+ content: message.content,
62
+ date: new Date(),
63
+ id: `autogenerated_${Date.now()}_${idx}`,
64
+ }));
65
+ }
66
+
37
67
  interface SendMessagePayload {
38
68
  messages: LettaRequest['messages'];
39
69
  }
@@ -68,10 +98,24 @@ export function useAgentMessages(options: UseAgentOptions) {
68
98
  async function sendNonStreamedMessage(
69
99
  sendMessagePayload: SendMessagePayload
70
100
  ) {
101
+ let originalMessageState: LocalMessagesState = localMessages;
71
102
  try {
72
103
  setIsSending(true);
73
104
  setSendingError(null);
74
105
 
106
+ const newMessages = messageCreateToMessageUnion(
107
+ sendMessagePayload.messages
108
+ );
109
+
110
+ setLocalMessages((prevState) => {
111
+ originalMessageState = prevState;
112
+
113
+ return {
114
+ ...prevState,
115
+ messages: [...prevState.messages, ...newMessages],
116
+ };
117
+ });
118
+
75
119
  const response = await localClient.agents.messages.create(agentId, {
76
120
  ...sendMessagePayload,
77
121
  ...messageOptions,
@@ -79,23 +123,39 @@ export function useAgentMessages(options: UseAgentOptions) {
79
123
 
80
124
  setLocalMessages((prevState) => ({
81
125
  ...prevState,
82
- messages: [...response.messages, ...prevState.messages],
126
+ messages: [...prevState.messages, ...response.messages],
83
127
  }));
84
128
  } catch (e) {
129
+ setLocalMessages(originalMessageState);
85
130
  setSendingError(e);
86
131
  } finally {
87
132
  setIsSending(false);
88
133
  }
89
134
  },
90
- [localClient]
135
+ [localClient, localMessages]
91
136
  );
92
137
 
93
138
  const sendStreamedMessage = useCallback(
94
139
  async function sendStreamedMessage(sendMessagePayload: SendMessagePayload) {
140
+ let originalMessageState: LocalMessagesState = localMessages;
141
+
95
142
  try {
96
143
  setIsSending(true);
97
144
  setSendingError(null);
98
145
 
146
+ const newMessages = messageCreateToMessageUnion(
147
+ sendMessagePayload.messages
148
+ );
149
+
150
+ setLocalMessages((prevState) => {
151
+ originalMessageState = prevState;
152
+
153
+ return {
154
+ ...prevState,
155
+ messages: [...prevState.messages, ...newMessages],
156
+ };
157
+ });
158
+
99
159
  const response = await localClient.agents.messages.createStream(
100
160
  agentId,
101
161
  {
@@ -244,15 +304,24 @@ export function useAgentMessages(options: UseAgentOptions) {
244
304
 
245
305
  const sendMessage = useCallback(
246
306
  function sendMessage(payload: SendMessagePayload) {
307
+ const filteredPayload = {
308
+ ...payload,
309
+ messages: payload.messages.filter((e) => !!e.content),
310
+ };
311
+
312
+ if (filteredPayload.messages.length === 0) {
313
+ return;
314
+ }
315
+
247
316
  if (isSending) {
248
317
  return;
249
318
  }
250
319
 
251
320
  if (method === 'stream') {
252
- return sendStreamedMessage(payload);
321
+ return sendStreamedMessage(filteredPayload);
253
322
  }
254
323
 
255
- return sendNonStreamedMessage(payload);
324
+ return sendNonStreamedMessage(filteredPayload);
256
325
  },
257
326
  [method, isSending, sendStreamedMessage, sendNonStreamedMessage]
258
327
  );
@@ -278,7 +347,7 @@ export function useAgentMessages(options: UseAgentOptions) {
278
347
 
279
348
  setLocalMessages((prevState) => ({
280
349
  ...prevState,
281
- messages: [...messagesToAdd, ...prevState.messages],
350
+ messages: dedupeMessages([...messagesToAdd, ...prevState.messages]),
282
351
  nextCursor: nextCursor?.id,
283
352
  }));
284
353
  } catch (e) {