lemma-sdk 0.2.23 → 0.2.25
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 +156 -511
- package/dist/auth.js +0 -1
- package/dist/browser/lemma-client.js +196 -112
- package/dist/namespaces/assistants.d.ts +21 -3
- package/dist/namespaces/assistants.js +13 -7
- package/dist/namespaces/files.d.ts +9 -4
- package/dist/namespaces/files.js +52 -14
- package/dist/namespaces/records.d.ts +10 -2
- package/dist/namespaces/records.js +15 -9
- package/dist/openapi_client/index.d.ts +7 -7
- package/dist/openapi_client/index.js +2 -4
- package/dist/openapi_client/models/ColumnSchema.d.ts +4 -0
- package/dist/openapi_client/models/CreateConversationRequest.d.ts +1 -1
- package/dist/openapi_client/models/CreateFolderRequest.d.ts +1 -2
- package/dist/openapi_client/models/CreateTableRequest.d.ts +1 -1
- package/dist/openapi_client/models/CreateTriggerRequest.d.ts +0 -1
- package/dist/openapi_client/models/DatastoreFileUploadRequest.d.ts +1 -1
- package/dist/openapi_client/models/DatastoreQueryRequest.d.ts +9 -0
- package/dist/openapi_client/models/DatastoreQueryResponse.d.ts +7 -0
- package/dist/openapi_client/models/DirectoryTreeNode.d.ts +7 -0
- package/dist/openapi_client/models/DirectoryTreeResponse.d.ts +6 -0
- package/dist/openapi_client/models/DirectoryTreeResponse.js +1 -0
- package/dist/openapi_client/models/FileResponse.d.ts +4 -6
- package/dist/openapi_client/models/FileSearchRequest.d.ts +5 -3
- package/dist/openapi_client/models/FileSearchResultSchema.d.ts +1 -0
- package/dist/openapi_client/models/FileSearchScopeMode.d.ts +4 -0
- package/dist/openapi_client/models/FileSearchScopeMode.js +9 -0
- package/dist/openapi_client/models/PodCreateRequest.d.ts +0 -4
- 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/TableResponse.d.ts +1 -1
- package/dist/openapi_client/models/TriggerResponse.d.ts +0 -1
- package/dist/openapi_client/models/update.d.ts +2 -2
- package/dist/openapi_client/services/ConversationsService.d.ts +3 -2
- package/dist/openapi_client/services/ConversationsService.js +5 -3
- package/dist/openapi_client/services/FilesService.d.ts +34 -25
- package/dist/openapi_client/services/FilesService.js +75 -47
- package/dist/openapi_client/services/PodMembersService.d.ts +14 -4
- package/dist/openapi_client/services/PodMembersService.js +29 -8
- package/dist/openapi_client/services/QueryService.d.ts +14 -0
- package/dist/openapi_client/services/QueryService.js +26 -0
- package/dist/openapi_client/services/RecordsService.d.ts +7 -13
- package/dist/openapi_client/services/RecordsService.js +12 -26
- package/dist/react/components/AssistantEmbedded.d.ts +1 -1
- package/dist/react/components/AssistantEmbedded.js +2 -1
- package/dist/react/index.d.ts +0 -2
- package/dist/react/index.js +0 -1
- package/dist/react/useAssistantController.d.ts +5 -1
- package/dist/react/useAssistantController.js +7 -3
- package/dist/react/useAssistantSession.d.ts +12 -0
- package/dist/react/useAssistantSession.js +24 -5
- 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 +10 -4
- 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/openapi_client/models/RecordFilter.d.ts +0 -15
- package/dist/openapi_client/models/RecordFilterOperator.d.ts +0 -10
- package/dist/openapi_client/models/RecordFilterOperator.js +0 -15
- package/dist/openapi_client/models/RecordQueryRequest.d.ts +0 -20
- package/dist/openapi_client/models/RecordSort.d.ts +0 -11
- package/dist/openapi_client/models/RecordSortDirection.d.ts +0 -4
- package/dist/openapi_client/models/RecordSortDirection.js +0 -9
- package/dist/react/useAgentRun.d.ts +0 -17
- package/dist/react/useAgentRun.js +0 -66
- /package/dist/openapi_client/models/{RecordFilter.js → DatastoreQueryRequest.js} +0 -0
- /package/dist/openapi_client/models/{RecordQueryRequest.js → DatastoreQueryResponse.js} +0 -0
- /package/dist/openapi_client/models/{RecordSort.js → DirectoryTreeNode.js} +0 -0
|
@@ -3,6 +3,7 @@ import { useAssistantRuntime } from "./useAssistantRuntime.js";
|
|
|
3
3
|
import { useAssistantSession } from "./useAssistantSession.js";
|
|
4
4
|
const EMPTY_SCOPE_KEY = JSON.stringify({
|
|
5
5
|
podId: null,
|
|
6
|
+
assistantName: null,
|
|
6
7
|
assistantId: null,
|
|
7
8
|
organizationId: null,
|
|
8
9
|
});
|
|
@@ -538,7 +539,7 @@ function isConversationRunning(status) {
|
|
|
538
539
|
}
|
|
539
540
|
return true;
|
|
540
541
|
}
|
|
541
|
-
export function useAssistantController({ client, podId, assistantId, organizationId, enabled = true, }) {
|
|
542
|
+
export function useAssistantController({ client, podId, assistantName, assistantId, organizationId, enabled = true, }) {
|
|
542
543
|
const [localError, setLocalError] = useState(null);
|
|
543
544
|
const [messages, setMessages] = useState([]);
|
|
544
545
|
const [conversations, setConversations] = useState([]);
|
|
@@ -560,20 +561,23 @@ export function useAssistantController({ client, podId, assistantId, organizatio
|
|
|
560
561
|
const skipInitialLoadConversationIdsRef = useRef(new Set());
|
|
561
562
|
const scope = useMemo(() => ({
|
|
562
563
|
podId: podId ?? null,
|
|
564
|
+
assistantName: assistantName ?? assistantId ?? null,
|
|
563
565
|
assistantId: assistantId ?? null,
|
|
564
566
|
organizationId: organizationId ?? null,
|
|
565
|
-
}), [assistantId, organizationId, podId]);
|
|
567
|
+
}), [assistantId, assistantName, organizationId, podId]);
|
|
566
568
|
const scopeKey = useMemo(() => JSON.stringify({
|
|
567
569
|
podId: scope.podId ?? null,
|
|
570
|
+
assistantName: scope.assistantName ?? null,
|
|
568
571
|
assistantId: scope.assistantId ?? null,
|
|
569
572
|
organizationId: scope.organizationId ?? null,
|
|
570
|
-
}), [scope.assistantId, scope.organizationId, scope.podId]);
|
|
573
|
+
}), [scope.assistantId, scope.assistantName, scope.organizationId, scope.podId]);
|
|
571
574
|
const handleAssistantSessionError = useCallback((sessionError) => {
|
|
572
575
|
setLocalError((prev) => prev || (sessionError instanceof Error ? sessionError.message : "Assistant session failed"));
|
|
573
576
|
}, []);
|
|
574
577
|
const assistantSession = useAssistantSession({
|
|
575
578
|
client,
|
|
576
579
|
podId: scope.podId ?? undefined,
|
|
580
|
+
assistantName: scope.assistantName ?? undefined,
|
|
577
581
|
assistantId: scope.assistantId ?? undefined,
|
|
578
582
|
organizationId: scope.organizationId ?? undefined,
|
|
579
583
|
conversationId: activeConversationId ?? undefined,
|
|
@@ -3,12 +3,20 @@ import { type SseRawEvent } from "../streams.js";
|
|
|
3
3
|
import type { Conversation, ConversationMessage, ConversationModel, CursorPage } from "../types.js";
|
|
4
4
|
interface ConversationScope {
|
|
5
5
|
podId?: string | null;
|
|
6
|
+
assistantName?: string | null;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use assistantName instead.
|
|
9
|
+
*/
|
|
6
10
|
assistantId?: string | null;
|
|
7
11
|
organizationId?: string | null;
|
|
8
12
|
}
|
|
9
13
|
export interface UseAssistantSessionOptions {
|
|
10
14
|
client: LemmaClient;
|
|
11
15
|
podId?: string;
|
|
16
|
+
assistantName?: string;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Use assistantName instead.
|
|
19
|
+
*/
|
|
12
20
|
assistantId?: string;
|
|
13
21
|
organizationId?: string;
|
|
14
22
|
conversationId?: string | null;
|
|
@@ -24,6 +32,10 @@ export interface CreateConversationInput {
|
|
|
24
32
|
title?: string | null;
|
|
25
33
|
model?: ConversationModel | null;
|
|
26
34
|
podId?: string | null;
|
|
35
|
+
assistantName?: string | null;
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Use assistantName instead.
|
|
38
|
+
*/
|
|
27
39
|
assistantId?: string | null;
|
|
28
40
|
organizationId?: string | null;
|
|
29
41
|
setActive?: boolean;
|
|
@@ -23,8 +23,14 @@ function normalizeError(error, fallback) {
|
|
|
23
23
|
return new Error(fallback);
|
|
24
24
|
}
|
|
25
25
|
function normalizeScope(client, defaults, override) {
|
|
26
|
+
const resolvedAssistantName = override?.assistantName
|
|
27
|
+
?? override?.assistantId
|
|
28
|
+
?? defaults.assistantName
|
|
29
|
+
?? defaults.assistantId
|
|
30
|
+
?? null;
|
|
26
31
|
return {
|
|
27
32
|
podId: override?.podId ?? defaults.podId ?? client.podId ?? null,
|
|
33
|
+
assistantName: resolvedAssistantName,
|
|
28
34
|
assistantId: override?.assistantId ?? defaults.assistantId ?? null,
|
|
29
35
|
organizationId: override?.organizationId ?? defaults.organizationId ?? null,
|
|
30
36
|
};
|
|
@@ -48,7 +54,7 @@ function resolveResumeInput(input) {
|
|
|
48
54
|
return input ?? {};
|
|
49
55
|
}
|
|
50
56
|
export function useAssistantSession(options) {
|
|
51
|
-
const { client, podId: defaultPodId, assistantId: defaultAssistantId, organizationId: defaultOrganizationId, conversationId: externalConversationId = null, autoLoad = true, autoResume = false, syncOnTurnEnd = false, onEvent, onStatus, onMessage, onError, } = options;
|
|
57
|
+
const { client, podId: defaultPodId, assistantName: defaultAssistantName, assistantId: defaultAssistantId, organizationId: defaultOrganizationId, conversationId: externalConversationId = null, autoLoad = true, autoResume = false, syncOnTurnEnd = false, onEvent, onStatus, onMessage, onError, } = options;
|
|
52
58
|
const [conversationId, setConversationIdState] = useState(externalConversationId);
|
|
53
59
|
const [conversation, setConversation] = useState(null);
|
|
54
60
|
const [status, setStatus] = useState(undefined);
|
|
@@ -129,16 +135,17 @@ export function useAssistantSession(options) {
|
|
|
129
135
|
}, []);
|
|
130
136
|
const defaultScope = useMemo(() => ({
|
|
131
137
|
podId: defaultPodId ?? null,
|
|
138
|
+
assistantName: defaultAssistantName ?? defaultAssistantId ?? null,
|
|
132
139
|
assistantId: defaultAssistantId ?? null,
|
|
133
140
|
organizationId: defaultOrganizationId ?? null,
|
|
134
|
-
}), [defaultAssistantId, defaultOrganizationId, defaultPodId]);
|
|
141
|
+
}), [defaultAssistantId, defaultAssistantName, defaultOrganizationId, defaultPodId]);
|
|
135
142
|
const listConversations = useCallback(async (input = {}) => {
|
|
136
143
|
try {
|
|
137
144
|
const scope = normalizeScope(client, defaultScope, input.scope);
|
|
138
145
|
applyPodScope(client, scope.podId);
|
|
139
146
|
const response = await client.conversations.list({
|
|
140
147
|
pod_id: scope.podId ?? undefined,
|
|
141
|
-
|
|
148
|
+
assistant_name: scope.assistantName ?? scope.assistantId ?? undefined,
|
|
142
149
|
organization_id: scope.organizationId ?? undefined,
|
|
143
150
|
limit: input.limit,
|
|
144
151
|
page_token: input.pageToken,
|
|
@@ -165,7 +172,11 @@ export function useAssistantSession(options) {
|
|
|
165
172
|
const payload = {
|
|
166
173
|
title: input.title ?? undefined,
|
|
167
174
|
pod_id: input.podId ?? defaultPodId ?? client.podId ?? undefined,
|
|
168
|
-
|
|
175
|
+
assistant_name: input.assistantName
|
|
176
|
+
?? input.assistantId
|
|
177
|
+
?? defaultAssistantName
|
|
178
|
+
?? defaultAssistantId
|
|
179
|
+
?? undefined,
|
|
169
180
|
organization_id: input.organizationId ?? defaultOrganizationId ?? undefined,
|
|
170
181
|
model: typeof input.model === "undefined"
|
|
171
182
|
? undefined
|
|
@@ -181,7 +192,15 @@ export function useAssistantSession(options) {
|
|
|
181
192
|
autoResumedKeyRef.current = null;
|
|
182
193
|
}
|
|
183
194
|
return created;
|
|
184
|
-
}, [
|
|
195
|
+
}, [
|
|
196
|
+
clearStreamingText,
|
|
197
|
+
client,
|
|
198
|
+
defaultAssistantId,
|
|
199
|
+
defaultAssistantName,
|
|
200
|
+
defaultOrganizationId,
|
|
201
|
+
defaultPodId,
|
|
202
|
+
setConversationStatus,
|
|
203
|
+
]);
|
|
185
204
|
const refreshConversation = useCallback(async (explicitConversationId) => {
|
|
186
205
|
const id = explicitConversationId ?? conversationId;
|
|
187
206
|
if (!id)
|
|
@@ -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,5 +1,3 @@
|
|
|
1
|
-
import type { RecordFilter as GeneratedRecordFilter } from "./openapi_client/models/RecordFilter.js";
|
|
2
|
-
import type { RecordSort as GeneratedRecordSort } from "./openapi_client/models/RecordSort.js";
|
|
3
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";
|
|
4
2
|
/** Public ergonomic types. */
|
|
5
3
|
export interface PageResult<T> {
|
|
@@ -7,8 +5,16 @@ export interface PageResult<T> {
|
|
|
7
5
|
nextPageToken?: string;
|
|
8
6
|
total?: number;
|
|
9
7
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
8
|
+
export interface RecordFilter {
|
|
9
|
+
field: string;
|
|
10
|
+
op: string;
|
|
11
|
+
value?: unknown;
|
|
12
|
+
values?: unknown[];
|
|
13
|
+
}
|
|
14
|
+
export interface RecordSort {
|
|
15
|
+
field: string;
|
|
16
|
+
direction?: "asc" | "desc" | string;
|
|
17
|
+
}
|
|
12
18
|
export interface ListRecordsOptions {
|
|
13
19
|
filters?: RecordFilter[];
|
|
14
20
|
sort?: RecordSort[];
|
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,15 +0,0 @@
|
|
|
1
|
-
import type { RecordFilterOperator } from './RecordFilterOperator.js';
|
|
2
|
-
export type RecordFilter = {
|
|
3
|
-
/**
|
|
4
|
-
* Table column name to filter on.
|
|
5
|
-
*/
|
|
6
|
-
field: string;
|
|
7
|
-
/**
|
|
8
|
-
* Comparison operator to apply.
|
|
9
|
-
*/
|
|
10
|
-
op?: RecordFilterOperator;
|
|
11
|
-
/**
|
|
12
|
-
* Filter comparison value.
|
|
13
|
-
*/
|
|
14
|
-
value: any;
|
|
15
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/* generated using openapi-typescript-codegen -- do not edit */
|
|
2
|
-
/* istanbul ignore file */
|
|
3
|
-
/* tslint:disable */
|
|
4
|
-
/* eslint-disable */
|
|
5
|
-
export var RecordFilterOperator;
|
|
6
|
-
(function (RecordFilterOperator) {
|
|
7
|
-
RecordFilterOperator["EQ"] = "eq";
|
|
8
|
-
RecordFilterOperator["NE"] = "ne";
|
|
9
|
-
RecordFilterOperator["GT"] = "gt";
|
|
10
|
-
RecordFilterOperator["GTE"] = "gte";
|
|
11
|
-
RecordFilterOperator["LT"] = "lt";
|
|
12
|
-
RecordFilterOperator["LTE"] = "lte";
|
|
13
|
-
RecordFilterOperator["LIKE"] = "like";
|
|
14
|
-
RecordFilterOperator["ILIKE"] = "ilike";
|
|
15
|
-
})(RecordFilterOperator || (RecordFilterOperator = {}));
|