lemma-sdk 0.2.30 → 0.2.31
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 +211 -51
- package/dist/react/index.d.ts +20 -0
- package/dist/react/index.js +10 -0
- package/dist/react/useAgentInputSchema.d.ts +19 -0
- package/dist/react/useAgentInputSchema.js +73 -0
- package/dist/react/useAgentRun.js +18 -20
- package/dist/react/useAgentRuns.d.ts +33 -0
- package/dist/react/useAgentRuns.js +149 -0
- package/dist/react/useAssistantRun.js +10 -9
- package/dist/react/useAssistantSession.js +21 -25
- package/dist/react/useBulkRecords.js +9 -16
- package/dist/react/useConversation.js +24 -8
- package/dist/react/useConversations.d.ts +4 -0
- package/dist/react/useConversations.js +49 -3
- package/dist/react/useCreateRecord.js +9 -16
- package/dist/react/useCurrentUser.d.ts +14 -0
- package/dist/react/useCurrentUser.js +68 -0
- package/dist/react/useDeleteRecord.js +9 -16
- package/dist/react/useFlowRunHistory.js +1 -5
- package/dist/react/useFlowSession.js +41 -33
- package/dist/react/useForeignKeyOptions.js +26 -15
- package/dist/react/useFunctionRun.d.ts +19 -0
- package/dist/react/useFunctionRun.js +30 -0
- package/dist/react/useFunctionRuns.d.ts +33 -0
- package/dist/react/useFunctionRuns.js +149 -0
- package/dist/react/useFunctionSession.js +37 -29
- package/dist/react/useJoinedRecords.js +24 -23
- package/dist/react/useMembers.d.ts +4 -0
- package/dist/react/useMembers.js +55 -16
- package/dist/react/useOrganizationMembers.d.ts +26 -0
- package/dist/react/useOrganizationMembers.js +113 -0
- package/dist/react/usePodAccess.d.ts +22 -0
- package/dist/react/usePodAccess.js +128 -0
- package/dist/react/useRecord.js +24 -13
- package/dist/react/useRecordForm.js +1 -18
- package/dist/react/useRecords.d.ts +2 -0
- package/dist/react/useRecords.js +62 -22
- package/dist/react/useRelatedRecords.js +28 -21
- package/dist/react/useReverseRelatedRecords.js +30 -21
- package/dist/react/useSchemaForm.js +1 -13
- package/dist/react/useTable.js +24 -13
- package/dist/react/useTables.d.ts +4 -0
- package/dist/react/useTables.js +57 -15
- package/dist/react/useTaskSession.js +11 -22
- package/dist/react/useUpdateRecord.js +9 -16
- package/dist/react/useWorkflowResume.d.ts +18 -0
- package/dist/react/useWorkflowResume.js +45 -0
- package/dist/react/useWorkflowRun.d.ts +21 -0
- package/dist/react/useWorkflowRun.js +49 -0
- package/dist/react/useWorkflowRuns.d.ts +33 -0
- package/dist/react/useWorkflowRuns.js +149 -0
- package/dist/react/useWorkflowStart.js +20 -27
- package/dist/react/utils.d.ts +5 -0
- package/dist/react/utils.js +25 -0
- package/dist/types.d.ts +1 -0
- package/package.json +2 -4
- package/dist/react/components/AssistantChrome.d.ts +0 -86
- package/dist/react/components/AssistantChrome.js +0 -48
- package/dist/react/components/AssistantEmbedded.d.ts +0 -10
- package/dist/react/components/AssistantEmbedded.js +0 -15
- package/dist/react/components/AssistantExperience.d.ts +0 -96
- package/dist/react/components/AssistantExperience.js +0 -1294
- package/dist/react/components/assistant-types.d.ts +0 -80
- package/dist/react/components/assistant-types.js +0 -1
|
@@ -2,18 +2,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
2
2
|
import { parseSSEJson, readSSE } from "../streams.js";
|
|
3
3
|
import { isTerminalTaskStatus, normalizeRunStatus } from "../run-utils.js";
|
|
4
4
|
import { parseTaskStreamEvent, upsertTaskMessage } from "../task-events.js";
|
|
5
|
-
|
|
6
|
-
const resolved = podId ?? client.podId;
|
|
7
|
-
if (!resolved) {
|
|
8
|
-
throw new Error("podId is required. Pass podId or set it on LemmaClient.");
|
|
9
|
-
}
|
|
10
|
-
return resolved;
|
|
11
|
-
}
|
|
12
|
-
function normalizeError(error, fallback) {
|
|
13
|
-
if (error instanceof Error)
|
|
14
|
-
return error;
|
|
15
|
-
return new Error(fallback);
|
|
16
|
-
}
|
|
5
|
+
import { normalizeError, resolvePodClient, resolvePodId } from "./utils.js";
|
|
17
6
|
function sleep(ms) {
|
|
18
7
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
8
|
}
|
|
@@ -92,8 +81,8 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
92
81
|
if (!id)
|
|
93
82
|
return null;
|
|
94
83
|
try {
|
|
95
|
-
client
|
|
96
|
-
const nextTask = await
|
|
84
|
+
const scopedClient = resolvePodClient(client, resolvePodId(client, podId));
|
|
85
|
+
const nextTask = await scopedClient.tasks.get(id);
|
|
97
86
|
setTask(nextTask);
|
|
98
87
|
setTaskStatus(nextTask.status);
|
|
99
88
|
return nextTask;
|
|
@@ -110,8 +99,8 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
110
99
|
if (!id)
|
|
111
100
|
return [];
|
|
112
101
|
try {
|
|
113
|
-
client
|
|
114
|
-
const response = await
|
|
102
|
+
const scopedClient = resolvePodClient(client, resolvePodId(client, podId));
|
|
103
|
+
const response = await scopedClient.tasks.messages.list(id, { limit: 100 });
|
|
115
104
|
const nextMessages = response.items ?? [];
|
|
116
105
|
setMessages(nextMessages);
|
|
117
106
|
return nextMessages;
|
|
@@ -141,8 +130,8 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
141
130
|
break;
|
|
142
131
|
}
|
|
143
132
|
try {
|
|
144
|
-
client
|
|
145
|
-
const stream = await
|
|
133
|
+
const scopedClient = resolvePodClient(client, resolvePodId(client, podId));
|
|
134
|
+
const stream = await scopedClient.tasks.stream(id, { signal: controller.signal });
|
|
146
135
|
reconnectDelayMs = 1000;
|
|
147
136
|
for await (const event of readSSE(stream)) {
|
|
148
137
|
if (controller.signal.aborted) {
|
|
@@ -201,8 +190,8 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
201
190
|
}, [client, disconnect, podId, setTaskStatus]);
|
|
202
191
|
const start = useCallback(async (input) => {
|
|
203
192
|
setError(null);
|
|
204
|
-
client
|
|
205
|
-
const created = await
|
|
193
|
+
const scopedClient = resolvePodClient(client, resolvePodId(client, podId));
|
|
194
|
+
const created = await scopedClient.tasks.create({
|
|
206
195
|
agent_name: input.agentName,
|
|
207
196
|
input_data: input.inputData,
|
|
208
197
|
});
|
|
@@ -221,8 +210,8 @@ export function useTaskSession({ client, podId, taskId: externalTaskId = null, a
|
|
|
221
210
|
if (!id)
|
|
222
211
|
return null;
|
|
223
212
|
try {
|
|
224
|
-
client
|
|
225
|
-
const stopped = await
|
|
213
|
+
const scopedClient = resolvePodClient(client, resolvePodId(client, podId));
|
|
214
|
+
const stopped = await scopedClient.tasks.stop(id);
|
|
226
215
|
setTask(stopped);
|
|
227
216
|
setTaskStatus(stopped.status);
|
|
228
217
|
return stopped;
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { useCallback, useMemo, useState } from "react";
|
|
2
|
-
|
|
3
|
-
if (!podId || podId === client.podId)
|
|
4
|
-
return client;
|
|
5
|
-
return client.withPod(podId);
|
|
6
|
-
}
|
|
7
|
-
function normalizeError(error, fallback) {
|
|
8
|
-
if (error instanceof Error)
|
|
9
|
-
return error;
|
|
10
|
-
return new Error(fallback);
|
|
11
|
-
}
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { normalizeError, resolvePodClient } from "./utils.js";
|
|
12
3
|
export function useUpdateRecord({ client, podId, tableName, recordId = null, enabled = true, onSuccess, onError, }) {
|
|
13
4
|
const [updatedRecord, setUpdatedRecord] = useState(null);
|
|
14
5
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
15
6
|
const [error, setError] = useState(null);
|
|
7
|
+
const onSuccessRef = useRef(onSuccess);
|
|
8
|
+
const onErrorRef = useRef(onError);
|
|
9
|
+
useEffect(() => { onSuccessRef.current = onSuccess; }, [onSuccess]);
|
|
10
|
+
useEffect(() => { onErrorRef.current = onError; }, [onError]);
|
|
16
11
|
const trimmedTableName = tableName.trim();
|
|
17
12
|
const trimmedRecordId = typeof recordId === "string" ? recordId.trim() : "";
|
|
18
13
|
const isEnabled = enabled && trimmedTableName.length > 0;
|
|
@@ -21,8 +16,6 @@ export function useUpdateRecord({ client, podId, tableName, recordId = null, ena
|
|
|
21
16
|
? overrides.recordId.trim()
|
|
22
17
|
: trimmedRecordId;
|
|
23
18
|
if (!isEnabled || nextRecordId.length === 0) {
|
|
24
|
-
const disabledError = new Error("Record update requires a table and record ID.");
|
|
25
|
-
setError(disabledError);
|
|
26
19
|
return null;
|
|
27
20
|
}
|
|
28
21
|
setIsSubmitting(true);
|
|
@@ -33,20 +26,20 @@ export function useUpdateRecord({ client, podId, tableName, recordId = null, ena
|
|
|
33
26
|
const nextRecord = (response.data ?? null);
|
|
34
27
|
setUpdatedRecord(nextRecord);
|
|
35
28
|
if (nextRecord) {
|
|
36
|
-
|
|
29
|
+
onSuccessRef.current?.(nextRecord, response);
|
|
37
30
|
}
|
|
38
31
|
return nextRecord;
|
|
39
32
|
}
|
|
40
33
|
catch (mutationError) {
|
|
41
34
|
const normalized = normalizeError(mutationError, "Failed to update record.");
|
|
42
35
|
setError(normalized);
|
|
43
|
-
|
|
36
|
+
onErrorRef.current?.(mutationError);
|
|
44
37
|
return null;
|
|
45
38
|
}
|
|
46
39
|
finally {
|
|
47
40
|
setIsSubmitting(false);
|
|
48
41
|
}
|
|
49
|
-
}, [client, isEnabled,
|
|
42
|
+
}, [client, isEnabled, podId, trimmedRecordId, trimmedTableName]);
|
|
50
43
|
const reset = useCallback(() => {
|
|
51
44
|
setUpdatedRecord(null);
|
|
52
45
|
setError(null);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LemmaClient } from "../client.js";
|
|
2
|
+
import type { FlowRun, WorkflowRunInputs } from "../types.js";
|
|
3
|
+
export interface UseWorkflowResumeOptions {
|
|
4
|
+
client: LemmaClient;
|
|
5
|
+
podId?: string;
|
|
6
|
+
runId?: string | null;
|
|
7
|
+
onRun?: (run: FlowRun) => void;
|
|
8
|
+
onError?: (error: unknown) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface UseWorkflowResumeResult {
|
|
11
|
+
run: FlowRun | null;
|
|
12
|
+
isResuming: boolean;
|
|
13
|
+
error: Error | null;
|
|
14
|
+
resume: (inputs?: WorkflowRunInputs, options?: {
|
|
15
|
+
runId?: string | null;
|
|
16
|
+
}) => Promise<FlowRun>;
|
|
17
|
+
}
|
|
18
|
+
export declare function useWorkflowResume({ client, podId, runId, onRun, onError, }: UseWorkflowResumeOptions): UseWorkflowResumeResult;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { normalizeError, resolvePodId } from "./utils.js";
|
|
3
|
+
function resolveRunId(base, override) {
|
|
4
|
+
const resolved = override ?? base;
|
|
5
|
+
if (!resolved) {
|
|
6
|
+
throw new Error("runId is required.");
|
|
7
|
+
}
|
|
8
|
+
return resolved;
|
|
9
|
+
}
|
|
10
|
+
export function useWorkflowResume({ client, podId, runId, onRun, onError, }) {
|
|
11
|
+
const [run, setRun] = useState(null);
|
|
12
|
+
const [isResuming, setIsResuming] = useState(false);
|
|
13
|
+
const [error, setError] = useState(null);
|
|
14
|
+
const onRunRef = useRef(onRun);
|
|
15
|
+
const onErrorRef = useRef(onError);
|
|
16
|
+
useEffect(() => { onRunRef.current = onRun; }, [onRun]);
|
|
17
|
+
useEffect(() => { onErrorRef.current = onError; }, [onError]);
|
|
18
|
+
const resume = useCallback(async (inputs = {}, options = {}) => {
|
|
19
|
+
setIsResuming(true);
|
|
20
|
+
setError(null);
|
|
21
|
+
try {
|
|
22
|
+
const resolvedPodId = resolvePodId(client, podId);
|
|
23
|
+
const resolvedRunId = resolveRunId(runId, options.runId);
|
|
24
|
+
const nextRun = await client.workflows.runs.resume(resolvedRunId, inputs, resolvedPodId);
|
|
25
|
+
setRun(nextRun);
|
|
26
|
+
onRunRef.current?.(nextRun);
|
|
27
|
+
return nextRun;
|
|
28
|
+
}
|
|
29
|
+
catch (resumeError) {
|
|
30
|
+
const normalized = normalizeError(resumeError, "Failed to resume workflow run.");
|
|
31
|
+
setError(normalized);
|
|
32
|
+
onErrorRef.current?.(resumeError);
|
|
33
|
+
throw normalized;
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
setIsResuming(false);
|
|
37
|
+
}
|
|
38
|
+
}, [client, podId, runId]);
|
|
39
|
+
return useMemo(() => ({
|
|
40
|
+
run,
|
|
41
|
+
isResuming,
|
|
42
|
+
error,
|
|
43
|
+
resume,
|
|
44
|
+
}), [error, isResuming, resume, run]);
|
|
45
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FlowRun, WorkflowRunInputs } from "../types.js";
|
|
2
|
+
import { type UseFlowSessionOptions, type UseFlowSessionResult } from "./useFlowSession.js";
|
|
3
|
+
export interface UseWorkflowRunOptions extends Omit<UseFlowSessionOptions, "flowName"> {
|
|
4
|
+
workflowName?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface UseWorkflowRunResult extends Omit<UseFlowSessionResult, "start" | "listHistory"> {
|
|
7
|
+
output: FlowRun["execution_context"] | null;
|
|
8
|
+
finalOutput: FlowRun["execution_context"] | null;
|
|
9
|
+
isWaitingForInput: boolean;
|
|
10
|
+
isFinished: boolean;
|
|
11
|
+
start: (inputs?: WorkflowRunInputs, options?: {
|
|
12
|
+
workflowName?: string;
|
|
13
|
+
connect?: boolean;
|
|
14
|
+
}) => Promise<FlowRun>;
|
|
15
|
+
listRuns: (options?: {
|
|
16
|
+
workflowName?: string;
|
|
17
|
+
limit?: number;
|
|
18
|
+
pageToken?: string;
|
|
19
|
+
}) => Promise<FlowRun[]>;
|
|
20
|
+
}
|
|
21
|
+
export declare function useWorkflowRun({ workflowName, ...options }: UseWorkflowRunOptions): UseWorkflowRunResult;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
import { isTerminalFlowStatus, normalizeRunStatus } from "../run-utils.js";
|
|
3
|
+
import { useFlowSession, } from "./useFlowSession.js";
|
|
4
|
+
function resolveWorkflowName(base, override) {
|
|
5
|
+
const resolved = override ?? base;
|
|
6
|
+
if (!resolved) {
|
|
7
|
+
throw new Error("workflowName is required.");
|
|
8
|
+
}
|
|
9
|
+
return resolved;
|
|
10
|
+
}
|
|
11
|
+
export function useWorkflowRun({ workflowName, ...options }) {
|
|
12
|
+
const session = useFlowSession({
|
|
13
|
+
...options,
|
|
14
|
+
flowName: workflowName,
|
|
15
|
+
});
|
|
16
|
+
const start = useCallback(async (inputs, startOptions = {}) => {
|
|
17
|
+
return session.start({
|
|
18
|
+
flowName: resolveWorkflowName(workflowName, startOptions.workflowName),
|
|
19
|
+
inputs,
|
|
20
|
+
connect: startOptions.connect,
|
|
21
|
+
});
|
|
22
|
+
}, [session, workflowName]);
|
|
23
|
+
const listRuns = useCallback(async (listOptions = {}) => {
|
|
24
|
+
return session.listHistory({
|
|
25
|
+
flowName: resolveWorkflowName(workflowName, listOptions.workflowName),
|
|
26
|
+
limit: listOptions.limit,
|
|
27
|
+
pageToken: listOptions.pageToken,
|
|
28
|
+
});
|
|
29
|
+
}, [session, workflowName]);
|
|
30
|
+
return useMemo(() => {
|
|
31
|
+
const normalizedStatus = normalizeRunStatus(session.status);
|
|
32
|
+
const isFinished = isTerminalFlowStatus(normalizedStatus);
|
|
33
|
+
const isWaitingForInput = normalizedStatus === "WAITING"
|
|
34
|
+
|| !!session.run?.waiting_task_id
|
|
35
|
+
|| !!session.run?.waiting_function_run_id
|
|
36
|
+
|| !!session.run?.waiting_trigger_id;
|
|
37
|
+
const output = session.run?.execution_context ?? null;
|
|
38
|
+
const finalOutput = isFinished ? output : null;
|
|
39
|
+
return {
|
|
40
|
+
...session,
|
|
41
|
+
output,
|
|
42
|
+
finalOutput,
|
|
43
|
+
isWaitingForInput,
|
|
44
|
+
isFinished,
|
|
45
|
+
start,
|
|
46
|
+
listRuns,
|
|
47
|
+
};
|
|
48
|
+
}, [listRuns, session, start]);
|
|
49
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LemmaClient } from "../client.js";
|
|
2
|
+
import type { FlowRun } from "../types.js";
|
|
3
|
+
export interface UseWorkflowRunsOptions {
|
|
4
|
+
client: LemmaClient;
|
|
5
|
+
podId?: string;
|
|
6
|
+
workflowName: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
autoLoad?: boolean;
|
|
9
|
+
limit?: number;
|
|
10
|
+
pageToken?: string;
|
|
11
|
+
initialRunId?: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface UseWorkflowRunsResult {
|
|
14
|
+
runs: FlowRun[];
|
|
15
|
+
total: number;
|
|
16
|
+
nextPageToken: string | null;
|
|
17
|
+
selectedRunId: string | null;
|
|
18
|
+
effectiveSelectedRunId: string | null;
|
|
19
|
+
selectedRun: FlowRun | null;
|
|
20
|
+
isLoading: boolean;
|
|
21
|
+
isLoadingMore: boolean;
|
|
22
|
+
error: Error | null;
|
|
23
|
+
selectRun: (runId: string | null) => void;
|
|
24
|
+
clearSelection: () => void;
|
|
25
|
+
refresh: (overrides?: {
|
|
26
|
+
limit?: number;
|
|
27
|
+
pageToken?: string;
|
|
28
|
+
}) => Promise<FlowRun[]>;
|
|
29
|
+
loadMore: (overrides?: {
|
|
30
|
+
limit?: number;
|
|
31
|
+
}) => Promise<FlowRun[]>;
|
|
32
|
+
}
|
|
33
|
+
export declare function useWorkflowRuns({ client, podId, workflowName, enabled, autoLoad, limit, pageToken, initialRunId, }: UseWorkflowRunsOptions): UseWorkflowRunsResult;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { normalizeError, resolvePodClient } from "./utils.js";
|
|
3
|
+
export function useWorkflowRuns({ client, podId, workflowName, enabled = true, autoLoad = true, limit = 100, pageToken, initialRunId = null, }) {
|
|
4
|
+
const [runs, setRuns] = useState([]);
|
|
5
|
+
const [total, setTotal] = useState(0);
|
|
6
|
+
const [nextPageToken, setNextPageToken] = useState(null);
|
|
7
|
+
const [selectedRunId, setSelectedRunId] = useState(initialRunId);
|
|
8
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
9
|
+
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
10
|
+
const [error, setError] = useState(null);
|
|
11
|
+
const trimmedWorkflowName = workflowName.trim();
|
|
12
|
+
const isEnabled = enabled && trimmedWorkflowName.length > 0;
|
|
13
|
+
const refresh = useCallback(async (overrides = {}, signal) => {
|
|
14
|
+
if (!isEnabled) {
|
|
15
|
+
setRuns([]);
|
|
16
|
+
setTotal(0);
|
|
17
|
+
setNextPageToken(null);
|
|
18
|
+
setError(null);
|
|
19
|
+
setIsLoading(false);
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
setIsLoading(true);
|
|
23
|
+
setError(null);
|
|
24
|
+
try {
|
|
25
|
+
const scopedClient = resolvePodClient(client, podId);
|
|
26
|
+
const response = await scopedClient.workflows.runs.list(trimmedWorkflowName, {
|
|
27
|
+
limit: overrides.limit ?? limit,
|
|
28
|
+
pageToken: overrides.pageToken ?? pageToken,
|
|
29
|
+
});
|
|
30
|
+
if (signal?.aborted)
|
|
31
|
+
return [];
|
|
32
|
+
const nextRuns = response.items ?? [];
|
|
33
|
+
setRuns(nextRuns);
|
|
34
|
+
setTotal(response.total ?? nextRuns.length);
|
|
35
|
+
setNextPageToken(response.next_page_token ?? null);
|
|
36
|
+
setSelectedRunId((current) => (current && nextRuns.some((run) => run.id === current) ? current : initialRunId));
|
|
37
|
+
return nextRuns;
|
|
38
|
+
}
|
|
39
|
+
catch (refreshError) {
|
|
40
|
+
if (signal?.aborted)
|
|
41
|
+
return [];
|
|
42
|
+
const normalized = normalizeError(refreshError, "Failed to load workflow runs.");
|
|
43
|
+
setError(normalized);
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
if (!signal?.aborted)
|
|
48
|
+
setIsLoading(false);
|
|
49
|
+
}
|
|
50
|
+
}, [client, initialRunId, isEnabled, limit, pageToken, podId, trimmedWorkflowName]);
|
|
51
|
+
const loadMore = useCallback(async (overrides = {}) => {
|
|
52
|
+
if (!isEnabled || !nextPageToken || isLoading || isLoadingMore) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
setIsLoadingMore(true);
|
|
56
|
+
setError(null);
|
|
57
|
+
try {
|
|
58
|
+
const scopedClient = resolvePodClient(client, podId);
|
|
59
|
+
const response = await scopedClient.workflows.runs.list(trimmedWorkflowName, {
|
|
60
|
+
limit: overrides.limit ?? limit,
|
|
61
|
+
pageToken: nextPageToken,
|
|
62
|
+
});
|
|
63
|
+
const moreRuns = response.items ?? [];
|
|
64
|
+
setRuns((previous) => [...previous, ...moreRuns]);
|
|
65
|
+
setTotal(response.total ?? runs.length + moreRuns.length);
|
|
66
|
+
setNextPageToken(response.next_page_token ?? null);
|
|
67
|
+
return moreRuns;
|
|
68
|
+
}
|
|
69
|
+
catch (loadError) {
|
|
70
|
+
const normalized = normalizeError(loadError, "Failed to load more workflow runs.");
|
|
71
|
+
setError(normalized);
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
setIsLoadingMore(false);
|
|
76
|
+
}
|
|
77
|
+
}, [client, isEnabled, isLoading, isLoadingMore, limit, nextPageToken, podId, trimmedWorkflowName]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
setSelectedRunId(initialRunId);
|
|
80
|
+
}, [initialRunId]);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (!isEnabled) {
|
|
83
|
+
setRuns([]);
|
|
84
|
+
setTotal(0);
|
|
85
|
+
setNextPageToken(null);
|
|
86
|
+
setError(null);
|
|
87
|
+
setIsLoading(false);
|
|
88
|
+
setIsLoadingMore(false);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!autoLoad)
|
|
92
|
+
return;
|
|
93
|
+
const controller = new AbortController();
|
|
94
|
+
let cancelled = false;
|
|
95
|
+
(async () => {
|
|
96
|
+
try {
|
|
97
|
+
await refresh({}, controller.signal);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
if (!cancelled) {
|
|
101
|
+
setError(normalizeError(new Error("Failed to load workflow runs."), "Failed to load workflow runs."));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
105
|
+
return () => {
|
|
106
|
+
cancelled = true;
|
|
107
|
+
controller.abort();
|
|
108
|
+
};
|
|
109
|
+
}, [autoLoad, isEnabled, refresh]);
|
|
110
|
+
const selectRun = useCallback((runId) => {
|
|
111
|
+
setSelectedRunId(runId);
|
|
112
|
+
}, []);
|
|
113
|
+
const clearSelection = useCallback(() => {
|
|
114
|
+
setSelectedRunId(null);
|
|
115
|
+
}, []);
|
|
116
|
+
return useMemo(() => {
|
|
117
|
+
const effectiveSelectedRunId = selectedRunId ?? runs[0]?.id ?? null;
|
|
118
|
+
const selectedRun = effectiveSelectedRunId
|
|
119
|
+
? runs.find((run) => run.id === effectiveSelectedRunId) ?? null
|
|
120
|
+
: null;
|
|
121
|
+
return {
|
|
122
|
+
runs,
|
|
123
|
+
total,
|
|
124
|
+
nextPageToken,
|
|
125
|
+
selectedRunId,
|
|
126
|
+
effectiveSelectedRunId,
|
|
127
|
+
selectedRun,
|
|
128
|
+
isLoading,
|
|
129
|
+
isLoadingMore,
|
|
130
|
+
error,
|
|
131
|
+
selectRun,
|
|
132
|
+
clearSelection,
|
|
133
|
+
refresh,
|
|
134
|
+
loadMore,
|
|
135
|
+
};
|
|
136
|
+
}, [
|
|
137
|
+
clearSelection,
|
|
138
|
+
error,
|
|
139
|
+
isLoading,
|
|
140
|
+
isLoadingMore,
|
|
141
|
+
loadMore,
|
|
142
|
+
nextPageToken,
|
|
143
|
+
refresh,
|
|
144
|
+
runs,
|
|
145
|
+
selectRun,
|
|
146
|
+
selectedRunId,
|
|
147
|
+
total,
|
|
148
|
+
]);
|
|
149
|
+
}
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from "react";
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { normalizeRunStatus } from "../run-utils.js";
|
|
3
|
+
import { normalizeError, resolvePodClient } from "./utils.js";
|
|
3
4
|
import { useFlowSession, } from "./useFlowSession.js";
|
|
4
|
-
function normalizeError(error, fallback) {
|
|
5
|
-
if (error instanceof Error)
|
|
6
|
-
return error;
|
|
7
|
-
return new Error(fallback);
|
|
8
|
-
}
|
|
9
|
-
function resolvePodClient(client, podId) {
|
|
10
|
-
if (!podId || podId === client.podId)
|
|
11
|
-
return client;
|
|
12
|
-
return client.withPod(podId);
|
|
13
|
-
}
|
|
14
5
|
function findFirstFormNode(workflow) {
|
|
15
6
|
if (!workflow?.nodes?.length)
|
|
16
7
|
return null;
|
|
@@ -136,20 +127,22 @@ export function useWorkflowStart({ client, podId, workflowName, runId = null, en
|
|
|
136
127
|
setIsStarting(false);
|
|
137
128
|
}
|
|
138
129
|
}, [hasWorkflowName, refreshWorkflow, session, workflow, workflowName]);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
130
|
+
return useMemo(() => {
|
|
131
|
+
const formNode = findFirstFormNode(workflow);
|
|
132
|
+
const startType = workflow?.start?.type ?? "MANUAL";
|
|
133
|
+
const error = workflowError ?? session.error;
|
|
134
|
+
return {
|
|
135
|
+
...session,
|
|
136
|
+
workflow,
|
|
137
|
+
startType,
|
|
138
|
+
inputSchema: formNode?.config.input_schema ?? null,
|
|
139
|
+
inputUiSchema: formNode?.config.ui_schema ?? null,
|
|
140
|
+
isLoadingWorkflow,
|
|
141
|
+
isStarting,
|
|
142
|
+
error,
|
|
143
|
+
refreshWorkflow,
|
|
144
|
+
listHistory,
|
|
145
|
+
start,
|
|
146
|
+
};
|
|
147
|
+
}, [isStarting, isLoadingWorkflow, listHistory, refreshWorkflow, session, start, workflow, workflowError]);
|
|
155
148
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LemmaClient } from "../client.js";
|
|
2
|
+
export declare function normalizeError(error: unknown, fallback: string): Error;
|
|
3
|
+
export declare function resolvePodClient(client: LemmaClient, podId?: string): LemmaClient;
|
|
4
|
+
export declare function resolvePodId(client: LemmaClient, podId?: string): string;
|
|
5
|
+
export declare function stringifyComparable(value: unknown): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function normalizeError(error, fallback) {
|
|
2
|
+
if (error instanceof Error)
|
|
3
|
+
return error;
|
|
4
|
+
return new Error(fallback);
|
|
5
|
+
}
|
|
6
|
+
export function resolvePodClient(client, podId) {
|
|
7
|
+
if (!podId || podId === client.podId)
|
|
8
|
+
return client;
|
|
9
|
+
return client.withPod(podId);
|
|
10
|
+
}
|
|
11
|
+
export function resolvePodId(client, podId) {
|
|
12
|
+
const resolved = podId ?? client.podId;
|
|
13
|
+
if (!resolved) {
|
|
14
|
+
throw new Error("podId is required. Pass podId or set it on LemmaClient.");
|
|
15
|
+
}
|
|
16
|
+
return resolved;
|
|
17
|
+
}
|
|
18
|
+
export function stringifyComparable(value) {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.stringify(value);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
25
|
+
}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lemma-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"description": "Official TypeScript SDK for Lemma pod-scoped APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"generate:client": "./scripts/generate_openapi_client.sh",
|
|
44
44
|
"build": "npm run clean && tsc -p tsconfig.json && npm run build:bundle",
|
|
45
45
|
"build:bundle": "tsc -p tsconfig.bundle.json && node ./scripts/build_browser_bundle.mjs",
|
|
46
|
-
"clean": "
|
|
46
|
+
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true, maxRetries: 10, retryDelay: 100 })\"",
|
|
47
47
|
"registry:build": "shadcn build ./registry.json -o ./public/r",
|
|
48
48
|
"prepublishOnly": "npm run build",
|
|
49
49
|
"release:check": "npm run build && npm_config_cache=.npm-cache npm pack --dry-run"
|
|
@@ -57,8 +57,6 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"react-markdown": "^10.1.0",
|
|
61
|
-
"remark-gfm": "^4.0.1",
|
|
62
60
|
"supertokens-web-js": "^0.16.0"
|
|
63
61
|
},
|
|
64
62
|
"devDependencies": {
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
-
import type { AssistantConversationListItem, AssistantConversationRenderArgs } from "./assistant-types.js";
|
|
3
|
-
export type AssistantSurfaceTone = "default" | "subtle" | "flat";
|
|
4
|
-
export type AssistantThemeMode = "auto" | "light" | "dark";
|
|
5
|
-
export interface AssistantThemeScopeProps extends ComponentPropsWithoutRef<"div"> {
|
|
6
|
-
children: ReactNode;
|
|
7
|
-
theme?: AssistantThemeMode;
|
|
8
|
-
}
|
|
9
|
-
export declare function AssistantThemeScope({ className, children, theme, ...props }: AssistantThemeScopeProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export interface AssistantHeaderProps {
|
|
11
|
-
title: ReactNode;
|
|
12
|
-
subtitle?: ReactNode;
|
|
13
|
-
badge?: ReactNode;
|
|
14
|
-
controls?: ReactNode;
|
|
15
|
-
tone?: AssistantSurfaceTone;
|
|
16
|
-
className?: string;
|
|
17
|
-
}
|
|
18
|
-
export interface AssistantMessageViewportProps extends ComponentPropsWithoutRef<"div"> {
|
|
19
|
-
innerClassName?: string;
|
|
20
|
-
children: ReactNode;
|
|
21
|
-
}
|
|
22
|
-
export declare const AssistantMessageViewport: import("react").ForwardRefExoticComponent<AssistantMessageViewportProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
23
|
-
export interface AssistantShellLayoutProps {
|
|
24
|
-
sidebar?: ReactNode;
|
|
25
|
-
sidebarVisible?: boolean;
|
|
26
|
-
main: ReactNode;
|
|
27
|
-
className?: string;
|
|
28
|
-
}
|
|
29
|
-
export declare function AssistantShellLayout({ sidebar, sidebarVisible, main, className, }: AssistantShellLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
-
export declare function AssistantHeader({ title, subtitle, badge, controls, tone, className, }: AssistantHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
-
export interface AssistantConversationListProps {
|
|
32
|
-
conversations: AssistantConversationListItem[];
|
|
33
|
-
activeConversationId: string | null;
|
|
34
|
-
onSelectConversation: (conversationId: string) => void;
|
|
35
|
-
onNewConversation?: () => void;
|
|
36
|
-
renderConversationLabel?: (args: AssistantConversationRenderArgs) => ReactNode;
|
|
37
|
-
title?: ReactNode;
|
|
38
|
-
newLabel?: ReactNode;
|
|
39
|
-
className?: string;
|
|
40
|
-
}
|
|
41
|
-
export declare function AssistantConversationList({ conversations, activeConversationId, onSelectConversation, onNewConversation, renderConversationLabel, title, newLabel, className, }: AssistantConversationListProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
-
export interface AssistantModelPickerProps<TValue extends string = string> {
|
|
43
|
-
value: TValue | null;
|
|
44
|
-
options: TValue[];
|
|
45
|
-
disabled?: boolean;
|
|
46
|
-
autoLabel?: ReactNode;
|
|
47
|
-
getOptionLabel?: (value: TValue) => ReactNode;
|
|
48
|
-
onChange: (value: TValue | null) => void;
|
|
49
|
-
className?: string;
|
|
50
|
-
}
|
|
51
|
-
export declare function AssistantModelPicker<TValue extends string = string>({ value, options, disabled, autoLabel, getOptionLabel, onChange, className, }: AssistantModelPickerProps<TValue>): import("react/jsx-runtime").JSX.Element;
|
|
52
|
-
export interface AssistantAskOverlayProps {
|
|
53
|
-
questionNumber: number;
|
|
54
|
-
totalQuestions: number;
|
|
55
|
-
question: ReactNode;
|
|
56
|
-
options: string[];
|
|
57
|
-
selectedOptions: string[];
|
|
58
|
-
canContinue: boolean;
|
|
59
|
-
continueLabel: ReactNode;
|
|
60
|
-
onSelectOption: (option: string) => void;
|
|
61
|
-
onContinue?: () => void;
|
|
62
|
-
onSkip?: () => void;
|
|
63
|
-
mode?: "single_select" | "multi_select" | "rank_priorities";
|
|
64
|
-
}
|
|
65
|
-
export declare function AssistantAskOverlay({ questionNumber, totalQuestions, question, options, selectedOptions, canContinue, continueLabel, onSelectOption, onContinue, onSkip, mode, }: AssistantAskOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
66
|
-
export interface AssistantPendingFileChipProps {
|
|
67
|
-
label: ReactNode;
|
|
68
|
-
onRemove?: () => void;
|
|
69
|
-
className?: string;
|
|
70
|
-
}
|
|
71
|
-
export interface AssistantComposerProps {
|
|
72
|
-
floating?: ReactNode;
|
|
73
|
-
status?: ReactNode;
|
|
74
|
-
pendingFiles?: ReactNode;
|
|
75
|
-
children: ReactNode;
|
|
76
|
-
tone?: AssistantSurfaceTone;
|
|
77
|
-
className?: string;
|
|
78
|
-
}
|
|
79
|
-
export declare function AssistantComposer({ floating, status, pendingFiles, children, tone, className, }: AssistantComposerProps): import("react/jsx-runtime").JSX.Element;
|
|
80
|
-
export declare function AssistantPendingFileChip({ label, onRemove, className, }: AssistantPendingFileChipProps): import("react/jsx-runtime").JSX.Element;
|
|
81
|
-
export interface AssistantStatusPillProps {
|
|
82
|
-
label: ReactNode;
|
|
83
|
-
subtle?: boolean;
|
|
84
|
-
className?: string;
|
|
85
|
-
}
|
|
86
|
-
export declare function AssistantStatusPill({ label, subtle, className, }: AssistantStatusPillProps): import("react/jsx-runtime").JSX.Element;
|