lemma-sdk 0.2.24 → 0.2.27
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/README.md +175 -506
- package/dist/browser/lemma-client.js +207 -12
- package/dist/client.d.ts +2 -0
- package/dist/client.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/namespaces/pod-join-requests.d.ts +16 -0
- package/dist/namespaces/pod-join-requests.js +24 -0
- package/dist/namespaces/pod-members.d.ts +1 -0
- package/dist/namespaces/pod-members.js +3 -0
- package/dist/openapi_client/index.d.ts +10 -3
- package/dist/openapi_client/index.js +4 -2
- package/dist/openapi_client/models/ColumnSchema.d.ts +4 -0
- package/dist/openapi_client/models/CreateTableRequest.d.ts +1 -1
- package/dist/openapi_client/models/DataStoreFlowStart.d.ts +3 -6
- package/dist/openapi_client/models/DatastoreOperation.d.ts +5 -0
- package/dist/openapi_client/models/DatastoreOperation.js +10 -0
- package/dist/openapi_client/models/DatastoreQueryRequest.d.ts +1 -1
- package/dist/openapi_client/models/FlowInstallEntity.d.ts +2 -2
- package/dist/openapi_client/models/FlowResponse.d.ts +4 -3
- package/dist/openapi_client/models/{FlowStart.d.ts → FlowStart_Input.d.ts} +1 -1
- package/dist/openapi_client/models/FlowStart_Output.d.ts +14 -0
- package/dist/openapi_client/models/FlowStart_Output.js +1 -0
- package/dist/openapi_client/models/PodCreateRequest.d.ts +0 -4
- package/dist/openapi_client/models/PodJoinRequestApproveRequest.d.ts +6 -0
- package/dist/openapi_client/models/PodJoinRequestApproveRequest.js +1 -0
- package/dist/openapi_client/models/PodJoinRequestCreateResponse.d.ts +17 -0
- package/dist/openapi_client/models/PodJoinRequestCreateResponse.js +1 -0
- package/dist/openapi_client/models/PodJoinRequestListResponse.d.ts +7 -0
- package/dist/openapi_client/models/PodJoinRequestListResponse.js +1 -0
- package/dist/openapi_client/models/PodJoinRequestStatus.d.ts +5 -0
- package/dist/openapi_client/models/PodJoinRequestStatus.js +10 -0
- package/dist/openapi_client/models/PodMemberDetailResponse.d.ts +14 -0
- package/dist/openapi_client/models/PodMemberDetailResponse.js +1 -0
- package/dist/openapi_client/models/PodMemberResponse.d.ts +3 -3
- package/dist/openapi_client/models/PodResponse.d.ts +0 -5
- package/dist/openapi_client/models/PodUpdateRequest.d.ts +0 -4
- package/dist/openapi_client/models/WorkflowCreateRequest.d.ts +7 -6
- package/dist/openapi_client/models/WorkflowGraphUpdateRequest.d.ts +2 -2
- package/dist/openapi_client/models/WorkflowInstallMode.d.ts +7 -0
- package/dist/openapi_client/models/WorkflowInstallMode.js +12 -0
- package/dist/openapi_client/models/WorkflowUpdateRequest.d.ts +5 -4
- package/dist/openapi_client/services/FilesService.d.ts +1 -1
- package/dist/openapi_client/services/FilesService.js +1 -1
- package/dist/openapi_client/services/PodJoinRequestsService.d.ts +44 -0
- package/dist/openapi_client/services/PodJoinRequestsService.js +93 -0
- package/dist/openapi_client/services/PodMembersService.d.ts +14 -4
- package/dist/openapi_client/services/PodMembersService.js +29 -8
- package/dist/openapi_client/services/RecordsService.d.ts +2 -2
- package/dist/openapi_client/services/RecordsService.js +2 -2
- package/dist/openapi_client/services/WorkflowsService.d.ts +1 -1
- package/dist/openapi_client/services/WorkflowsService.js +1 -1
- package/dist/react/AuthGuard.d.ts +5 -2
- package/dist/react/AuthGuard.js +126 -3
- package/dist/react/components/AssistantChrome.js +1 -1
- package/dist/react/components/AssistantExperience.d.ts +7 -2
- package/dist/react/components/AssistantExperience.js +272 -32
- package/dist/react/components/assistant-types.d.ts +1 -0
- package/dist/react/index.d.ts +0 -2
- package/dist/react/index.js +0 -1
- package/dist/react/styles.css +594 -224
- package/dist/react/useAssistantController.js +2 -1
- package/dist/react/useAssistantRuntime.d.ts +2 -1
- package/dist/react/useAssistantRuntime.js +7 -3
- package/dist/react/useTaskSession.js +145 -73
- package/dist/task-events.d.ts +2 -1
- package/dist/task-events.js +38 -1
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
- package/dist/openapi_client/models/PodStatus.d.ts +0 -4
- package/dist/openapi_client/models/PodStatus.js +0 -9
- package/dist/openapi_client/models/PodType.d.ts +0 -6
- package/dist/openapi_client/models/PodType.js +0 -11
- package/dist/react/useAgentRun.d.ts +0 -17
- package/dist/react/useAgentRun.js +0 -66
- /package/dist/openapi_client/models/{FlowStart.js → FlowStart_Input.js} +0 -0
|
@@ -584,9 +584,10 @@ export function useAssistantController({ client, podId, assistantName, assistant
|
|
|
584
584
|
autoLoad: false,
|
|
585
585
|
onError: handleAssistantSessionError,
|
|
586
586
|
});
|
|
587
|
-
const { listConversations: sessionListConversations, loadMessages: sessionLoadMessages, sendMessage: sessionSendMessage, createConversation: sessionCreateConversation, resumeIfRunning: sessionResumeIfRunning, stop: sessionStop, cancel: sessionCancel, isStreaming: sessionIsStreaming, messages: sessionMessages, streamingText: sessionStreamingText, status: sessionStatus, } = assistantSession;
|
|
587
|
+
const { conversationId: sessionConversationId, listConversations: sessionListConversations, loadMessages: sessionLoadMessages, sendMessage: sessionSendMessage, createConversation: sessionCreateConversation, resumeIfRunning: sessionResumeIfRunning, stop: sessionStop, cancel: sessionCancel, isStreaming: sessionIsStreaming, messages: sessionMessages, streamingText: sessionStreamingText, status: sessionStatus, } = assistantSession;
|
|
588
588
|
const { runtimeMessages, appendOptimisticUserMessage, replaceLoadedMessages, mergeMessages, clear: clearRuntimeMessages, } = useAssistantRuntime({
|
|
589
589
|
conversationId: activeConversationId,
|
|
590
|
+
sessionConversationId,
|
|
590
591
|
sessionMessages,
|
|
591
592
|
});
|
|
592
593
|
const error = localError;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ConversationMessage } from "../types.js";
|
|
2
2
|
export interface UseAssistantRuntimeOptions {
|
|
3
3
|
conversationId?: string | null;
|
|
4
|
+
sessionConversationId?: string | null;
|
|
4
5
|
sessionMessages?: ConversationMessage[];
|
|
5
6
|
}
|
|
6
7
|
export interface UseAssistantRuntimeResult {
|
|
@@ -12,4 +13,4 @@ export interface UseAssistantRuntimeResult {
|
|
|
12
13
|
mergeMessages: (messages: ConversationMessage[]) => void;
|
|
13
14
|
clear: () => void;
|
|
14
15
|
}
|
|
15
|
-
export declare function useAssistantRuntime({ conversationId, sessionMessages, }: UseAssistantRuntimeOptions): UseAssistantRuntimeResult;
|
|
16
|
+
export declare function useAssistantRuntime({ conversationId, sessionConversationId, sessionMessages, }: UseAssistantRuntimeOptions): UseAssistantRuntimeResult;
|
|
@@ -73,7 +73,7 @@ function buildOptimisticId() {
|
|
|
73
73
|
}
|
|
74
74
|
return `optimistic-user-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
75
75
|
}
|
|
76
|
-
export function useAssistantRuntime({ conversationId = null, sessionMessages = [], }) {
|
|
76
|
+
export function useAssistantRuntime({ conversationId = null, sessionConversationId = null, sessionMessages = [], }) {
|
|
77
77
|
const [runtimeMessages, setRuntimeMessages] = useState([]);
|
|
78
78
|
const mergeMessages = useCallback((messages) => {
|
|
79
79
|
setRuntimeMessages((previous) => {
|
|
@@ -125,13 +125,17 @@ export function useAssistantRuntime({ conversationId = null, sessionMessages = [
|
|
|
125
125
|
useEffect(() => {
|
|
126
126
|
if (sessionMessages.length === 0)
|
|
127
127
|
return;
|
|
128
|
+
// Session message state can lag one render behind active conversation
|
|
129
|
+
// updates. Prefer the session's own conversation id as fallback so we
|
|
130
|
+
// never relabel stale messages into the newly selected thread.
|
|
131
|
+
const fallbackConversationId = sessionConversationId ?? conversationId;
|
|
128
132
|
const normalized = sessionMessages
|
|
129
|
-
.map((message) => toRuntimeMessage(message,
|
|
133
|
+
.map((message) => toRuntimeMessage(message, fallbackConversationId))
|
|
130
134
|
.filter((message) => !conversationId || message.conversation_id === conversationId);
|
|
131
135
|
if (normalized.length === 0)
|
|
132
136
|
return;
|
|
133
137
|
mergeMessages(normalized);
|
|
134
|
-
}, [conversationId, mergeMessages, sessionMessages]);
|
|
138
|
+
}, [conversationId, mergeMessages, sessionConversationId, sessionMessages]);
|
|
135
139
|
return {
|
|
136
140
|
runtimeMessages,
|
|
137
141
|
appendOptimisticUserMessage,
|
|
@@ -14,6 +14,9 @@ function normalizeError(error, fallback) {
|
|
|
14
14
|
return error;
|
|
15
15
|
return new Error(fallback);
|
|
16
16
|
}
|
|
17
|
+
function sleep(ms) {
|
|
18
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
|
+
}
|
|
17
20
|
export function useTaskSession({ client, podId, taskId: externalTaskId = null, autoConnect = true, autoConnectOnStart = true, onEvent, onStatus, onMessage, onError, }) {
|
|
18
21
|
const [taskId, setTaskIdState] = useState(externalTaskId);
|
|
19
22
|
const [task, setTask] = useState(null);
|
|
@@ -22,53 +25,88 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
22
25
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
23
26
|
const [error, setError] = useState(null);
|
|
24
27
|
const abortRef = useRef(null);
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
const previousExternalTaskIdRef = useRef(externalTaskId);
|
|
29
|
+
const taskIdRef = useRef(externalTaskId);
|
|
30
|
+
const statusRef = useRef(undefined);
|
|
31
|
+
const onEventRef = useRef(onEvent);
|
|
32
|
+
const onStatusRef = useRef(onStatus);
|
|
33
|
+
const onMessageRef = useRef(onMessage);
|
|
34
|
+
const onErrorRef = useRef(onError);
|
|
35
|
+
const setTaskStatus = useCallback((nextStatus) => {
|
|
36
|
+
const normalized = normalizeRunStatus(nextStatus);
|
|
37
|
+
setStatus(normalized);
|
|
38
|
+
statusRef.current = normalized;
|
|
39
|
+
if (normalized) {
|
|
40
|
+
onStatusRef.current?.(normalized);
|
|
31
41
|
}
|
|
32
42
|
}, []);
|
|
43
|
+
const setTaskId = useCallback((nextTaskId) => {
|
|
44
|
+
abortRef.current?.abort();
|
|
45
|
+
abortRef.current = null;
|
|
46
|
+
setTaskIdState((currentTaskId) => {
|
|
47
|
+
if (currentTaskId === nextTaskId) {
|
|
48
|
+
return currentTaskId;
|
|
49
|
+
}
|
|
50
|
+
setError(null);
|
|
51
|
+
setIsStreaming(false);
|
|
52
|
+
if (!nextTaskId) {
|
|
53
|
+
setTask(null);
|
|
54
|
+
setTaskStatus(undefined);
|
|
55
|
+
setMessages([]);
|
|
56
|
+
}
|
|
57
|
+
return nextTaskId;
|
|
58
|
+
});
|
|
59
|
+
}, [setTaskStatus]);
|
|
33
60
|
const disconnect = useCallback(() => {
|
|
34
61
|
abortRef.current?.abort();
|
|
35
62
|
abortRef.current = null;
|
|
63
|
+
setIsStreaming(false);
|
|
36
64
|
}, []);
|
|
37
65
|
useEffect(() => {
|
|
38
|
-
|
|
66
|
+
taskIdRef.current = taskId;
|
|
67
|
+
}, [taskId]);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
statusRef.current = status;
|
|
70
|
+
}, [status]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
onEventRef.current = onEvent;
|
|
73
|
+
}, [onEvent]);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
onStatusRef.current = onStatus;
|
|
76
|
+
}, [onStatus]);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
onMessageRef.current = onMessage;
|
|
79
|
+
}, [onMessage]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
onErrorRef.current = onError;
|
|
82
|
+
}, [onError]);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (previousExternalTaskIdRef.current === externalTaskId) {
|
|
39
85
|
return;
|
|
40
|
-
setTaskIdState(externalTaskId);
|
|
41
|
-
if (!externalTaskId) {
|
|
42
|
-
disconnect();
|
|
43
|
-
setTask(null);
|
|
44
|
-
setStatus(undefined);
|
|
45
|
-
setMessages([]);
|
|
46
86
|
}
|
|
47
|
-
|
|
87
|
+
previousExternalTaskIdRef.current = externalTaskId;
|
|
88
|
+
setTaskId(externalTaskId);
|
|
89
|
+
}, [externalTaskId, setTaskId]);
|
|
48
90
|
const refreshTask = useCallback(async (explicitTaskId) => {
|
|
49
|
-
const id = explicitTaskId ??
|
|
91
|
+
const id = explicitTaskId ?? taskIdRef.current;
|
|
50
92
|
if (!id)
|
|
51
93
|
return null;
|
|
52
94
|
try {
|
|
53
95
|
client.setPodId(resolvePodId(client, podId));
|
|
54
96
|
const nextTask = await client.tasks.get(id);
|
|
55
97
|
setTask(nextTask);
|
|
56
|
-
|
|
57
|
-
setStatus(nextStatus);
|
|
58
|
-
if (nextStatus) {
|
|
59
|
-
onStatus?.(nextStatus);
|
|
60
|
-
}
|
|
98
|
+
setTaskStatus(nextTask.status);
|
|
61
99
|
return nextTask;
|
|
62
100
|
}
|
|
63
101
|
catch (refreshError) {
|
|
64
102
|
const normalized = normalizeError(refreshError, "Failed to fetch task.");
|
|
65
103
|
setError(normalized);
|
|
66
|
-
|
|
104
|
+
onErrorRef.current?.(refreshError);
|
|
67
105
|
return null;
|
|
68
106
|
}
|
|
69
|
-
}, [client,
|
|
107
|
+
}, [client, podId, setTaskStatus]);
|
|
70
108
|
const loadMessages = useCallback(async (explicitTaskId) => {
|
|
71
|
-
const id = explicitTaskId ??
|
|
109
|
+
const id = explicitTaskId ?? taskIdRef.current;
|
|
72
110
|
if (!id)
|
|
73
111
|
return [];
|
|
74
112
|
try {
|
|
@@ -81,57 +119,86 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
81
119
|
catch (messageError) {
|
|
82
120
|
const normalized = normalizeError(messageError, "Failed to fetch task messages.");
|
|
83
121
|
setError(normalized);
|
|
84
|
-
|
|
122
|
+
onErrorRef.current?.(messageError);
|
|
85
123
|
return [];
|
|
86
124
|
}
|
|
87
|
-
}, [client,
|
|
125
|
+
}, [client, podId]);
|
|
88
126
|
const connect = useCallback(async (explicitTaskId) => {
|
|
89
|
-
const id = explicitTaskId ??
|
|
127
|
+
const id = explicitTaskId ?? taskIdRef.current;
|
|
90
128
|
if (!id)
|
|
91
129
|
return;
|
|
92
130
|
setTaskIdState(id);
|
|
131
|
+
taskIdRef.current = id;
|
|
93
132
|
disconnect();
|
|
94
133
|
const controller = new AbortController();
|
|
95
134
|
abortRef.current = controller;
|
|
96
135
|
setError(null);
|
|
97
136
|
setIsStreaming(true);
|
|
137
|
+
let reconnectDelayMs = 1000;
|
|
98
138
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
for await (const event of readSSE(stream)) {
|
|
102
|
-
if (controller.signal.aborted) {
|
|
139
|
+
while (!controller.signal.aborted) {
|
|
140
|
+
if (isTerminalTaskStatus(statusRef.current)) {
|
|
103
141
|
break;
|
|
104
142
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
143
|
+
try {
|
|
144
|
+
client.setPodId(resolvePodId(client, podId));
|
|
145
|
+
const stream = await client.tasks.stream(id, { signal: controller.signal });
|
|
146
|
+
reconnectDelayMs = 1000;
|
|
147
|
+
for await (const event of readSSE(stream)) {
|
|
148
|
+
if (controller.signal.aborted) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
const payload = parseSSEJson(event);
|
|
152
|
+
onEventRef.current?.(event, payload);
|
|
153
|
+
const parsed = parseTaskStreamEvent(payload);
|
|
154
|
+
if (parsed.task?.id === id) {
|
|
155
|
+
setTask(parsed.task);
|
|
156
|
+
setTaskStatus(parsed.task.status);
|
|
157
|
+
}
|
|
158
|
+
if (parsed.message) {
|
|
159
|
+
setMessages((previous) => upsertTaskMessage(previous, parsed.message));
|
|
160
|
+
onMessageRef.current?.(parsed.message);
|
|
161
|
+
}
|
|
162
|
+
if (parsed.status) {
|
|
163
|
+
setTaskStatus(parsed.status);
|
|
164
|
+
setTask((previous) => {
|
|
165
|
+
if (!previous || previous.id !== id)
|
|
166
|
+
return previous;
|
|
167
|
+
return {
|
|
168
|
+
...previous,
|
|
169
|
+
status: parsed.status,
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (isTerminalTaskStatus(statusRef.current)) {
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (controller.signal.aborted || isTerminalTaskStatus(statusRef.current)) {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
await sleep(Math.max(reconnectDelayMs, 2000));
|
|
181
|
+
reconnectDelayMs = Math.min(Math.max(reconnectDelayMs * 2, 2000), 6000);
|
|
111
182
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
onStatus?.(parsed.status);
|
|
115
|
-
if (isTerminalTaskStatus(parsed.status)) {
|
|
183
|
+
catch (streamError) {
|
|
184
|
+
if (streamError instanceof Error && streamError.name === "AbortError") {
|
|
116
185
|
break;
|
|
117
186
|
}
|
|
187
|
+
const normalized = normalizeError(streamError, "Failed to stream task run.");
|
|
188
|
+
setError(normalized);
|
|
189
|
+
onErrorRef.current?.(streamError);
|
|
190
|
+
await sleep(reconnectDelayMs);
|
|
191
|
+
reconnectDelayMs = Math.min(reconnectDelayMs * 2, 6000);
|
|
118
192
|
}
|
|
119
193
|
}
|
|
120
194
|
}
|
|
121
|
-
catch (streamError) {
|
|
122
|
-
if (!(streamError instanceof Error && streamError.name === "AbortError")) {
|
|
123
|
-
const normalized = normalizeError(streamError, "Failed to stream task run.");
|
|
124
|
-
setError(normalized);
|
|
125
|
-
onError?.(streamError);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
195
|
finally {
|
|
129
196
|
if (abortRef.current === controller) {
|
|
130
197
|
abortRef.current = null;
|
|
131
198
|
}
|
|
132
199
|
setIsStreaming(false);
|
|
133
200
|
}
|
|
134
|
-
}, [client, disconnect,
|
|
201
|
+
}, [client, disconnect, podId, setTaskStatus]);
|
|
135
202
|
const start = useCallback(async (input) => {
|
|
136
203
|
setError(null);
|
|
137
204
|
client.setPodId(resolvePodId(client, podId));
|
|
@@ -139,55 +206,60 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
139
206
|
agent_name: input.agentName,
|
|
140
207
|
input_data: input.inputData,
|
|
141
208
|
});
|
|
209
|
+
taskIdRef.current = created.id;
|
|
142
210
|
setTask(created);
|
|
143
211
|
setTaskIdState(created.id);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (nextStatus) {
|
|
147
|
-
onStatus?.(nextStatus);
|
|
148
|
-
}
|
|
212
|
+
setMessages([]);
|
|
213
|
+
setTaskStatus(created.status);
|
|
149
214
|
if (autoConnectOnStart && !autoConnect) {
|
|
150
215
|
await connect(created.id);
|
|
151
216
|
}
|
|
152
217
|
return created;
|
|
153
|
-
}, [autoConnect, autoConnectOnStart, client, connect,
|
|
218
|
+
}, [autoConnect, autoConnectOnStart, client, connect, podId, setTaskStatus]);
|
|
154
219
|
const stop = useCallback(async () => {
|
|
155
|
-
|
|
220
|
+
const id = taskIdRef.current;
|
|
221
|
+
if (!id)
|
|
156
222
|
return null;
|
|
157
223
|
try {
|
|
158
224
|
client.setPodId(resolvePodId(client, podId));
|
|
159
|
-
const stopped = await client.tasks.stop(
|
|
225
|
+
const stopped = await client.tasks.stop(id);
|
|
160
226
|
setTask(stopped);
|
|
161
|
-
|
|
162
|
-
setStatus(nextStatus);
|
|
163
|
-
if (nextStatus) {
|
|
164
|
-
onStatus?.(nextStatus);
|
|
165
|
-
}
|
|
227
|
+
setTaskStatus(stopped.status);
|
|
166
228
|
return stopped;
|
|
167
229
|
}
|
|
168
230
|
catch (stopError) {
|
|
169
231
|
const normalized = normalizeError(stopError, "Failed to stop task run.");
|
|
170
232
|
setError(normalized);
|
|
171
|
-
|
|
233
|
+
onErrorRef.current?.(stopError);
|
|
172
234
|
return null;
|
|
173
235
|
}
|
|
174
|
-
}, [client,
|
|
236
|
+
}, [client, podId, setTaskStatus]);
|
|
175
237
|
const clearMessages = useCallback(() => {
|
|
176
238
|
setMessages([]);
|
|
177
239
|
}, []);
|
|
178
240
|
useEffect(() => {
|
|
179
241
|
if (!taskId)
|
|
180
242
|
return;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
243
|
+
let cancelled = false;
|
|
244
|
+
const bootstrapTask = async () => {
|
|
245
|
+
const latestTask = await refreshTask(taskId);
|
|
246
|
+
if (cancelled)
|
|
247
|
+
return;
|
|
248
|
+
await loadMessages(taskId);
|
|
249
|
+
if (cancelled || !autoConnect)
|
|
250
|
+
return;
|
|
251
|
+
const latestStatus = normalizeRunStatus(latestTask?.status) ?? normalizeRunStatus(statusRef.current);
|
|
252
|
+
if (isTerminalTaskStatus(latestStatus)) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
await connect(taskId);
|
|
256
|
+
};
|
|
257
|
+
void bootstrapTask();
|
|
258
|
+
return () => {
|
|
259
|
+
cancelled = true;
|
|
260
|
+
disconnect();
|
|
261
|
+
};
|
|
262
|
+
}, [autoConnect, connect, disconnect, loadMessages, refreshTask, taskId]);
|
|
191
263
|
return {
|
|
192
264
|
taskId,
|
|
193
265
|
task,
|
package/dist/task-events.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { TaskMessage } from "./types.js";
|
|
1
|
+
import type { Task, TaskMessage } from "./types.js";
|
|
2
2
|
export interface ParsedTaskStreamEvent {
|
|
3
3
|
message?: TaskMessage;
|
|
4
4
|
status?: string;
|
|
5
|
+
task?: Task;
|
|
5
6
|
}
|
|
6
7
|
export declare function parseTaskStreamEvent(value: unknown): ParsedTaskStreamEvent;
|
|
7
8
|
export declare function upsertTaskMessage(messages: TaskMessage[], incoming: TaskMessage): TaskMessage[];
|
package/dist/task-events.js
CHANGED
|
@@ -26,6 +26,37 @@ function toTaskMessage(value) {
|
|
|
26
26
|
};
|
|
27
27
|
return message;
|
|
28
28
|
}
|
|
29
|
+
function toTask(value) {
|
|
30
|
+
if (!isRecord(value))
|
|
31
|
+
return undefined;
|
|
32
|
+
if (typeof value.id !== "string")
|
|
33
|
+
return undefined;
|
|
34
|
+
const status = normalizeStatus(value.status);
|
|
35
|
+
if (!status)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (typeof value.agent_id !== "string")
|
|
38
|
+
return undefined;
|
|
39
|
+
if (typeof value.pod_id !== "string")
|
|
40
|
+
return undefined;
|
|
41
|
+
if (typeof value.user_id !== "string")
|
|
42
|
+
return undefined;
|
|
43
|
+
if (typeof value.created_at !== "string")
|
|
44
|
+
return undefined;
|
|
45
|
+
if (typeof value.updated_at !== "string")
|
|
46
|
+
return undefined;
|
|
47
|
+
return {
|
|
48
|
+
id: value.id,
|
|
49
|
+
agent_id: value.agent_id,
|
|
50
|
+
pod_id: value.pod_id,
|
|
51
|
+
user_id: value.user_id,
|
|
52
|
+
input_data: isRecord(value.input_data) ? value.input_data : null,
|
|
53
|
+
output_data: isRecord(value.output_data) ? value.output_data : null,
|
|
54
|
+
error: typeof value.error === "string" ? value.error : null,
|
|
55
|
+
status: status,
|
|
56
|
+
created_at: value.created_at,
|
|
57
|
+
updated_at: value.updated_at,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
29
60
|
function extractPayload(record) {
|
|
30
61
|
if ("data" in record)
|
|
31
62
|
return record.data;
|
|
@@ -59,8 +90,14 @@ export function parseTaskStreamEvent(value) {
|
|
|
59
90
|
|| eventType === "task_status"
|
|
60
91
|
|| eventType === "task"
|
|
61
92
|
|| eventType === "task_updated") {
|
|
93
|
+
const task = toTask(payload) ?? (isRecord(payload) ? toTask(payload.task) : undefined);
|
|
62
94
|
const status = extractStatus(payload);
|
|
63
|
-
|
|
95
|
+
if (task || status) {
|
|
96
|
+
return {
|
|
97
|
+
task,
|
|
98
|
+
status: status ?? task?.status,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
64
101
|
}
|
|
65
102
|
return {};
|
|
66
103
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentResponse, AssistantResponse, AvailableModels, ConversationMessageResponse, ConversationResponse, CreateAgentRequest, CreateAssistantRequest, CreateTaskRequest, FlowRunEntity, FunctionRunResponse, IconUploadResponse, OrganizationInvitationResponse, OrganizationMemberResponse, OrganizationResponse, PodConfigResponse, PodMemberResponse, PodResponse, TaskMessageResponse, TaskResponse, UpdateAgentRequest, UpdateAssistantRequest, UserResponse } from "./openapi_client/index.js";
|
|
1
|
+
import type { AgentResponse, AssistantResponse, AvailableModels, ConversationMessageResponse, ConversationResponse, CreateAgentRequest, CreateAssistantRequest, CreateTaskRequest, FlowRunEntity, FunctionRunResponse, IconUploadResponse, OrganizationInvitationResponse, OrganizationMemberResponse, OrganizationResponse, PodConfigResponse, PodJoinRequestCreateResponse, PodMemberResponse, PodResponse, TaskMessageResponse, TaskResponse, UpdateAgentRequest, UpdateAssistantRequest, UserResponse } from "./openapi_client/index.js";
|
|
2
2
|
/** Public ergonomic types. */
|
|
3
3
|
export interface PageResult<T> {
|
|
4
4
|
items: T[];
|
|
@@ -54,6 +54,7 @@ export type FlowRun = FlowRunEntity;
|
|
|
54
54
|
export type Pod = PodResponse;
|
|
55
55
|
export type PodConfig = PodConfigResponse;
|
|
56
56
|
export type PodMember = PodMemberResponse;
|
|
57
|
+
export type PodJoinRequest = PodJoinRequestCreateResponse;
|
|
57
58
|
export type Organization = OrganizationResponse;
|
|
58
59
|
export type OrganizationMember = OrganizationMemberResponse;
|
|
59
60
|
export type OrganizationInvitation = OrganizationInvitationResponse;
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/* generated using openapi-typescript-codegen -- do not edit */
|
|
2
|
-
/* istanbul ignore file */
|
|
3
|
-
/* tslint:disable */
|
|
4
|
-
/* eslint-disable */
|
|
5
|
-
export var PodStatus;
|
|
6
|
-
(function (PodStatus) {
|
|
7
|
-
PodStatus["ACTIVE"] = "ACTIVE";
|
|
8
|
-
PodStatus["ARCHIVED"] = "ARCHIVED";
|
|
9
|
-
})(PodStatus || (PodStatus = {}));
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* generated using openapi-typescript-codegen -- do not edit */
|
|
2
|
-
/* istanbul ignore file */
|
|
3
|
-
/* tslint:disable */
|
|
4
|
-
/* eslint-disable */
|
|
5
|
-
export var PodType;
|
|
6
|
-
(function (PodType) {
|
|
7
|
-
PodType["UI"] = "UI";
|
|
8
|
-
PodType["ASSISTANT"] = "ASSISTANT";
|
|
9
|
-
PodType["HYBRID"] = "HYBRID";
|
|
10
|
-
PodType["AUTOMATION"] = "AUTOMATION";
|
|
11
|
-
})(PodType || (PodType = {}));
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { LemmaClient } from "../client.js";
|
|
2
|
-
import { type SseRawEvent } from "../streams.js";
|
|
3
|
-
export interface UseAgentRunStreamOptions {
|
|
4
|
-
client: LemmaClient;
|
|
5
|
-
podId?: string;
|
|
6
|
-
taskId?: string | null;
|
|
7
|
-
autoConnect?: boolean;
|
|
8
|
-
onEvent?: (event: SseRawEvent, payload: unknown | null) => void;
|
|
9
|
-
onError?: (error: unknown) => void;
|
|
10
|
-
}
|
|
11
|
-
export interface UseAgentRunStreamResult {
|
|
12
|
-
isStreaming: boolean;
|
|
13
|
-
error: Error | null;
|
|
14
|
-
connect: () => Promise<void>;
|
|
15
|
-
disconnect: () => void;
|
|
16
|
-
}
|
|
17
|
-
export declare function useAgentRunStream({ client, podId, taskId, autoConnect, onEvent, onError, }: UseAgentRunStreamOptions): UseAgentRunStreamResult;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { parseSSEJson, readSSE } from "../streams.js";
|
|
3
|
-
function resolvePodId(client, podId) {
|
|
4
|
-
const resolved = podId ?? client.podId;
|
|
5
|
-
if (!resolved) {
|
|
6
|
-
throw new Error("podId is required. Pass podId or set it on LemmaClient.");
|
|
7
|
-
}
|
|
8
|
-
return resolved;
|
|
9
|
-
}
|
|
10
|
-
export function useAgentRunStream({ client, podId, taskId, autoConnect = true, onEvent, onError, }) {
|
|
11
|
-
const [isStreaming, setIsStreaming] = useState(false);
|
|
12
|
-
const [error, setError] = useState(null);
|
|
13
|
-
const abortRef = useRef(null);
|
|
14
|
-
const disconnect = useCallback(() => {
|
|
15
|
-
abortRef.current?.abort();
|
|
16
|
-
abortRef.current = null;
|
|
17
|
-
}, []);
|
|
18
|
-
const connect = useCallback(async () => {
|
|
19
|
-
if (!taskId) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
disconnect();
|
|
23
|
-
const controller = new AbortController();
|
|
24
|
-
abortRef.current = controller;
|
|
25
|
-
setError(null);
|
|
26
|
-
setIsStreaming(true);
|
|
27
|
-
try {
|
|
28
|
-
client.setPodId(resolvePodId(client, podId));
|
|
29
|
-
const stream = await client.tasks.stream(taskId, { signal: controller.signal });
|
|
30
|
-
for await (const event of readSSE(stream)) {
|
|
31
|
-
if (controller.signal.aborted) {
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
onEvent?.(event, parseSSEJson(event));
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch (streamError) {
|
|
38
|
-
if (!(streamError instanceof Error && streamError.name === "AbortError")) {
|
|
39
|
-
const normalized = streamError instanceof Error
|
|
40
|
-
? streamError
|
|
41
|
-
: new Error("Failed to stream agent run.");
|
|
42
|
-
setError(normalized);
|
|
43
|
-
onError?.(streamError);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
finally {
|
|
47
|
-
if (abortRef.current === controller) {
|
|
48
|
-
abortRef.current = null;
|
|
49
|
-
}
|
|
50
|
-
setIsStreaming(false);
|
|
51
|
-
}
|
|
52
|
-
}, [client, disconnect, onError, onEvent, podId, taskId]);
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
if (!autoConnect || !taskId) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
void connect();
|
|
58
|
-
return () => disconnect();
|
|
59
|
-
}, [autoConnect, connect, disconnect, taskId]);
|
|
60
|
-
return {
|
|
61
|
-
isStreaming,
|
|
62
|
-
error,
|
|
63
|
-
connect,
|
|
64
|
-
disconnect,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
File without changes
|