@letta-ai/letta-react 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/useAgentMessages/useAgentMessages.js +34 -10
- package/dist/hooks/useAgentPassages/useAgentPassages.d.ts +13 -0
- package/dist/hooks/useAgentPassages/useAgentPassages.js +45 -0
- package/dist/hooks/useAgentState/useAgentState.d.ts +5 -2
- package/dist/hooks/useAgentState/useAgentState.js +25 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/examples/view-and-send-messages/src/App.tsx +21 -4
- package/hooks/useAgentMessages/useAgentMessages.js +34 -10
- package/hooks/useAgentPassages/useAgentPassages.d.ts +13 -0
- package/hooks/useAgentPassages/useAgentPassages.js +45 -0
- package/hooks/useAgentState/useAgentState.d.ts +5 -2
- package/hooks/useAgentState/useAgentState.js +25 -8
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/src/hooks/useAgentMessages/useAgentMessages.ts +60 -13
- package/src/hooks/useAgentPassages/useAgentPassages.ts +51 -0
- package/src/hooks/useAgentState/useAgentState.ts +29 -12
- package/src/index.ts +1 -0
@@ -46,13 +46,21 @@ function dedupeMessages(messages) {
|
|
46
46
|
return false;
|
47
47
|
}, []);
|
48
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
|
+
}
|
49
57
|
export function useAgentMessages(options) {
|
50
58
|
const { client = {}, method = 'stream', messageOptions = {}, limit = 20, agentId, } = options;
|
51
59
|
const localClient = useLettaClient(client);
|
52
60
|
const [localMessages, setLocalMessages] = useCachedState(`messages-${agentId}`, {
|
53
61
|
messages: [],
|
54
62
|
});
|
55
|
-
const
|
63
|
+
const agentIdMessagesLoadedRef = useRef(false);
|
56
64
|
const [isLoading, setIsLoading] = useState(true);
|
57
65
|
const [isFetching, setIsFetching] = useState(false);
|
58
66
|
const [loadingError, setLoadingError] = useState(null);
|
@@ -60,26 +68,39 @@ export function useAgentMessages(options) {
|
|
60
68
|
const [sendingError, setSendingError] = useState(null);
|
61
69
|
const sendNonStreamedMessage = useCallback(function sendNonStreamedMessage(sendMessagePayload) {
|
62
70
|
return __awaiter(this, void 0, void 0, function* () {
|
71
|
+
let originalMessageState = localMessages;
|
63
72
|
try {
|
64
73
|
setIsSending(true);
|
65
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
|
+
});
|
66
80
|
const response = yield localClient.agents.messages.create(agentId, Object.assign(Object.assign({}, sendMessagePayload), messageOptions));
|
67
|
-
setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...
|
81
|
+
setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...response.messages] })));
|
68
82
|
}
|
69
83
|
catch (e) {
|
84
|
+
setLocalMessages(originalMessageState);
|
70
85
|
setSendingError(e);
|
71
86
|
}
|
72
87
|
finally {
|
73
88
|
setIsSending(false);
|
74
89
|
}
|
75
90
|
});
|
76
|
-
}, [localClient]);
|
91
|
+
}, [localClient, localMessages]);
|
77
92
|
const sendStreamedMessage = useCallback(function sendStreamedMessage(sendMessagePayload) {
|
78
93
|
return __awaiter(this, void 0, void 0, function* () {
|
79
94
|
var _a, e_1, _b, _c;
|
95
|
+
let originalMessageState = localMessages;
|
80
96
|
try {
|
81
97
|
setIsSending(true);
|
82
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
|
+
});
|
83
104
|
const response = yield localClient.agents.messages.createStream(agentId, Object.assign(Object.assign(Object.assign({}, sendMessagePayload), messageOptions), { streamTokens: true }));
|
84
105
|
try {
|
85
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) {
|
@@ -167,13 +188,17 @@ export function useAgentMessages(options) {
|
|
167
188
|
});
|
168
189
|
}, [localClient]);
|
169
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
|
+
}
|
170
195
|
if (isSending) {
|
171
196
|
return;
|
172
197
|
}
|
173
198
|
if (method === 'stream') {
|
174
|
-
return sendStreamedMessage(
|
199
|
+
return sendStreamedMessage(filteredPayload);
|
175
200
|
}
|
176
|
-
return sendNonStreamedMessage(
|
201
|
+
return sendNonStreamedMessage(filteredPayload);
|
177
202
|
}, [method, isSending, sendStreamedMessage, sendNonStreamedMessage]);
|
178
203
|
const getMessages = useCallback(function getMessages(before) {
|
179
204
|
return __awaiter(this, void 0, void 0, function* () {
|
@@ -205,12 +230,11 @@ export function useAgentMessages(options) {
|
|
205
230
|
return getMessages(nextCursor);
|
206
231
|
}), [getMessages]);
|
207
232
|
useEffect(() => {
|
208
|
-
if (
|
209
|
-
|
233
|
+
if (!agentIdMessagesLoadedRef.current) {
|
234
|
+
setIsLoading(true);
|
235
|
+
void getMessages();
|
236
|
+
agentIdMessagesLoadedRef.current = true;
|
210
237
|
}
|
211
|
-
hasInitialLoaded.current = true;
|
212
|
-
setIsLoading(true);
|
213
|
-
getMessages();
|
214
238
|
}, []);
|
215
239
|
return {
|
216
240
|
messages: localMessages.messages,
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import type { Passage } from '@letta-ai/letta-client/api';
|
2
|
+
import type { LettaClient } from '@letta-ai/letta-client';
|
3
|
+
interface UseAgentStateOptions {
|
4
|
+
client?: LettaClient.Options;
|
5
|
+
agentId: string;
|
6
|
+
}
|
7
|
+
export declare function useAgentPassages(options: UseAgentStateOptions): {
|
8
|
+
isLoading: boolean;
|
9
|
+
isLoadingError: unknown;
|
10
|
+
passages: Passage[] | undefined;
|
11
|
+
refresh: () => Promise<void>;
|
12
|
+
};
|
13
|
+
export {};
|
@@ -0,0 +1,45 @@
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
|
+
});
|
9
|
+
};
|
10
|
+
import { useLettaClient } from '../useLettaClient/useLettaClient';
|
11
|
+
import { useCachedState } from '../useCachedState/useCachedState';
|
12
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
13
|
+
export function useAgentPassages(options) {
|
14
|
+
const { client, agentId } = options;
|
15
|
+
const localClient = useLettaClient(client);
|
16
|
+
const loadedAgentId = useRef(null);
|
17
|
+
const [localState, setLocalState] = useCachedState(`agent-passages-${agentId}`, undefined);
|
18
|
+
const [isLoading, setIsLoading] = useState(true);
|
19
|
+
const [isLoadingError, setIsLoadingError] = useState(null);
|
20
|
+
const getAgentPassages = useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
21
|
+
try {
|
22
|
+
const state = yield localClient.agents.passages.list(agentId);
|
23
|
+
setLocalState(state);
|
24
|
+
}
|
25
|
+
catch (error) {
|
26
|
+
setIsLoadingError(error);
|
27
|
+
}
|
28
|
+
finally {
|
29
|
+
setIsLoading(false);
|
30
|
+
}
|
31
|
+
}), [agentId, localClient, setLocalState]);
|
32
|
+
useEffect(() => {
|
33
|
+
if (agentId !== loadedAgentId.current) {
|
34
|
+
setIsLoading(true);
|
35
|
+
void getAgentPassages();
|
36
|
+
loadedAgentId.current = agentId;
|
37
|
+
}
|
38
|
+
}, [agentId, getAgentPassages]);
|
39
|
+
return {
|
40
|
+
isLoading,
|
41
|
+
isLoadingError,
|
42
|
+
passages: localState,
|
43
|
+
refresh: getAgentPassages,
|
44
|
+
};
|
45
|
+
}
|
@@ -1,12 +1,15 @@
|
|
1
1
|
import type { LettaClient } from '@letta-ai/letta-client';
|
2
|
-
import type { AgentState } from '@letta-ai/letta-client/api';
|
2
|
+
import type { AgentState, UpdateAgent } from '@letta-ai/letta-client/api';
|
3
3
|
interface UseAgentStateOptions {
|
4
4
|
client?: LettaClient.Options;
|
5
5
|
agentId: string;
|
6
6
|
}
|
7
7
|
export declare function useAgentState(options: UseAgentStateOptions): {
|
8
8
|
isLoading: boolean;
|
9
|
-
|
9
|
+
updateAgentState: (state: Partial<UpdateAgent>) => Promise<void>;
|
10
|
+
isUpdating: boolean;
|
11
|
+
updatingError: unknown;
|
12
|
+
loadingError: unknown;
|
10
13
|
agentState: AgentState | undefined;
|
11
14
|
refresh: () => Promise<void>;
|
12
15
|
};
|
@@ -15,8 +15,10 @@ export function useAgentState(options) {
|
|
15
15
|
const localClient = useLettaClient(client);
|
16
16
|
const [localState, setLocalState] = useCachedState(`agent-state-${agentId}`, undefined);
|
17
17
|
const [isLoading, setIsLoading] = useState(true);
|
18
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
19
|
+
const [updatingError, setUpdatingError] = useState(null);
|
18
20
|
const [loadingError, setLoadingError] = useState(null);
|
19
|
-
const
|
21
|
+
const loadedAgentId = useRef(null);
|
20
22
|
const getAgentState = useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
21
23
|
try {
|
22
24
|
const state = yield localClient.agents.retrieve(agentId);
|
@@ -29,17 +31,32 @@ export function useAgentState(options) {
|
|
29
31
|
setIsLoading(false);
|
30
32
|
}
|
31
33
|
}), [agentId, localClient, setLocalState]);
|
34
|
+
const updateAgentState = useCallback((state) => __awaiter(this, void 0, void 0, function* () {
|
35
|
+
setIsUpdating(true);
|
36
|
+
try {
|
37
|
+
const response = yield localClient.agents.modify(agentId, state);
|
38
|
+
setLocalState(response);
|
39
|
+
}
|
40
|
+
catch (error) {
|
41
|
+
setUpdatingError(error);
|
42
|
+
}
|
43
|
+
finally {
|
44
|
+
setIsUpdating(false);
|
45
|
+
}
|
46
|
+
}), [agentId, localClient, setLocalState]);
|
32
47
|
useEffect(() => {
|
33
|
-
if (
|
34
|
-
|
48
|
+
if (agentId !== loadedAgentId.current) {
|
49
|
+
setIsLoading(true);
|
50
|
+
void getAgentState();
|
51
|
+
loadedAgentId.current = agentId;
|
35
52
|
}
|
36
|
-
|
37
|
-
setIsLoading(true);
|
38
|
-
getAgentState();
|
39
|
-
}, []);
|
53
|
+
}, [agentId]);
|
40
54
|
return {
|
41
55
|
isLoading,
|
42
|
-
|
56
|
+
updateAgentState,
|
57
|
+
isUpdating,
|
58
|
+
updatingError,
|
59
|
+
loadingError,
|
43
60
|
agentState: localState,
|
44
61
|
refresh: getAgentState,
|
45
62
|
};
|
package/dist/index.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
export { LettaProvider } from './hooks/useGlobalLettaConfig/useGlobalLettaConfig';
|
2
2
|
export { useAgentMessages } from './hooks/useAgentMessages/useAgentMessages';
|
3
3
|
export { useAgentState } from './hooks/useAgentState/useAgentState';
|
4
|
+
export { useAgentPassages } from './hooks/useAgentPassages/useAgentPassages';
|
package/dist/index.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
export { LettaProvider } from './hooks/useGlobalLettaConfig/useGlobalLettaConfig';
|
2
2
|
export { useAgentMessages } from './hooks/useAgentMessages/useAgentMessages';
|
3
3
|
export { useAgentState } from './hooks/useAgentState/useAgentState';
|
4
|
+
export { useAgentPassages } from './hooks/useAgentPassages/useAgentPassages';
|
@@ -1,7 +1,11 @@
|
|
1
1
|
import React, { FormEvent, useCallback } from 'react';
|
2
2
|
import { useState } from 'react';
|
3
3
|
import './App.css';
|
4
|
-
import {
|
4
|
+
import {
|
5
|
+
useAgentMessages,
|
6
|
+
useAgentPassages,
|
7
|
+
useAgentState,
|
8
|
+
} from '@letta-ai/letta-react';
|
5
9
|
|
6
10
|
function App() {
|
7
11
|
const [messageToSend, setMessageToSend] = useState<string>('');
|
@@ -14,11 +18,15 @@ function App() {
|
|
14
18
|
isSending,
|
15
19
|
sendMessage,
|
16
20
|
} = useAgentMessages({
|
17
|
-
agentId: 'agent-
|
21
|
+
agentId: 'agent-0d07e901-64de-4bbd-8a7c-268ce88bc6cb',
|
22
|
+
});
|
23
|
+
|
24
|
+
const { passages, isLoading: isPassagesLoading } = useAgentPassages({
|
25
|
+
agentId: 'agent-0d07e901-64de-4bbd-8a7c-268ce88bc6cb',
|
18
26
|
});
|
19
27
|
|
20
28
|
const { agentState } = useAgentState({
|
21
|
-
agentId: 'agent-
|
29
|
+
agentId: 'agent-0d07e901-64de-4bbd-8a7c-268ce88bc6cb',
|
22
30
|
});
|
23
31
|
|
24
32
|
const handleSubmit = useCallback(
|
@@ -42,6 +50,16 @@ function App() {
|
|
42
50
|
return (
|
43
51
|
<main>
|
44
52
|
<header>Talking to: {agentState?.name}</header>
|
53
|
+
{isPassagesLoading ? (
|
54
|
+
<div>Loading passages!</div>
|
55
|
+
) : (
|
56
|
+
<ul className="passages">
|
57
|
+
{passages?.map((passage) => (
|
58
|
+
<li key={passage.id}>{passage.text}</li>
|
59
|
+
))}
|
60
|
+
</ul>
|
61
|
+
)}
|
62
|
+
|
45
63
|
{hasOlderMessages && (
|
46
64
|
<button onClick={fetchOlderMessages} disabled={isFetching}>
|
47
65
|
{isFetching ? 'Loading older messages' : 'Load older messages'}
|
@@ -57,7 +75,6 @@ function App() {
|
|
57
75
|
return (
|
58
76
|
<li key={`${message.id}${message.messageType}`}>
|
59
77
|
{message.content}
|
60
|
-
{message.id}
|
61
78
|
</li>
|
62
79
|
);
|
63
80
|
}
|
@@ -46,13 +46,21 @@ function dedupeMessages(messages) {
|
|
46
46
|
return false;
|
47
47
|
}, []);
|
48
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
|
+
}
|
49
57
|
export function useAgentMessages(options) {
|
50
58
|
const { client = {}, method = 'stream', messageOptions = {}, limit = 20, agentId, } = options;
|
51
59
|
const localClient = useLettaClient(client);
|
52
60
|
const [localMessages, setLocalMessages] = useCachedState(`messages-${agentId}`, {
|
53
61
|
messages: [],
|
54
62
|
});
|
55
|
-
const
|
63
|
+
const agentIdMessagesLoadedRef = useRef(false);
|
56
64
|
const [isLoading, setIsLoading] = useState(true);
|
57
65
|
const [isFetching, setIsFetching] = useState(false);
|
58
66
|
const [loadingError, setLoadingError] = useState(null);
|
@@ -60,26 +68,39 @@ export function useAgentMessages(options) {
|
|
60
68
|
const [sendingError, setSendingError] = useState(null);
|
61
69
|
const sendNonStreamedMessage = useCallback(function sendNonStreamedMessage(sendMessagePayload) {
|
62
70
|
return __awaiter(this, void 0, void 0, function* () {
|
71
|
+
let originalMessageState = localMessages;
|
63
72
|
try {
|
64
73
|
setIsSending(true);
|
65
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
|
+
});
|
66
80
|
const response = yield localClient.agents.messages.create(agentId, Object.assign(Object.assign({}, sendMessagePayload), messageOptions));
|
67
|
-
setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...
|
81
|
+
setLocalMessages((prevState) => (Object.assign(Object.assign({}, prevState), { messages: [...prevState.messages, ...response.messages] })));
|
68
82
|
}
|
69
83
|
catch (e) {
|
84
|
+
setLocalMessages(originalMessageState);
|
70
85
|
setSendingError(e);
|
71
86
|
}
|
72
87
|
finally {
|
73
88
|
setIsSending(false);
|
74
89
|
}
|
75
90
|
});
|
76
|
-
}, [localClient]);
|
91
|
+
}, [localClient, localMessages]);
|
77
92
|
const sendStreamedMessage = useCallback(function sendStreamedMessage(sendMessagePayload) {
|
78
93
|
return __awaiter(this, void 0, void 0, function* () {
|
79
94
|
var _a, e_1, _b, _c;
|
95
|
+
let originalMessageState = localMessages;
|
80
96
|
try {
|
81
97
|
setIsSending(true);
|
82
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
|
+
});
|
83
104
|
const response = yield localClient.agents.messages.createStream(agentId, Object.assign(Object.assign(Object.assign({}, sendMessagePayload), messageOptions), { streamTokens: true }));
|
84
105
|
try {
|
85
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) {
|
@@ -167,13 +188,17 @@ export function useAgentMessages(options) {
|
|
167
188
|
});
|
168
189
|
}, [localClient]);
|
169
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
|
+
}
|
170
195
|
if (isSending) {
|
171
196
|
return;
|
172
197
|
}
|
173
198
|
if (method === 'stream') {
|
174
|
-
return sendStreamedMessage(
|
199
|
+
return sendStreamedMessage(filteredPayload);
|
175
200
|
}
|
176
|
-
return sendNonStreamedMessage(
|
201
|
+
return sendNonStreamedMessage(filteredPayload);
|
177
202
|
}, [method, isSending, sendStreamedMessage, sendNonStreamedMessage]);
|
178
203
|
const getMessages = useCallback(function getMessages(before) {
|
179
204
|
return __awaiter(this, void 0, void 0, function* () {
|
@@ -205,12 +230,11 @@ export function useAgentMessages(options) {
|
|
205
230
|
return getMessages(nextCursor);
|
206
231
|
}), [getMessages]);
|
207
232
|
useEffect(() => {
|
208
|
-
if (
|
209
|
-
|
233
|
+
if (!agentIdMessagesLoadedRef.current) {
|
234
|
+
setIsLoading(true);
|
235
|
+
void getMessages();
|
236
|
+
agentIdMessagesLoadedRef.current = true;
|
210
237
|
}
|
211
|
-
hasInitialLoaded.current = true;
|
212
|
-
setIsLoading(true);
|
213
|
-
getMessages();
|
214
238
|
}, []);
|
215
239
|
return {
|
216
240
|
messages: localMessages.messages,
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import type { Passage } from '@letta-ai/letta-client/api';
|
2
|
+
import type { LettaClient } from '@letta-ai/letta-client';
|
3
|
+
interface UseAgentStateOptions {
|
4
|
+
client?: LettaClient.Options;
|
5
|
+
agentId: string;
|
6
|
+
}
|
7
|
+
export declare function useAgentPassages(options: UseAgentStateOptions): {
|
8
|
+
isLoading: boolean;
|
9
|
+
isLoadingError: unknown;
|
10
|
+
passages: Passage[] | undefined;
|
11
|
+
refresh: () => Promise<void>;
|
12
|
+
};
|
13
|
+
export {};
|
@@ -0,0 +1,45 @@
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
|
+
});
|
9
|
+
};
|
10
|
+
import { useLettaClient } from '../useLettaClient/useLettaClient';
|
11
|
+
import { useCachedState } from '../useCachedState/useCachedState';
|
12
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
13
|
+
export function useAgentPassages(options) {
|
14
|
+
const { client, agentId } = options;
|
15
|
+
const localClient = useLettaClient(client);
|
16
|
+
const loadedAgentId = useRef(null);
|
17
|
+
const [localState, setLocalState] = useCachedState(`agent-passages-${agentId}`, undefined);
|
18
|
+
const [isLoading, setIsLoading] = useState(true);
|
19
|
+
const [isLoadingError, setIsLoadingError] = useState(null);
|
20
|
+
const getAgentPassages = useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
21
|
+
try {
|
22
|
+
const state = yield localClient.agents.passages.list(agentId);
|
23
|
+
setLocalState(state);
|
24
|
+
}
|
25
|
+
catch (error) {
|
26
|
+
setIsLoadingError(error);
|
27
|
+
}
|
28
|
+
finally {
|
29
|
+
setIsLoading(false);
|
30
|
+
}
|
31
|
+
}), [agentId, localClient, setLocalState]);
|
32
|
+
useEffect(() => {
|
33
|
+
if (agentId !== loadedAgentId.current) {
|
34
|
+
setIsLoading(true);
|
35
|
+
void getAgentPassages();
|
36
|
+
loadedAgentId.current = agentId;
|
37
|
+
}
|
38
|
+
}, [agentId, getAgentPassages]);
|
39
|
+
return {
|
40
|
+
isLoading,
|
41
|
+
isLoadingError,
|
42
|
+
passages: localState,
|
43
|
+
refresh: getAgentPassages,
|
44
|
+
};
|
45
|
+
}
|
@@ -1,12 +1,15 @@
|
|
1
1
|
import type { LettaClient } from '@letta-ai/letta-client';
|
2
|
-
import type { AgentState } from '@letta-ai/letta-client/api';
|
2
|
+
import type { AgentState, UpdateAgent } from '@letta-ai/letta-client/api';
|
3
3
|
interface UseAgentStateOptions {
|
4
4
|
client?: LettaClient.Options;
|
5
5
|
agentId: string;
|
6
6
|
}
|
7
7
|
export declare function useAgentState(options: UseAgentStateOptions): {
|
8
8
|
isLoading: boolean;
|
9
|
-
|
9
|
+
updateAgentState: (state: Partial<UpdateAgent>) => Promise<void>;
|
10
|
+
isUpdating: boolean;
|
11
|
+
updatingError: unknown;
|
12
|
+
loadingError: unknown;
|
10
13
|
agentState: AgentState | undefined;
|
11
14
|
refresh: () => Promise<void>;
|
12
15
|
};
|
@@ -15,8 +15,10 @@ export function useAgentState(options) {
|
|
15
15
|
const localClient = useLettaClient(client);
|
16
16
|
const [localState, setLocalState] = useCachedState(`agent-state-${agentId}`, undefined);
|
17
17
|
const [isLoading, setIsLoading] = useState(true);
|
18
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
19
|
+
const [updatingError, setUpdatingError] = useState(null);
|
18
20
|
const [loadingError, setLoadingError] = useState(null);
|
19
|
-
const
|
21
|
+
const loadedAgentId = useRef(null);
|
20
22
|
const getAgentState = useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
21
23
|
try {
|
22
24
|
const state = yield localClient.agents.retrieve(agentId);
|
@@ -29,17 +31,32 @@ export function useAgentState(options) {
|
|
29
31
|
setIsLoading(false);
|
30
32
|
}
|
31
33
|
}), [agentId, localClient, setLocalState]);
|
34
|
+
const updateAgentState = useCallback((state) => __awaiter(this, void 0, void 0, function* () {
|
35
|
+
setIsUpdating(true);
|
36
|
+
try {
|
37
|
+
const response = yield localClient.agents.modify(agentId, state);
|
38
|
+
setLocalState(response);
|
39
|
+
}
|
40
|
+
catch (error) {
|
41
|
+
setUpdatingError(error);
|
42
|
+
}
|
43
|
+
finally {
|
44
|
+
setIsUpdating(false);
|
45
|
+
}
|
46
|
+
}), [agentId, localClient, setLocalState]);
|
32
47
|
useEffect(() => {
|
33
|
-
if (
|
34
|
-
|
48
|
+
if (agentId !== loadedAgentId.current) {
|
49
|
+
setIsLoading(true);
|
50
|
+
void getAgentState();
|
51
|
+
loadedAgentId.current = agentId;
|
35
52
|
}
|
36
|
-
|
37
|
-
setIsLoading(true);
|
38
|
-
getAgentState();
|
39
|
-
}, []);
|
53
|
+
}, [agentId]);
|
40
54
|
return {
|
41
55
|
isLoading,
|
42
|
-
|
56
|
+
updateAgentState,
|
57
|
+
isUpdating,
|
58
|
+
updatingError,
|
59
|
+
loadingError,
|
43
60
|
agentState: localState,
|
44
61
|
refresh: getAgentState,
|
45
62
|
};
|
package/index.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
export { LettaProvider } from './hooks/useGlobalLettaConfig/useGlobalLettaConfig';
|
2
2
|
export { useAgentMessages } from './hooks/useAgentMessages/useAgentMessages';
|
3
3
|
export { useAgentState } from './hooks/useAgentState/useAgentState';
|
4
|
+
export { useAgentPassages } from './hooks/useAgentPassages/useAgentPassages';
|
package/index.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
export { LettaProvider } from './hooks/useGlobalLettaConfig/useGlobalLettaConfig';
|
2
2
|
export { useAgentMessages } from './hooks/useAgentMessages/useAgentMessages';
|
3
3
|
export { useAgentState } from './hooks/useAgentState/useAgentState';
|
4
|
+
export { useAgentPassages } from './hooks/useAgentPassages/useAgentPassages';
|
package/package.json
CHANGED
@@ -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;
|
@@ -52,6 +53,17 @@ function dedupeMessages(
|
|
52
53
|
}, []);
|
53
54
|
}
|
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
|
+
|
55
67
|
interface SendMessagePayload {
|
56
68
|
messages: LettaRequest['messages'];
|
57
69
|
}
|
@@ -73,7 +85,7 @@ export function useAgentMessages(options: UseAgentOptions) {
|
|
73
85
|
}
|
74
86
|
);
|
75
87
|
|
76
|
-
const
|
88
|
+
const agentIdMessagesLoadedRef = useRef(false);
|
77
89
|
|
78
90
|
const [isLoading, setIsLoading] = useState(true);
|
79
91
|
const [isFetching, setIsFetching] = useState(false);
|
@@ -86,10 +98,24 @@ export function useAgentMessages(options: UseAgentOptions) {
|
|
86
98
|
async function sendNonStreamedMessage(
|
87
99
|
sendMessagePayload: SendMessagePayload
|
88
100
|
) {
|
101
|
+
let originalMessageState: LocalMessagesState = localMessages;
|
89
102
|
try {
|
90
103
|
setIsSending(true);
|
91
104
|
setSendingError(null);
|
92
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
|
+
|
93
119
|
const response = await localClient.agents.messages.create(agentId, {
|
94
120
|
...sendMessagePayload,
|
95
121
|
...messageOptions,
|
@@ -97,23 +123,39 @@ export function useAgentMessages(options: UseAgentOptions) {
|
|
97
123
|
|
98
124
|
setLocalMessages((prevState) => ({
|
99
125
|
...prevState,
|
100
|
-
messages: [...
|
126
|
+
messages: [...prevState.messages, ...response.messages],
|
101
127
|
}));
|
102
128
|
} catch (e) {
|
129
|
+
setLocalMessages(originalMessageState);
|
103
130
|
setSendingError(e);
|
104
131
|
} finally {
|
105
132
|
setIsSending(false);
|
106
133
|
}
|
107
134
|
},
|
108
|
-
[localClient]
|
135
|
+
[localClient, localMessages]
|
109
136
|
);
|
110
137
|
|
111
138
|
const sendStreamedMessage = useCallback(
|
112
139
|
async function sendStreamedMessage(sendMessagePayload: SendMessagePayload) {
|
140
|
+
let originalMessageState: LocalMessagesState = localMessages;
|
141
|
+
|
113
142
|
try {
|
114
143
|
setIsSending(true);
|
115
144
|
setSendingError(null);
|
116
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
|
+
|
117
159
|
const response = await localClient.agents.messages.createStream(
|
118
160
|
agentId,
|
119
161
|
{
|
@@ -262,15 +304,24 @@ export function useAgentMessages(options: UseAgentOptions) {
|
|
262
304
|
|
263
305
|
const sendMessage = useCallback(
|
264
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
|
+
|
265
316
|
if (isSending) {
|
266
317
|
return;
|
267
318
|
}
|
268
319
|
|
269
320
|
if (method === 'stream') {
|
270
|
-
return sendStreamedMessage(
|
321
|
+
return sendStreamedMessage(filteredPayload);
|
271
322
|
}
|
272
323
|
|
273
|
-
return sendNonStreamedMessage(
|
324
|
+
return sendNonStreamedMessage(filteredPayload);
|
274
325
|
},
|
275
326
|
[method, isSending, sendStreamedMessage, sendNonStreamedMessage]
|
276
327
|
);
|
@@ -320,15 +371,11 @@ export function useAgentMessages(options: UseAgentOptions) {
|
|
320
371
|
}, [getMessages]);
|
321
372
|
|
322
373
|
useEffect(() => {
|
323
|
-
if (
|
324
|
-
|
374
|
+
if (!agentIdMessagesLoadedRef.current) {
|
375
|
+
setIsLoading(true);
|
376
|
+
void getMessages();
|
377
|
+
agentIdMessagesLoadedRef.current = true;
|
325
378
|
}
|
326
|
-
|
327
|
-
hasInitialLoaded.current = true;
|
328
|
-
|
329
|
-
setIsLoading(true);
|
330
|
-
|
331
|
-
getMessages();
|
332
379
|
}, []);
|
333
380
|
|
334
381
|
return {
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { useLettaClient } from '../useLettaClient/useLettaClient';
|
2
|
+
import { useCachedState } from '../useCachedState/useCachedState';
|
3
|
+
import type { AgentState, Passage } from '@letta-ai/letta-client/api';
|
4
|
+
import type { LettaClient } from '@letta-ai/letta-client';
|
5
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
6
|
+
|
7
|
+
interface UseAgentStateOptions {
|
8
|
+
client?: LettaClient.Options;
|
9
|
+
agentId: string;
|
10
|
+
}
|
11
|
+
|
12
|
+
export function useAgentPassages(options: UseAgentStateOptions) {
|
13
|
+
const { client, agentId } = options;
|
14
|
+
const localClient = useLettaClient(client);
|
15
|
+
const loadedAgentId = useRef<string | null>(null);
|
16
|
+
|
17
|
+
const [localState, setLocalState] = useCachedState<Passage[] | undefined>(
|
18
|
+
`agent-passages-${agentId}`,
|
19
|
+
undefined
|
20
|
+
);
|
21
|
+
|
22
|
+
const [isLoading, setIsLoading] = useState(true);
|
23
|
+
const [isLoadingError, setIsLoadingError] = useState<unknown | null>(null);
|
24
|
+
|
25
|
+
const getAgentPassages = useCallback(async () => {
|
26
|
+
try {
|
27
|
+
const state = await localClient.agents.passages.list(agentId);
|
28
|
+
|
29
|
+
setLocalState(state);
|
30
|
+
} catch (error) {
|
31
|
+
setIsLoadingError(error);
|
32
|
+
} finally {
|
33
|
+
setIsLoading(false);
|
34
|
+
}
|
35
|
+
}, [agentId, localClient, setLocalState]);
|
36
|
+
|
37
|
+
useEffect(() => {
|
38
|
+
if (agentId !== loadedAgentId.current) {
|
39
|
+
setIsLoading(true);
|
40
|
+
void getAgentPassages();
|
41
|
+
loadedAgentId.current = agentId;
|
42
|
+
}
|
43
|
+
}, [agentId, getAgentPassages]);
|
44
|
+
|
45
|
+
return {
|
46
|
+
isLoading,
|
47
|
+
isLoadingError,
|
48
|
+
passages: localState,
|
49
|
+
refresh: getAgentPassages,
|
50
|
+
};
|
51
|
+
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { useLettaClient } from '../useLettaClient/useLettaClient';
|
2
2
|
import type { LettaClient } from '@letta-ai/letta-client';
|
3
3
|
import { useCachedState } from '../useCachedState/useCachedState';
|
4
|
-
import type { AgentState } from '@letta-ai/letta-client/api';
|
4
|
+
import type { AgentState, UpdateAgent } from '@letta-ai/letta-client/api';
|
5
5
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
6
6
|
|
7
7
|
interface UseAgentStateOptions {
|
@@ -19,8 +19,10 @@ export function useAgentState(options: UseAgentStateOptions) {
|
|
19
19
|
);
|
20
20
|
|
21
21
|
const [isLoading, setIsLoading] = useState(true);
|
22
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
23
|
+
const [updatingError, setUpdatingError] = useState<unknown | null>(null);
|
22
24
|
const [loadingError, setLoadingError] = useState<unknown | null>(null);
|
23
|
-
const
|
25
|
+
const loadedAgentId = useRef<string | null>(null);
|
24
26
|
|
25
27
|
const getAgentState = useCallback(async () => {
|
26
28
|
try {
|
@@ -34,21 +36,36 @@ export function useAgentState(options: UseAgentStateOptions) {
|
|
34
36
|
}
|
35
37
|
}, [agentId, localClient, setLocalState]);
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
hasInitialLoaded.current = true;
|
39
|
+
const updateAgentState = useCallback(
|
40
|
+
async (state: Partial<UpdateAgent>) => {
|
41
|
+
setIsUpdating(true);
|
42
|
+
try {
|
43
|
+
const response = await localClient.agents.modify(agentId, state);
|
43
44
|
|
44
|
-
|
45
|
+
setLocalState(response);
|
46
|
+
} catch (error) {
|
47
|
+
setUpdatingError(error);
|
48
|
+
} finally {
|
49
|
+
setIsUpdating(false);
|
50
|
+
}
|
51
|
+
},
|
52
|
+
[agentId, localClient, setLocalState]
|
53
|
+
);
|
45
54
|
|
46
|
-
|
47
|
-
|
55
|
+
useEffect(() => {
|
56
|
+
if (agentId !== loadedAgentId.current) {
|
57
|
+
setIsLoading(true);
|
58
|
+
void getAgentState();
|
59
|
+
loadedAgentId.current = agentId;
|
60
|
+
}
|
61
|
+
}, [agentId]);
|
48
62
|
|
49
63
|
return {
|
50
64
|
isLoading,
|
51
|
-
|
65
|
+
updateAgentState,
|
66
|
+
isUpdating,
|
67
|
+
updatingError,
|
68
|
+
loadingError,
|
52
69
|
agentState: localState,
|
53
70
|
refresh: getAgentState,
|
54
71
|
};
|
package/src/index.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
export { LettaProvider } from './hooks/useGlobalLettaConfig/useGlobalLettaConfig';
|
2
2
|
export { useAgentMessages } from './hooks/useAgentMessages/useAgentMessages';
|
3
3
|
export { useAgentState } from './hooks/useAgentState/useAgentState';
|
4
|
+
export { useAgentPassages } from './hooks/useAgentPassages/useAgentPassages';
|