lemma-sdk 0.2.28 → 0.2.30
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 +113 -233
- package/bin/lemma-sdk.js +108 -0
- package/dist/browser/lemma-client.js +125 -4
- package/dist/client.d.ts +2 -0
- package/dist/client.js +3 -0
- package/dist/config.d.ts +2 -2
- package/dist/config.js +2 -2
- package/dist/datastore-query.d.ts +54 -0
- package/dist/datastore-query.js +157 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +3 -0
- package/dist/namespaces/datastore.d.ts +9 -0
- package/dist/namespaces/datastore.js +13 -0
- package/dist/namespaces/records.d.ts +1 -1
- package/dist/openapi_client/index.d.ts +4 -0
- package/dist/openapi_client/index.js +1 -0
- package/dist/openapi_client/models/ConvertedArtifactResponse.d.ts +6 -0
- package/dist/openapi_client/models/ConvertedArtifactResponse.js +1 -0
- package/dist/openapi_client/models/ConvertedFileResponse.d.ts +10 -0
- package/dist/openapi_client/models/ConvertedFileResponse.js +1 -0
- package/dist/openapi_client/models/CreateFolderRequest.d.ts +3 -1
- package/dist/openapi_client/models/FlowRunEntity.d.ts +1 -0
- package/dist/openapi_client/models/ScheduledFlowStart.d.ts +3 -6
- package/dist/openapi_client/models/ScheduledFlowStartType.d.ts +4 -0
- package/dist/openapi_client/models/ScheduledFlowStartType.js +9 -0
- package/dist/openapi_client/models/WorkflowInstallRequest.d.ts +5 -0
- package/dist/openapi_client/models/WorkflowTimeInstallConfig.d.ts +19 -0
- package/dist/openapi_client/models/WorkflowTimeInstallConfig.js +1 -0
- package/dist/openapi_client/services/FilesService.d.ts +27 -1
- package/dist/openapi_client/services/FilesService.js +69 -1
- package/dist/openapi_client/services/WorkflowsService.d.ts +1 -1
- package/dist/openapi_client/services/WorkflowsService.js +1 -1
- package/dist/react/assistant-output.d.ts +6 -0
- package/dist/react/assistant-output.js +90 -0
- package/dist/react/index.d.ts +42 -8
- package/dist/react/index.js +21 -4
- package/dist/react/useAgentRun.d.ts +17 -0
- package/dist/react/useAgentRun.js +58 -0
- package/dist/react/useAssistantRun.d.ts +9 -0
- package/dist/react/useAssistantRun.js +19 -9
- package/dist/react/useAssistantSession.d.ts +5 -0
- package/dist/react/useAssistantSession.js +123 -70
- package/dist/react/useBulkRecords.d.ts +20 -0
- package/dist/react/useBulkRecords.js +72 -0
- package/dist/react/useConversation.d.ts +18 -0
- package/dist/react/useConversation.js +59 -0
- package/dist/react/useConversationMessages.d.ts +59 -0
- package/dist/react/useConversationMessages.js +167 -0
- package/dist/react/useConversations.d.ts +48 -0
- package/dist/react/useConversations.js +182 -0
- package/dist/react/useCreateRecord.d.ts +18 -0
- package/dist/react/useCreateRecord.js +58 -0
- package/dist/react/useDeleteRecord.d.ts +21 -0
- package/dist/react/useDeleteRecord.js +59 -0
- package/dist/react/useForeignKeyOptions.d.ts +31 -0
- package/dist/react/useForeignKeyOptions.js +150 -0
- package/dist/react/useJoinedRecords.d.ts +18 -0
- package/dist/react/useJoinedRecords.js +79 -0
- package/dist/react/useMembers.d.ts +22 -0
- package/dist/react/useMembers.js +59 -0
- package/dist/react/useRecord.d.ts +18 -0
- package/dist/react/useRecord.js +64 -0
- package/dist/react/useRecordForm.d.ts +42 -0
- package/dist/react/useRecordForm.js +238 -0
- package/dist/react/useRecordSchema.d.ts +20 -0
- package/dist/react/useRecordSchema.js +24 -0
- package/dist/react/useRecords.d.ts +18 -0
- package/dist/react/useRecords.js +106 -0
- package/dist/react/useRelatedRecords.d.ts +43 -0
- package/dist/react/useRelatedRecords.js +232 -0
- package/dist/react/useReverseRelatedRecords.d.ts +47 -0
- package/dist/react/useReverseRelatedRecords.js +226 -0
- package/dist/react/useSchemaForm.d.ts +24 -0
- package/dist/react/useSchemaForm.js +116 -0
- package/dist/react/useTable.d.ts +16 -0
- package/dist/react/useTable.js +59 -0
- package/dist/react/useTables.d.ts +22 -0
- package/dist/react/useTables.js +71 -0
- package/dist/react/useUpdateRecord.d.ts +21 -0
- package/dist/react/useUpdateRecord.js +62 -0
- package/dist/react/useWorkflowStart.d.ts +33 -0
- package/dist/react/useWorkflowStart.js +155 -0
- package/dist/record-form.d.ts +30 -0
- package/dist/record-form.js +199 -0
- package/dist/schema-form.d.ts +41 -0
- package/dist/schema-form.js +200 -0
- package/dist/types.d.ts +5 -1
- package/package.json +10 -5
- package/dist/react/styles.css +0 -2407
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
export function normalizeConversationStatus(status) {
|
|
5
|
+
if (typeof status !== "string")
|
|
6
|
+
return undefined;
|
|
7
|
+
const normalized = status.trim().toUpperCase();
|
|
8
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
9
|
+
}
|
|
10
|
+
export function isConversationRunningStatus(status) {
|
|
11
|
+
const normalized = normalizeConversationStatus(status);
|
|
12
|
+
if (!normalized)
|
|
13
|
+
return false;
|
|
14
|
+
return normalized === "RUNNING" || normalized === "IN_PROGRESS" || normalized === "PROCESSING";
|
|
15
|
+
}
|
|
16
|
+
function extractTextFromStructuredContentEntry(entry) {
|
|
17
|
+
if (typeof entry === "string")
|
|
18
|
+
return entry.trim();
|
|
19
|
+
if (!isRecord(entry))
|
|
20
|
+
return "";
|
|
21
|
+
if (typeof entry.text === "string")
|
|
22
|
+
return entry.text.trim();
|
|
23
|
+
if (typeof entry.content === "string")
|
|
24
|
+
return entry.content.trim();
|
|
25
|
+
if (typeof entry.value === "string")
|
|
26
|
+
return entry.value.trim();
|
|
27
|
+
if (Array.isArray(entry.content)) {
|
|
28
|
+
const nested = entry.content
|
|
29
|
+
.map((child) => extractTextFromStructuredContentEntry(child))
|
|
30
|
+
.filter((text) => text.length > 0)
|
|
31
|
+
.join("\n")
|
|
32
|
+
.trim();
|
|
33
|
+
if (nested.length > 0)
|
|
34
|
+
return nested;
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(entry.summary)) {
|
|
37
|
+
const summary = entry.summary
|
|
38
|
+
.map((child) => extractTextFromStructuredContentEntry(child))
|
|
39
|
+
.filter((text) => text.length > 0)
|
|
40
|
+
.join("\n")
|
|
41
|
+
.trim();
|
|
42
|
+
if (summary.length > 0)
|
|
43
|
+
return summary;
|
|
44
|
+
}
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
export function extractConversationMessageText(content) {
|
|
48
|
+
if (typeof content === "string")
|
|
49
|
+
return content.trim();
|
|
50
|
+
if (Array.isArray(content)) {
|
|
51
|
+
return content
|
|
52
|
+
.map((entry) => extractTextFromStructuredContentEntry(entry))
|
|
53
|
+
.filter((text) => text.length > 0)
|
|
54
|
+
.join("\n\n")
|
|
55
|
+
.trim();
|
|
56
|
+
}
|
|
57
|
+
if (!isRecord(content))
|
|
58
|
+
return "";
|
|
59
|
+
const directContent = content.content;
|
|
60
|
+
if (typeof directContent === "string")
|
|
61
|
+
return directContent.trim();
|
|
62
|
+
if (Array.isArray(directContent)) {
|
|
63
|
+
const text = directContent
|
|
64
|
+
.map((entry) => extractTextFromStructuredContentEntry(entry))
|
|
65
|
+
.filter((entry) => entry.length > 0)
|
|
66
|
+
.join("\n\n")
|
|
67
|
+
.trim();
|
|
68
|
+
if (text.length > 0)
|
|
69
|
+
return text;
|
|
70
|
+
}
|
|
71
|
+
if (typeof content.text === "string")
|
|
72
|
+
return content.text.trim();
|
|
73
|
+
return extractTextFromStructuredContentEntry(content);
|
|
74
|
+
}
|
|
75
|
+
export function sortConversationMessagesByCreatedAt(messages) {
|
|
76
|
+
return [...messages].sort((a, b) => {
|
|
77
|
+
const aTime = Number.isFinite(new Date(a.created_at).getTime()) ? new Date(a.created_at).getTime() : 0;
|
|
78
|
+
const bTime = Number.isFinite(new Date(b.created_at).getTime()) ? new Date(b.created_at).getTime() : 0;
|
|
79
|
+
return aTime - bTime;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
export function getLatestAssistantMessage(messages) {
|
|
83
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
84
|
+
const message = messages[index];
|
|
85
|
+
if (typeof message?.role === "string" && message.role.toLowerCase() === "assistant") {
|
|
86
|
+
return message;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -4,25 +4,59 @@ export { useAuth } from "./useAuth.js";
|
|
|
4
4
|
export type { UseAuthResult } from "./useAuth.js";
|
|
5
5
|
export { useAssistantRun } from "./useAssistantRun.js";
|
|
6
6
|
export type { UseAssistantRunOptions, UseAssistantRunResult } from "./useAssistantRun.js";
|
|
7
|
+
export { useConversations } from "./useConversations.js";
|
|
8
|
+
export type { UseConversationsOptions, UseConversationsResult } from "./useConversations.js";
|
|
9
|
+
export { useConversation } from "./useConversation.js";
|
|
10
|
+
export type { UseConversationOptions, UseConversationResult } from "./useConversation.js";
|
|
11
|
+
export { useConversationMessages } from "./useConversationMessages.js";
|
|
12
|
+
export type { UseConversationMessagesOptions, UseConversationMessagesResult, } from "./useConversationMessages.js";
|
|
13
|
+
export { useAgentRun } from "./useAgentRun.js";
|
|
14
|
+
export type { UseAgentRunOptions, UseAgentRunResult } from "./useAgentRun.js";
|
|
7
15
|
export { useAssistantSession } from "./useAssistantSession.js";
|
|
8
16
|
export type { CreateConversationInput, SendAssistantMessageOptions, UseAssistantSessionOptions, UseAssistantSessionResult, } from "./useAssistantSession.js";
|
|
9
17
|
export { useAssistantRuntime } from "./useAssistantRuntime.js";
|
|
10
18
|
export type { UseAssistantRuntimeOptions, UseAssistantRuntimeResult, } from "./useAssistantRuntime.js";
|
|
19
|
+
export { useMembers } from "./useMembers.js";
|
|
20
|
+
export type { UseMembersOptions, UseMembersResult } from "./useMembers.js";
|
|
21
|
+
export { useTables } from "./useTables.js";
|
|
22
|
+
export type { UseTablesOptions, UseTablesResult } from "./useTables.js";
|
|
23
|
+
export { useTable } from "./useTable.js";
|
|
24
|
+
export type { UseTableOptions, UseTableResult } from "./useTable.js";
|
|
25
|
+
export { useRecords } from "./useRecords.js";
|
|
26
|
+
export type { UseRecordsOptions, UseRecordsResult } from "./useRecords.js";
|
|
27
|
+
export { useRecord } from "./useRecord.js";
|
|
28
|
+
export type { UseRecordOptions, UseRecordResult } from "./useRecord.js";
|
|
29
|
+
export { useCreateRecord } from "./useCreateRecord.js";
|
|
30
|
+
export type { UseCreateRecordOptions, UseCreateRecordResult } from "./useCreateRecord.js";
|
|
31
|
+
export { useUpdateRecord } from "./useUpdateRecord.js";
|
|
32
|
+
export type { UseUpdateRecordOptions, UseUpdateRecordResult } from "./useUpdateRecord.js";
|
|
33
|
+
export { useDeleteRecord } from "./useDeleteRecord.js";
|
|
34
|
+
export type { UseDeleteRecordOptions, UseDeleteRecordResult } from "./useDeleteRecord.js";
|
|
35
|
+
export { useBulkRecords } from "./useBulkRecords.js";
|
|
36
|
+
export type { UseBulkRecordsOptions, UseBulkRecordsResult } from "./useBulkRecords.js";
|
|
37
|
+
export { useJoinedRecords } from "./useJoinedRecords.js";
|
|
38
|
+
export type { UseJoinedRecordsOptions, UseJoinedRecordsResult } from "./useJoinedRecords.js";
|
|
39
|
+
export { useRelatedRecords } from "./useRelatedRecords.js";
|
|
40
|
+
export type { RelatedRecordsColumn, RelatedRecordsInclude, RelatedRecordsResolvedInclude, UseRelatedRecordsOptions, UseRelatedRecordsResult, } from "./useRelatedRecords.js";
|
|
41
|
+
export { useReverseRelatedRecords } from "./useReverseRelatedRecords.js";
|
|
42
|
+
export type { ReverseRelatedRecordsColumn, ReverseRelatedRelation, ReverseRelationSelector, UseReverseRelatedRecordsOptions, UseReverseRelatedRecordsResult, } from "./useReverseRelatedRecords.js";
|
|
43
|
+
export { useForeignKeyOptions } from "./useForeignKeyOptions.js";
|
|
44
|
+
export type { ForeignKeyOption, UseForeignKeyOptionsOptions, UseForeignKeyOptionsResult, } from "./useForeignKeyOptions.js";
|
|
45
|
+
export { useRecordSchema } from "./useRecordSchema.js";
|
|
46
|
+
export type { UseRecordSchemaOptions, UseRecordSchemaResult } from "./useRecordSchema.js";
|
|
47
|
+
export { useRecordForm } from "./useRecordForm.js";
|
|
48
|
+
export type { UseRecordFormOptions, UseRecordFormResult } from "./useRecordForm.js";
|
|
49
|
+
export { useSchemaForm } from "./useSchemaForm.js";
|
|
50
|
+
export type { UseSchemaFormOptions, UseSchemaFormResult } from "./useSchemaForm.js";
|
|
11
51
|
export { useAssistantController } from "./useAssistantController.js";
|
|
12
52
|
export type { AssistantAction, AssistantConversationScope, AssistantMessagePart, AssistantRenderableMessage, AssistantToolInvocation, UseAssistantControllerOptions, UseAssistantControllerResult, } from "./useAssistantController.js";
|
|
13
|
-
export type { AssistantConversationRenderArgs, AssistantControllerView, AssistantExperienceCustomizationProps, AssistantMessageRenderArgs, EmptyStateSuggestion, AssistantPendingFileRenderArgs, AssistantPresentedFileRenderArgs, AssistantToolRenderArgs, } from "./components/assistant-types.js";
|
|
14
|
-
export { AssistantAskOverlay, AssistantComposer, AssistantConversationList, AssistantHeader, AssistantMessageViewport, AssistantModelPicker, AssistantPendingFileChip, AssistantShellLayout, AssistantStatusPill, AssistantThemeScope, } from "./components/AssistantChrome.js";
|
|
15
|
-
export type { AssistantAskOverlayProps, AssistantComposerProps, AssistantConversationListProps, AssistantHeaderProps, AssistantMessageViewportProps, AssistantModelPickerProps, AssistantPendingFileChipProps, AssistantShellLayoutProps, AssistantStatusPillProps, AssistantSurfaceTone, AssistantThemeMode, AssistantThemeScopeProps, } from "./components/AssistantChrome.js";
|
|
16
|
-
export { AssistantExperienceView } from "./components/AssistantExperience.js";
|
|
17
|
-
export type { ActiveToolBanner, AskUserInputQuestion, AssistantChromeStyle, AssistantExperienceViewProps, AssistantRadiusScale, AssistantStatusPlacement, DisplayMessageRow, EmptyStateProps, PendingAskUserInput, PlanStepState, PlanSummaryState, } from "./components/AssistantExperience.js";
|
|
18
|
-
export { AssistantEmbedded } from "./components/AssistantEmbedded.js";
|
|
19
|
-
export type { AssistantEmbeddedProps } from "./components/AssistantEmbedded.js";
|
|
20
|
-
export { buildDisplayMessageRows, DEFAULT_EMPTY_STATE_SUGGESTIONS, dedupToolInvocations, EmptyState, findPendingAskUserInput, formatAskUserInputAnswers, getActiveToolBanner, extractPresentFilePathsFromInvocation, latestPlanSummary, MessageGroup, PlanSummaryStrip, ThinkingIndicator, } from "./components/AssistantExperience.js";
|
|
21
53
|
export { useTaskSession } from "./useTaskSession.js";
|
|
22
54
|
export type { CreateTaskInput, UseTaskSessionOptions, UseTaskSessionResult, } from "./useTaskSession.js";
|
|
23
55
|
export { useFunctionSession } from "./useFunctionSession.js";
|
|
24
56
|
export type { UseFunctionSessionOptions, UseFunctionSessionResult, } from "./useFunctionSession.js";
|
|
25
57
|
export { useFlowSession } from "./useFlowSession.js";
|
|
26
58
|
export type { UseFlowSessionOptions, UseFlowSessionResult, } from "./useFlowSession.js";
|
|
59
|
+
export { useWorkflowStart } from "./useWorkflowStart.js";
|
|
60
|
+
export type { UseWorkflowStartOptions, UseWorkflowStartResult, } from "./useWorkflowStart.js";
|
|
27
61
|
export { useFlowRunHistory } from "./useFlowRunHistory.js";
|
|
28
62
|
export type { UseFlowRunHistoryOptions, UseFlowRunHistoryResult, } from "./useFlowRunHistory.js";
|
package/dist/react/index.js
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
export { AuthGuard } from "./AuthGuard.js";
|
|
2
2
|
export { useAuth } from "./useAuth.js";
|
|
3
3
|
export { useAssistantRun } from "./useAssistantRun.js";
|
|
4
|
+
export { useConversations } from "./useConversations.js";
|
|
5
|
+
export { useConversation } from "./useConversation.js";
|
|
6
|
+
export { useConversationMessages } from "./useConversationMessages.js";
|
|
7
|
+
export { useAgentRun } from "./useAgentRun.js";
|
|
4
8
|
export { useAssistantSession } from "./useAssistantSession.js";
|
|
5
9
|
export { useAssistantRuntime } from "./useAssistantRuntime.js";
|
|
10
|
+
export { useMembers } from "./useMembers.js";
|
|
11
|
+
export { useTables } from "./useTables.js";
|
|
12
|
+
export { useTable } from "./useTable.js";
|
|
13
|
+
export { useRecords } from "./useRecords.js";
|
|
14
|
+
export { useRecord } from "./useRecord.js";
|
|
15
|
+
export { useCreateRecord } from "./useCreateRecord.js";
|
|
16
|
+
export { useUpdateRecord } from "./useUpdateRecord.js";
|
|
17
|
+
export { useDeleteRecord } from "./useDeleteRecord.js";
|
|
18
|
+
export { useBulkRecords } from "./useBulkRecords.js";
|
|
19
|
+
export { useJoinedRecords } from "./useJoinedRecords.js";
|
|
20
|
+
export { useRelatedRecords } from "./useRelatedRecords.js";
|
|
21
|
+
export { useReverseRelatedRecords } from "./useReverseRelatedRecords.js";
|
|
22
|
+
export { useForeignKeyOptions } from "./useForeignKeyOptions.js";
|
|
23
|
+
export { useRecordSchema } from "./useRecordSchema.js";
|
|
24
|
+
export { useRecordForm } from "./useRecordForm.js";
|
|
25
|
+
export { useSchemaForm } from "./useSchemaForm.js";
|
|
6
26
|
export { useAssistantController } from "./useAssistantController.js";
|
|
7
|
-
export { AssistantAskOverlay, AssistantComposer, AssistantConversationList, AssistantHeader, AssistantMessageViewport, AssistantModelPicker, AssistantPendingFileChip, AssistantShellLayout, AssistantStatusPill, AssistantThemeScope, } from "./components/AssistantChrome.js";
|
|
8
|
-
export { AssistantExperienceView } from "./components/AssistantExperience.js";
|
|
9
|
-
export { AssistantEmbedded } from "./components/AssistantEmbedded.js";
|
|
10
|
-
export { buildDisplayMessageRows, DEFAULT_EMPTY_STATE_SUGGESTIONS, dedupToolInvocations, EmptyState, findPendingAskUserInput, formatAskUserInputAnswers, getActiveToolBanner, extractPresentFilePathsFromInvocation, latestPlanSummary, MessageGroup, PlanSummaryStrip, ThinkingIndicator, } from "./components/AssistantExperience.js";
|
|
11
27
|
export { useTaskSession } from "./useTaskSession.js";
|
|
12
28
|
export { useFunctionSession } from "./useFunctionSession.js";
|
|
13
29
|
export { useFlowSession } from "./useFlowSession.js";
|
|
30
|
+
export { useWorkflowStart } from "./useWorkflowStart.js";
|
|
14
31
|
export { useFlowRunHistory } from "./useFlowRunHistory.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Task } from "../types.js";
|
|
2
|
+
import { type UseTaskSessionOptions, type UseTaskSessionResult } from "./useTaskSession.js";
|
|
3
|
+
export interface UseAgentRunOptions extends Omit<UseTaskSessionOptions, "taskId"> {
|
|
4
|
+
agentName?: string;
|
|
5
|
+
taskId?: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface UseAgentRunResult extends Omit<UseTaskSessionResult, "start"> {
|
|
8
|
+
output: Task["output_data"];
|
|
9
|
+
finalOutput: Task["output_data"];
|
|
10
|
+
isWaitingForInput: boolean;
|
|
11
|
+
isFinished: boolean;
|
|
12
|
+
start: (inputData?: Record<string, unknown> | null, options?: {
|
|
13
|
+
agentName?: string;
|
|
14
|
+
}) => Promise<Task>;
|
|
15
|
+
submitInput: (content: string) => Promise<Task | null>;
|
|
16
|
+
}
|
|
17
|
+
export declare function useAgentRun({ client, podId, agentName, taskId, autoConnect, autoConnectOnStart, onEvent, onStatus, onMessage, onError, }: UseAgentRunOptions): UseAgentRunResult;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { isTerminalTaskStatus, normalizeRunStatus } from "../run-utils.js";
|
|
3
|
+
import { useTaskSession, } from "./useTaskSession.js";
|
|
4
|
+
function resolveAgentName(base, override) {
|
|
5
|
+
const resolved = override ?? base;
|
|
6
|
+
if (!resolved) {
|
|
7
|
+
throw new Error("agentName is required.");
|
|
8
|
+
}
|
|
9
|
+
return resolved;
|
|
10
|
+
}
|
|
11
|
+
function resolvePodClient(client, podId) {
|
|
12
|
+
if (!podId || podId === client.podId)
|
|
13
|
+
return client;
|
|
14
|
+
return client.withPod(podId);
|
|
15
|
+
}
|
|
16
|
+
export function useAgentRun({ client, podId, agentName, taskId = null, autoConnect = true, autoConnectOnStart = true, onEvent, onStatus, onMessage, onError, }) {
|
|
17
|
+
const session = useTaskSession({
|
|
18
|
+
client,
|
|
19
|
+
podId,
|
|
20
|
+
taskId,
|
|
21
|
+
autoConnect,
|
|
22
|
+
autoConnectOnStart,
|
|
23
|
+
onEvent,
|
|
24
|
+
onStatus,
|
|
25
|
+
onMessage,
|
|
26
|
+
onError,
|
|
27
|
+
});
|
|
28
|
+
const start = useCallback(async (inputData, options) => {
|
|
29
|
+
return session.start({
|
|
30
|
+
agentName: resolveAgentName(agentName, options?.agentName),
|
|
31
|
+
inputData: inputData ?? undefined,
|
|
32
|
+
});
|
|
33
|
+
}, [agentName, session]);
|
|
34
|
+
const submitInput = useCallback(async (content) => {
|
|
35
|
+
const resolvedTaskId = session.taskId;
|
|
36
|
+
if (!resolvedTaskId) {
|
|
37
|
+
throw new Error("taskId is required to submit additional agent input.");
|
|
38
|
+
}
|
|
39
|
+
const scopedClient = resolvePodClient(client, podId);
|
|
40
|
+
await scopedClient.tasks.messages.add(resolvedTaskId, { content });
|
|
41
|
+
await session.loadMessages(resolvedTaskId);
|
|
42
|
+
return session.refreshTask(resolvedTaskId);
|
|
43
|
+
}, [client, podId, session]);
|
|
44
|
+
const normalizedStatus = normalizeRunStatus(session.status);
|
|
45
|
+
const isFinished = isTerminalTaskStatus(normalizedStatus);
|
|
46
|
+
const isWaitingForInput = normalizedStatus === "WAITING";
|
|
47
|
+
const output = session.task?.output_data ?? null;
|
|
48
|
+
const finalOutput = isFinished ? output : null;
|
|
49
|
+
return {
|
|
50
|
+
...session,
|
|
51
|
+
output,
|
|
52
|
+
finalOutput,
|
|
53
|
+
isWaitingForInput,
|
|
54
|
+
isFinished,
|
|
55
|
+
start,
|
|
56
|
+
submitInput,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LemmaClient } from "../client.js";
|
|
2
2
|
import type { SseRawEvent } from "../streams.js";
|
|
3
|
+
import type { ConversationMessage } from "../types.js";
|
|
3
4
|
export interface UseAssistantRunOptions {
|
|
4
5
|
client: LemmaClient;
|
|
5
6
|
podId?: string;
|
|
@@ -10,6 +11,14 @@ export interface UseAssistantRunOptions {
|
|
|
10
11
|
export interface UseAssistantRunResult {
|
|
11
12
|
isStreaming: boolean;
|
|
12
13
|
error: Error | null;
|
|
14
|
+
status?: string;
|
|
15
|
+
messages: ConversationMessage[];
|
|
16
|
+
output: ConversationMessage["content"] | null;
|
|
17
|
+
outputText: string;
|
|
18
|
+
finalOutput: ConversationMessage["content"] | null;
|
|
19
|
+
finalOutputText: string;
|
|
20
|
+
latestAssistantMessage: ConversationMessage | null;
|
|
21
|
+
refresh: () => Promise<ConversationMessage[]>;
|
|
13
22
|
sendMessage: (content: string) => Promise<void>;
|
|
14
23
|
resume: () => Promise<void>;
|
|
15
24
|
stop: () => Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useConversationMessages } from "./useConversationMessages.js";
|
|
2
2
|
function requireConversationId(conversationId) {
|
|
3
3
|
if (!conversationId) {
|
|
4
4
|
throw new Error("conversationId is required.");
|
|
@@ -6,31 +6,41 @@ function requireConversationId(conversationId) {
|
|
|
6
6
|
return conversationId;
|
|
7
7
|
}
|
|
8
8
|
export function useAssistantRun({ client, podId, conversationId, onEvent, onError, }) {
|
|
9
|
-
const
|
|
9
|
+
const messages = useConversationMessages({
|
|
10
10
|
client,
|
|
11
11
|
podId,
|
|
12
12
|
conversationId,
|
|
13
|
+
autoLoad: true,
|
|
14
|
+
autoResume: false,
|
|
13
15
|
onEvent,
|
|
14
16
|
onError,
|
|
15
17
|
});
|
|
16
18
|
const sendMessage = async (content) => {
|
|
17
|
-
await
|
|
18
|
-
conversationId: requireConversationId(conversationId ??
|
|
19
|
+
await messages.sendMessage(content, {
|
|
20
|
+
conversationId: requireConversationId(conversationId ?? messages.conversationId),
|
|
19
21
|
createIfMissing: false,
|
|
20
22
|
});
|
|
21
23
|
};
|
|
22
24
|
const resume = async () => {
|
|
23
|
-
await
|
|
25
|
+
await messages.resume(requireConversationId(conversationId ?? messages.conversationId));
|
|
24
26
|
};
|
|
25
27
|
const stop = async () => {
|
|
26
|
-
await
|
|
28
|
+
await messages.stop(requireConversationId(conversationId ?? messages.conversationId));
|
|
27
29
|
};
|
|
28
30
|
return {
|
|
29
|
-
isStreaming:
|
|
30
|
-
error:
|
|
31
|
+
isStreaming: messages.isStreaming,
|
|
32
|
+
error: messages.error,
|
|
33
|
+
status: messages.status,
|
|
34
|
+
messages: messages.messages,
|
|
35
|
+
output: messages.output,
|
|
36
|
+
outputText: messages.outputText,
|
|
37
|
+
finalOutput: messages.finalOutput,
|
|
38
|
+
finalOutputText: messages.finalOutputText,
|
|
39
|
+
latestAssistantMessage: messages.latestAssistantMessage,
|
|
40
|
+
refresh: () => messages.refresh(),
|
|
31
41
|
sendMessage,
|
|
32
42
|
resume,
|
|
33
43
|
stop,
|
|
34
|
-
cancel:
|
|
44
|
+
cancel: messages.cancel,
|
|
35
45
|
};
|
|
36
46
|
}
|
|
@@ -59,6 +59,11 @@ export interface UseAssistantSessionResult {
|
|
|
59
59
|
conversation: Conversation | null;
|
|
60
60
|
status?: string;
|
|
61
61
|
messages: ConversationMessage[];
|
|
62
|
+
latestAssistantMessage: ConversationMessage | null;
|
|
63
|
+
output: ConversationMessage["content"] | null;
|
|
64
|
+
outputText: string;
|
|
65
|
+
finalOutput: ConversationMessage["content"] | null;
|
|
66
|
+
finalOutputText: string;
|
|
62
67
|
streamingText: string;
|
|
63
68
|
isStreaming: boolean;
|
|
64
69
|
error: Error | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { parseSSEJson, readSSE } from "../streams.js";
|
|
3
3
|
import { parseAssistantStreamEvent, upsertConversationMessage } from "../assistant-events.js";
|
|
4
|
+
import { extractConversationMessageText, getLatestAssistantMessage, } from "./assistant-output.js";
|
|
4
5
|
function resolveOptionalPodId(client, podId) {
|
|
5
6
|
return podId ?? client.podId;
|
|
6
7
|
}
|
|
@@ -140,6 +141,7 @@ export function useAssistantSession(options) {
|
|
|
140
141
|
organizationId: defaultOrganizationId ?? null,
|
|
141
142
|
}), [defaultAssistantId, defaultAssistantName, defaultOrganizationId, defaultPodId]);
|
|
142
143
|
const listConversations = useCallback(async (input = {}) => {
|
|
144
|
+
setError(null);
|
|
143
145
|
try {
|
|
144
146
|
const scope = normalizeScope(client, defaultScope, input.scope);
|
|
145
147
|
applyPodScope(client, scope.podId);
|
|
@@ -168,30 +170,39 @@ export function useAssistantSession(options) {
|
|
|
168
170
|
}
|
|
169
171
|
}, [client, defaultScope]);
|
|
170
172
|
const createConversation = useCallback(async (input = {}) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
: input.model
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
173
|
+
setError(null);
|
|
174
|
+
try {
|
|
175
|
+
applyPodScope(client, input.podId ?? defaultPodId ?? null);
|
|
176
|
+
const payload = {
|
|
177
|
+
title: input.title ?? undefined,
|
|
178
|
+
pod_id: input.podId ?? defaultPodId ?? client.podId ?? undefined,
|
|
179
|
+
assistant_name: input.assistantName
|
|
180
|
+
?? input.assistantId
|
|
181
|
+
?? defaultAssistantName
|
|
182
|
+
?? defaultAssistantId
|
|
183
|
+
?? undefined,
|
|
184
|
+
organization_id: input.organizationId ?? defaultOrganizationId ?? undefined,
|
|
185
|
+
model: typeof input.model === "undefined"
|
|
186
|
+
? undefined
|
|
187
|
+
: input.model,
|
|
188
|
+
};
|
|
189
|
+
const created = await client.conversations.create(payload);
|
|
190
|
+
if (input.setActive !== false) {
|
|
191
|
+
setConversationIdState(created.id);
|
|
192
|
+
setConversation(created);
|
|
193
|
+
setConversationStatus(created.status);
|
|
194
|
+
setMessages([]);
|
|
195
|
+
clearStreamingText();
|
|
196
|
+
autoResumedKeyRef.current = null;
|
|
197
|
+
}
|
|
198
|
+
return created;
|
|
199
|
+
}
|
|
200
|
+
catch (createError) {
|
|
201
|
+
const normalized = normalizeError(createError, "Failed to create conversation.");
|
|
202
|
+
setError(normalized);
|
|
203
|
+
onErrorRef.current?.(createError);
|
|
204
|
+
throw normalized;
|
|
193
205
|
}
|
|
194
|
-
return created;
|
|
195
206
|
}, [
|
|
196
207
|
clearStreamingText,
|
|
197
208
|
client,
|
|
@@ -205,6 +216,7 @@ export function useAssistantSession(options) {
|
|
|
205
216
|
const id = explicitConversationId ?? conversationId;
|
|
206
217
|
if (!id)
|
|
207
218
|
return null;
|
|
219
|
+
setError(null);
|
|
208
220
|
try {
|
|
209
221
|
const scope = normalizeScope(client, defaultScope);
|
|
210
222
|
applyPodScope(client, scope.podId);
|
|
@@ -230,6 +242,7 @@ export function useAssistantSession(options) {
|
|
|
230
242
|
if (!id) {
|
|
231
243
|
return { items: [], limit: input.limit ?? 20, next_page_token: null };
|
|
232
244
|
}
|
|
245
|
+
setError(null);
|
|
233
246
|
try {
|
|
234
247
|
const response = await client.conversations.messages.list(id, {
|
|
235
248
|
limit: input.limit,
|
|
@@ -351,48 +364,66 @@ export function useAssistantSession(options) {
|
|
|
351
364
|
});
|
|
352
365
|
}, [conversation, conversationId, createConversation, refreshConversation]);
|
|
353
366
|
const sendMessage = useCallback(async (content, input = {}) => {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
367
|
+
setError(null);
|
|
368
|
+
try {
|
|
369
|
+
const resolvedConversation = await ensureConversation(input.conversationId, input);
|
|
370
|
+
const resolvedConversationId = requireConversationId(resolvedConversation.id);
|
|
371
|
+
cancel();
|
|
372
|
+
const controller = new AbortController();
|
|
373
|
+
abortRef.current = controller;
|
|
374
|
+
const scope = normalizeScope(client, defaultScope, input.createConversation);
|
|
375
|
+
applyPodScope(client, scope.podId);
|
|
376
|
+
const stream = await client.conversations.sendMessageStream(resolvedConversationId, { content }, {
|
|
377
|
+
pod_id: scope.podId ?? undefined,
|
|
378
|
+
signal: controller.signal,
|
|
379
|
+
});
|
|
380
|
+
setConversationStatus("RUNNING");
|
|
381
|
+
await consume({
|
|
382
|
+
stream,
|
|
383
|
+
controller,
|
|
384
|
+
streamConversationId: resolvedConversationId,
|
|
385
|
+
syncAfterStream: input.syncOnTurnEnd,
|
|
386
|
+
});
|
|
387
|
+
return resolvedConversation;
|
|
388
|
+
}
|
|
389
|
+
catch (sendError) {
|
|
390
|
+
const normalized = normalizeError(sendError, "Failed to send assistant message.");
|
|
391
|
+
setError(normalized);
|
|
392
|
+
onErrorRef.current?.(sendError);
|
|
393
|
+
throw normalized;
|
|
394
|
+
}
|
|
373
395
|
}, [cancel, client, consume, defaultScope, ensureConversation, setConversationStatus]);
|
|
374
396
|
const resume = useCallback(async (input) => {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
397
|
+
setError(null);
|
|
398
|
+
try {
|
|
399
|
+
const resumeInput = resolveResumeInput(input);
|
|
400
|
+
const id = requireConversationId(resumeInput.conversationId ?? conversationId);
|
|
401
|
+
if (resumeInput.onlyIfRunning && !isConversationRunningStatus(statusRef.current)) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
cancel();
|
|
405
|
+
const controller = new AbortController();
|
|
406
|
+
abortRef.current = controller;
|
|
407
|
+
const scope = normalizeScope(client, defaultScope);
|
|
408
|
+
applyPodScope(client, scope.podId);
|
|
409
|
+
const stream = await client.conversations.resumeStream(id, {
|
|
410
|
+
pod_id: scope.podId ?? undefined,
|
|
411
|
+
signal: controller.signal,
|
|
412
|
+
});
|
|
413
|
+
setConversationStatus("RUNNING");
|
|
414
|
+
await consume({
|
|
415
|
+
stream,
|
|
416
|
+
controller,
|
|
417
|
+
streamConversationId: id,
|
|
418
|
+
syncAfterStream: resumeInput.syncOnTurnEnd,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
catch (resumeError) {
|
|
422
|
+
const normalized = normalizeError(resumeError, "Failed to resume assistant run.");
|
|
423
|
+
setError(normalized);
|
|
424
|
+
onErrorRef.current?.(resumeError);
|
|
425
|
+
throw normalized;
|
|
379
426
|
}
|
|
380
|
-
cancel();
|
|
381
|
-
const controller = new AbortController();
|
|
382
|
-
abortRef.current = controller;
|
|
383
|
-
const scope = normalizeScope(client, defaultScope);
|
|
384
|
-
applyPodScope(client, scope.podId);
|
|
385
|
-
const stream = await client.conversations.resumeStream(id, {
|
|
386
|
-
pod_id: scope.podId ?? undefined,
|
|
387
|
-
signal: controller.signal,
|
|
388
|
-
});
|
|
389
|
-
setConversationStatus("RUNNING");
|
|
390
|
-
await consume({
|
|
391
|
-
stream,
|
|
392
|
-
controller,
|
|
393
|
-
streamConversationId: id,
|
|
394
|
-
syncAfterStream: resumeInput.syncOnTurnEnd,
|
|
395
|
-
});
|
|
396
427
|
}, [cancel, client, consume, conversationId, defaultScope, setConversationStatus]);
|
|
397
428
|
const resumeIfRunning = useCallback(async (explicitConversationId) => {
|
|
398
429
|
const id = explicitConversationId ?? conversationId;
|
|
@@ -429,14 +460,23 @@ export function useAssistantSession(options) {
|
|
|
429
460
|
}
|
|
430
461
|
}, [conversationId, isStreaming, refreshConversation, resume]);
|
|
431
462
|
const stop = useCallback(async (explicitConversationId) => {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
463
|
+
setError(null);
|
|
464
|
+
try {
|
|
465
|
+
const id = requireConversationId(explicitConversationId ?? conversationId);
|
|
466
|
+
const scope = normalizeScope(client, defaultScope);
|
|
467
|
+
applyPodScope(client, scope.podId);
|
|
468
|
+
await client.conversations.stopRun(id, {
|
|
469
|
+
pod_id: scope.podId ?? undefined,
|
|
470
|
+
});
|
|
471
|
+
setConversationStatus("WAITING");
|
|
472
|
+
clearStreamingText();
|
|
473
|
+
}
|
|
474
|
+
catch (stopError) {
|
|
475
|
+
const normalized = normalizeError(stopError, "Failed to stop assistant run.");
|
|
476
|
+
setError(normalized);
|
|
477
|
+
onErrorRef.current?.(stopError);
|
|
478
|
+
throw normalized;
|
|
479
|
+
}
|
|
440
480
|
}, [client, conversationId, defaultScope]);
|
|
441
481
|
const clearMessages = useCallback(() => {
|
|
442
482
|
setMessages([]);
|
|
@@ -473,11 +513,24 @@ export function useAssistantSession(options) {
|
|
|
473
513
|
cancelled = true;
|
|
474
514
|
};
|
|
475
515
|
}, [autoLoad, autoResume, conversationId, loadMessages, refreshConversation, resumeIfRunning]);
|
|
516
|
+
const latestAssistantMessage = useMemo(() => getLatestAssistantMessage(messages), [messages]);
|
|
517
|
+
const output = latestAssistantMessage?.content ?? null;
|
|
518
|
+
const latestAssistantText = latestAssistantMessage
|
|
519
|
+
? extractConversationMessageText(latestAssistantMessage.content)
|
|
520
|
+
: "";
|
|
521
|
+
const outputText = streamingText.trim() || latestAssistantText;
|
|
522
|
+
const finalOutput = !isStreaming && !isConversationRunningStatus(status) ? output : null;
|
|
523
|
+
const finalOutputText = !isStreaming && !isConversationRunningStatus(status) ? latestAssistantText : "";
|
|
476
524
|
return {
|
|
477
525
|
conversationId,
|
|
478
526
|
conversation,
|
|
479
527
|
status,
|
|
480
528
|
messages,
|
|
529
|
+
latestAssistantMessage,
|
|
530
|
+
output,
|
|
531
|
+
outputText,
|
|
532
|
+
finalOutput,
|
|
533
|
+
finalOutputText,
|
|
481
534
|
streamingText,
|
|
482
535
|
isStreaming,
|
|
483
536
|
error,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LemmaClient } from "../client.js";
|
|
2
|
+
import type { DatastoreMessageResponse } from "../types.js";
|
|
3
|
+
export interface UseBulkRecordsOptions {
|
|
4
|
+
client: LemmaClient;
|
|
5
|
+
podId?: string;
|
|
6
|
+
tableName: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
onSuccess?: (response: DatastoreMessageResponse) => void;
|
|
9
|
+
onError?: (error: unknown) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface UseBulkRecordsResult {
|
|
12
|
+
isSubmitting: boolean;
|
|
13
|
+
error: Error | null;
|
|
14
|
+
lastMessage: string | null;
|
|
15
|
+
createMany: (records: Record<string, unknown>[]) => Promise<DatastoreMessageResponse | null>;
|
|
16
|
+
updateMany: (records: Record<string, unknown>[]) => Promise<DatastoreMessageResponse | null>;
|
|
17
|
+
deleteMany: (recordIds: Array<string | number>) => Promise<DatastoreMessageResponse | null>;
|
|
18
|
+
reset: () => void;
|
|
19
|
+
}
|
|
20
|
+
export declare function useBulkRecords({ client, podId, tableName, enabled, onSuccess, onError, }: UseBulkRecordsOptions): UseBulkRecordsResult;
|