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.
Files changed (75) hide show
  1. package/README.md +175 -506
  2. package/dist/browser/lemma-client.js +207 -12
  3. package/dist/client.d.ts +2 -0
  4. package/dist/client.js +3 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/namespaces/pod-join-requests.d.ts +16 -0
  7. package/dist/namespaces/pod-join-requests.js +24 -0
  8. package/dist/namespaces/pod-members.d.ts +1 -0
  9. package/dist/namespaces/pod-members.js +3 -0
  10. package/dist/openapi_client/index.d.ts +10 -3
  11. package/dist/openapi_client/index.js +4 -2
  12. package/dist/openapi_client/models/ColumnSchema.d.ts +4 -0
  13. package/dist/openapi_client/models/CreateTableRequest.d.ts +1 -1
  14. package/dist/openapi_client/models/DataStoreFlowStart.d.ts +3 -6
  15. package/dist/openapi_client/models/DatastoreOperation.d.ts +5 -0
  16. package/dist/openapi_client/models/DatastoreOperation.js +10 -0
  17. package/dist/openapi_client/models/DatastoreQueryRequest.d.ts +1 -1
  18. package/dist/openapi_client/models/FlowInstallEntity.d.ts +2 -2
  19. package/dist/openapi_client/models/FlowResponse.d.ts +4 -3
  20. package/dist/openapi_client/models/{FlowStart.d.ts → FlowStart_Input.d.ts} +1 -1
  21. package/dist/openapi_client/models/FlowStart_Output.d.ts +14 -0
  22. package/dist/openapi_client/models/FlowStart_Output.js +1 -0
  23. package/dist/openapi_client/models/PodCreateRequest.d.ts +0 -4
  24. package/dist/openapi_client/models/PodJoinRequestApproveRequest.d.ts +6 -0
  25. package/dist/openapi_client/models/PodJoinRequestApproveRequest.js +1 -0
  26. package/dist/openapi_client/models/PodJoinRequestCreateResponse.d.ts +17 -0
  27. package/dist/openapi_client/models/PodJoinRequestCreateResponse.js +1 -0
  28. package/dist/openapi_client/models/PodJoinRequestListResponse.d.ts +7 -0
  29. package/dist/openapi_client/models/PodJoinRequestListResponse.js +1 -0
  30. package/dist/openapi_client/models/PodJoinRequestStatus.d.ts +5 -0
  31. package/dist/openapi_client/models/PodJoinRequestStatus.js +10 -0
  32. package/dist/openapi_client/models/PodMemberDetailResponse.d.ts +14 -0
  33. package/dist/openapi_client/models/PodMemberDetailResponse.js +1 -0
  34. package/dist/openapi_client/models/PodMemberResponse.d.ts +3 -3
  35. package/dist/openapi_client/models/PodResponse.d.ts +0 -5
  36. package/dist/openapi_client/models/PodUpdateRequest.d.ts +0 -4
  37. package/dist/openapi_client/models/WorkflowCreateRequest.d.ts +7 -6
  38. package/dist/openapi_client/models/WorkflowGraphUpdateRequest.d.ts +2 -2
  39. package/dist/openapi_client/models/WorkflowInstallMode.d.ts +7 -0
  40. package/dist/openapi_client/models/WorkflowInstallMode.js +12 -0
  41. package/dist/openapi_client/models/WorkflowUpdateRequest.d.ts +5 -4
  42. package/dist/openapi_client/services/FilesService.d.ts +1 -1
  43. package/dist/openapi_client/services/FilesService.js +1 -1
  44. package/dist/openapi_client/services/PodJoinRequestsService.d.ts +44 -0
  45. package/dist/openapi_client/services/PodJoinRequestsService.js +93 -0
  46. package/dist/openapi_client/services/PodMembersService.d.ts +14 -4
  47. package/dist/openapi_client/services/PodMembersService.js +29 -8
  48. package/dist/openapi_client/services/RecordsService.d.ts +2 -2
  49. package/dist/openapi_client/services/RecordsService.js +2 -2
  50. package/dist/openapi_client/services/WorkflowsService.d.ts +1 -1
  51. package/dist/openapi_client/services/WorkflowsService.js +1 -1
  52. package/dist/react/AuthGuard.d.ts +5 -2
  53. package/dist/react/AuthGuard.js +126 -3
  54. package/dist/react/components/AssistantChrome.js +1 -1
  55. package/dist/react/components/AssistantExperience.d.ts +7 -2
  56. package/dist/react/components/AssistantExperience.js +272 -32
  57. package/dist/react/components/assistant-types.d.ts +1 -0
  58. package/dist/react/index.d.ts +0 -2
  59. package/dist/react/index.js +0 -1
  60. package/dist/react/styles.css +594 -224
  61. package/dist/react/useAssistantController.js +2 -1
  62. package/dist/react/useAssistantRuntime.d.ts +2 -1
  63. package/dist/react/useAssistantRuntime.js +7 -3
  64. package/dist/react/useTaskSession.js +145 -73
  65. package/dist/task-events.d.ts +2 -1
  66. package/dist/task-events.js +38 -1
  67. package/dist/types.d.ts +2 -1
  68. package/package.json +1 -1
  69. package/dist/openapi_client/models/PodStatus.d.ts +0 -4
  70. package/dist/openapi_client/models/PodStatus.js +0 -9
  71. package/dist/openapi_client/models/PodType.d.ts +0 -6
  72. package/dist/openapi_client/models/PodType.js +0 -11
  73. package/dist/react/useAgentRun.d.ts +0 -17
  74. package/dist/react/useAgentRun.js +0 -66
  75. /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, conversationId))
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 setTaskId = useCallback((nextTaskId) => {
26
- setTaskIdState(nextTaskId);
27
- if (!nextTaskId) {
28
- setTask(null);
29
- setStatus(undefined);
30
- setMessages([]);
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
- if (externalTaskId === taskId)
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
- }, [disconnect, externalTaskId, taskId]);
87
+ previousExternalTaskIdRef.current = externalTaskId;
88
+ setTaskId(externalTaskId);
89
+ }, [externalTaskId, setTaskId]);
48
90
  const refreshTask = useCallback(async (explicitTaskId) => {
49
- const id = explicitTaskId ?? taskId;
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
- const nextStatus = normalizeRunStatus(nextTask.status);
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
- onError?.(refreshError);
104
+ onErrorRef.current?.(refreshError);
67
105
  return null;
68
106
  }
69
- }, [client, onError, onStatus, podId, taskId]);
107
+ }, [client, podId, setTaskStatus]);
70
108
  const loadMessages = useCallback(async (explicitTaskId) => {
71
- const id = explicitTaskId ?? taskId;
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
- onError?.(messageError);
122
+ onErrorRef.current?.(messageError);
85
123
  return [];
86
124
  }
87
- }, [client, onError, podId, taskId]);
125
+ }, [client, podId]);
88
126
  const connect = useCallback(async (explicitTaskId) => {
89
- const id = explicitTaskId ?? taskId;
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
- client.setPodId(resolvePodId(client, podId));
100
- const stream = await client.tasks.stream(id, { signal: controller.signal });
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
- const payload = parseSSEJson(event);
106
- onEvent?.(event, payload);
107
- const parsed = parseTaskStreamEvent(payload);
108
- if (parsed.message) {
109
- setMessages((previous) => upsertTaskMessage(previous, parsed.message));
110
- onMessage?.(parsed.message);
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
- if (parsed.status) {
113
- setStatus(parsed.status);
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, onError, onEvent, onMessage, onStatus, podId, taskId]);
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
- const nextStatus = normalizeRunStatus(created.status);
145
- setStatus(nextStatus);
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, onStatus, podId]);
218
+ }, [autoConnect, autoConnectOnStart, client, connect, podId, setTaskStatus]);
154
219
  const stop = useCallback(async () => {
155
- if (!taskId)
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(taskId);
225
+ const stopped = await client.tasks.stop(id);
160
226
  setTask(stopped);
161
- const nextStatus = normalizeRunStatus(stopped.status);
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
- onError?.(stopError);
233
+ onErrorRef.current?.(stopError);
172
234
  return null;
173
235
  }
174
- }, [client, onError, onStatus, podId, taskId]);
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
- void refreshTask(taskId);
182
- void loadMessages(taskId);
183
- }, [loadMessages, refreshTask, taskId]);
184
- useEffect(() => {
185
- if (!autoConnect || !taskId) {
186
- return;
187
- }
188
- void connect(taskId);
189
- return () => disconnect();
190
- }, [autoConnect, connect, disconnect, taskId]);
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,
@@ -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[];
@@ -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
- return status ? { status } : {};
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,6 +1,6 @@
1
1
  {
2
2
  "name": "lemma-sdk",
3
- "version": "0.2.24",
3
+ "version": "0.2.27",
4
4
  "description": "Official TypeScript SDK for Lemma pod-scoped APIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,4 +0,0 @@
1
- export declare enum PodStatus {
2
- ACTIVE = "ACTIVE",
3
- ARCHIVED = "ARCHIVED"
4
- }
@@ -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,6 +0,0 @@
1
- export declare enum PodType {
2
- UI = "UI",
3
- ASSISTANT = "ASSISTANT",
4
- HYBRID = "HYBRID",
5
- AUTOMATION = "AUTOMATION"
6
- }
@@ -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
- }