@vertesia/ui 0.65.0 → 0.67.0
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/lib/esm/core/components/EmptyCollection.js +2 -2
- package/lib/esm/core/components/EmptyCollection.js.map +1 -1
- package/lib/esm/core/components/InputList.js +2 -2
- package/lib/esm/core/components/InputList.js.map +1 -1
- package/lib/esm/core/components/SidePanel.js +1 -1
- package/lib/esm/core/components/SidePanel.js.map +1 -1
- package/lib/esm/core/components/Switch.js +2 -2
- package/lib/esm/core/components/Switch.js.map +1 -1
- package/lib/esm/core/components/shadcn/calendar.js +0 -1
- package/lib/esm/core/components/shadcn/calendar.js.map +1 -1
- package/lib/esm/core/components/shadcn/checkbox.js +0 -1
- package/lib/esm/core/components/shadcn/checkbox.js.map +1 -1
- package/lib/esm/core/components/shadcn/command.js +0 -1
- package/lib/esm/core/components/shadcn/command.js.map +1 -1
- package/lib/esm/core/components/shadcn/dialog.js +0 -1
- package/lib/esm/core/components/shadcn/dialog.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/comboBox.js +18 -0
- package/lib/esm/core/components/shadcn/filters/comboBox.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +38 -17
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filters.js +11 -5
- package/lib/esm/core/components/shadcn/filters/filters.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/selectFilter.js +1 -1
- package/lib/esm/core/components/shadcn/filters/selectFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/stringListFilter.js +24 -0
- package/lib/esm/core/components/shadcn/filters/stringListFilter.js.map +1 -0
- package/lib/esm/core/components/shadcn/filters/textFilter.js +2 -1
- package/lib/esm/core/components/shadcn/filters/textFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/label.js +0 -1
- package/lib/esm/core/components/shadcn/label.js.map +1 -1
- package/lib/esm/features/agent/PayloadBuilder.js +27 -0
- package/lib/esm/features/agent/PayloadBuilder.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +1 -1
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -3
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/esm/features/facets/VEnvironmentFacet.js +24 -0
- package/lib/esm/features/facets/VEnvironmentFacet.js.map +1 -0
- package/lib/esm/features/facets/VFacetsNav.js +69 -26
- package/lib/esm/features/facets/VFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/VInteractionFacet.js +45 -0
- package/lib/esm/features/facets/VInteractionFacet.js.map +1 -0
- package/lib/esm/features/facets/VStringFacet.js +6 -5
- package/lib/esm/features/facets/VStringFacet.js.map +1 -1
- package/lib/esm/features/facets/VUserFacet.js +6 -6
- package/lib/esm/features/facets/VUserFacet.js.map +1 -1
- package/lib/esm/features/layout/GenericPageNavHeader.js +1 -1
- package/lib/esm/features/magic-pdf/TextPageView.js +1 -2
- package/lib/esm/features/magic-pdf/TextPageView.js.map +1 -1
- package/lib/esm/features/store/collections/CollectionsTable.js +9 -5
- package/lib/esm/features/store/collections/CollectionsTable.js.map +1 -1
- package/lib/esm/features/store/collections/{CollectionsView.js → CreateCollection.js} +6 -14
- package/lib/esm/features/store/collections/CreateCollection.js.map +1 -0
- package/lib/esm/features/store/collections/EditCollectionView.js +1 -1
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/SelectCollection.js +24 -0
- package/lib/esm/features/store/collections/SelectCollection.js.map +1 -0
- package/lib/esm/features/store/collections/index.js +2 -2
- package/lib/esm/features/store/collections/index.js.map +1 -1
- package/lib/esm/features/store/objects/DocumentSearchResults.js +6 -3
- package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/esm/features/store/objects/components/ContentOverview.js +17 -16
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/esm/features/store/objects/components/DocumentIcon.js +7 -10
- package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -1
- package/lib/esm/features/store/objects/components/DocumentInput.js +1 -2
- package/lib/esm/features/store/objects/components/DocumentInput.js.map +1 -1
- package/lib/esm/features/store/objects/components/PropertiesEditorModal.js +4 -2
- package/lib/esm/features/store/objects/components/PropertiesEditorModal.js.map +1 -1
- package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +1 -2
- package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
- package/lib/esm/features/store/objects/components/SelectDocument.js +9 -3
- package/lib/esm/features/store/objects/components/SelectDocument.js.map +1 -1
- package/lib/esm/features/store/objects/components/SelectDocumentModal.js +2 -2
- package/lib/esm/features/store/objects/components/SelectDocumentModal.js.map +1 -1
- package/lib/esm/features/store/objects/layout/documentLayout.js +2 -2
- package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -1
- package/lib/esm/features/store/objects/search/DocumentSearchContext.js +4 -2
- package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -1
- package/lib/esm/features/store/objects/selection/SelectionActions.js +1 -1
- package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +7 -10
- package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/ChangeTypeAction.js +1 -1
- package/lib/esm/features/store/objects/selection/actions/ChangeTypeAction.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +2 -2
- package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js +1 -1
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/RemoveFromCollectionAction.js +1 -1
- package/lib/esm/features/store/objects/selection/actions/RemoveFromCollectionAction.js.map +1 -1
- package/lib/esm/features/store/types/ContentObjectTypesSearch.js +2 -3
- package/lib/esm/features/store/types/ContentObjectTypesSearch.js.map +1 -1
- package/lib/esm/features/store/types/ContentObjectTypesTable.js +1 -1
- package/lib/esm/features/store/types/ContentObjectTypesTable.js.map +1 -1
- package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +2 -2
- package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -1
- package/lib/esm/features/store/types/ObjectSchemaEditor.js +2 -3
- package/lib/esm/features/store/types/ObjectSchemaEditor.js.map +1 -1
- package/lib/esm/features/store/types/TableLayoutEditor.js +1 -1
- package/lib/esm/features/store/types/TableLayoutEditor.js.map +1 -1
- package/lib/esm/features/store/types/index.js +0 -2
- package/lib/esm/features/store/types/index.js.map +1 -1
- package/lib/esm/features/user/UserInfo.js +1 -2
- package/lib/esm/features/user/UserInfo.js.map +1 -1
- package/lib/esm/features/utils/rendition.js +22 -2
- package/lib/esm/features/utils/rendition.js.map +1 -1
- package/lib/esm/layout/FullHeightLayout.js +2 -4
- package/lib/esm/layout/FullHeightLayout.js.map +1 -1
- package/lib/esm/session/UserSession.js +2 -2
- package/lib/esm/session/UserSession.js.map +1 -1
- package/lib/esm/session/auth/composable.js +1 -1
- package/lib/esm/session/auth/composable.js.map +1 -1
- package/lib/esm/session/constants.js +3 -0
- package/lib/esm/session/constants.js.map +1 -0
- package/lib/esm/widgets/codemirror/CodeMirrorEditor.js +2 -2
- package/lib/esm/widgets/codemirror/CodeMirrorEditor.js.map +1 -1
- package/lib/esm/widgets/properties/PropertiesView.js +4 -2
- package/lib/esm/widgets/properties/PropertiesView.js.map +1 -1
- package/lib/esm/widgets/schema-editor/editor/SchemaEditor.js +1 -1
- package/lib/esm/widgets/schema-editor/editor/SchemaEditor.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/InputList.d.ts +2 -1
- package/lib/types/core/components/Switch.d.ts +2 -1
- package/lib/types/core/components/shadcn/filters/comboBox.d.ts +5 -0
- package/lib/types/core/components/shadcn/filters/stringListFilter.d.ts +10 -0
- package/lib/types/core/components/shadcn/filters/types.d.ts +3 -3
- package/lib/types/features/agent/PayloadBuilder.d.ts +8 -1
- package/lib/types/features/facets/VEnvironmentFacet.d.ts +11 -0
- package/lib/types/features/facets/VFacetsNav.d.ts +9 -1
- package/lib/types/features/facets/VInteractionFacet.d.ts +14 -0
- package/lib/types/features/facets/VStringFacet.d.ts +3 -2
- package/lib/types/features/facets/VUserFacet.d.ts +3 -2
- package/lib/types/features/store/collections/{CollectionsView.d.ts → CreateCollection.d.ts} +5 -3
- package/lib/types/features/store/collections/SelectCollection.d.ts +14 -0
- package/lib/types/features/store/collections/index.d.ts +2 -2
- package/lib/types/features/store/objects/components/ContentOverview.d.ts +2 -1
- package/lib/types/features/store/objects/components/DocumentIcon.d.ts +2 -1
- package/lib/types/features/store/objects/components/PropertiesEditorModal.d.ts +2 -1
- package/lib/types/features/store/objects/layout/documentLayout.d.ts +1 -1
- package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +3 -2
- package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +2 -1
- package/lib/types/features/store/objects/selection/actions/RemoveFromCollectionAction.d.ts +2 -1
- package/lib/types/features/store/types/index.d.ts +0 -2
- package/lib/types/features/utils/rendition.d.ts +1 -1
- package/lib/types/session/UserSession.d.ts +2 -2
- package/lib/types/session/constants.d.ts +2 -0
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-layout.js +1 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +4 -4
- package/src/core/components/EmptyCollection.tsx +26 -24
- package/src/core/components/InputList.tsx +3 -1
- package/src/core/components/SidePanel.tsx +2 -2
- package/src/core/components/Switch.tsx +4 -3
- package/src/core/components/shadcn/calendar.tsx +0 -2
- package/src/core/components/shadcn/checkbox.tsx +0 -2
- package/src/core/components/shadcn/command.tsx +0 -2
- package/src/core/components/shadcn/dialog.tsx +0 -2
- package/src/core/components/shadcn/filters/comboBox.tsx +73 -0
- package/src/core/components/shadcn/filters/filterBar.tsx +41 -17
- package/src/core/components/shadcn/filters/filters.tsx +30 -14
- package/src/core/components/shadcn/filters/selectFilter.tsx +3 -3
- package/src/core/components/shadcn/filters/stringListFilter.tsx +58 -0
- package/src/core/components/shadcn/filters/textFilter.tsx +2 -1
- package/src/core/components/shadcn/filters/types.ts +3 -3
- package/src/core/components/shadcn/label.tsx +0 -2
- package/src/features/agent/PayloadBuilder.tsx +34 -1
- package/src/features/agent/chat/ModernAgentConversation.tsx +639 -639
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +12 -13
- package/src/features/facets/VEnvironmentFacet.tsx +42 -0
- package/src/features/facets/VFacetsNav.tsx +87 -29
- package/src/features/facets/VInteractionFacet.tsx +73 -0
- package/src/features/facets/VStringFacet.tsx +7 -6
- package/src/features/facets/VUserFacet.tsx +7 -6
- package/src/features/layout/GenericPageNavHeader.tsx +1 -1
- package/src/features/magic-pdf/TextPageView.tsx +1 -2
- package/src/features/store/collections/CollectionsTable.tsx +49 -40
- package/src/features/store/collections/{CollectionsView.tsx → CreateCollection.tsx} +15 -42
- package/src/features/store/collections/EditCollectionView.tsx +1 -1
- package/src/features/store/collections/SelectCollection.tsx +46 -0
- package/src/features/store/collections/index.ts +2 -2
- package/src/features/store/objects/DocumentSearchResults.tsx +6 -3
- package/src/features/store/objects/components/ContentOverview.tsx +38 -98
- package/src/features/store/objects/components/DocumentIcon.tsx +27 -14
- package/src/features/store/objects/components/DocumentInput.tsx +1 -2
- package/src/features/store/objects/components/PropertiesEditorModal.tsx +7 -3
- package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +2 -2
- package/src/features/store/objects/components/SelectDocument.tsx +18 -3
- package/src/features/store/objects/components/SelectDocumentModal.tsx +6 -6
- package/src/features/store/objects/layout/documentLayout.tsx +2 -2
- package/src/features/store/objects/search/DocumentSearchContext.ts +6 -3
- package/src/features/store/objects/selection/ObjectsActionContext.tsx +1 -1
- package/src/features/store/objects/selection/SelectionActions.tsx +0 -1
- package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +10 -21
- package/src/features/store/objects/selection/actions/ChangeTypeAction.tsx +1 -1
- package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +2 -2
- package/src/features/store/objects/selection/actions/ExportPropertiesAction.tsx +1 -1
- package/src/features/store/objects/selection/actions/RemoveFromCollectionAction.tsx +1 -1
- package/src/features/store/types/ContentObjectTypesSearch.tsx +3 -4
- package/src/features/store/types/ContentObjectTypesTable.tsx +3 -1
- package/src/features/store/types/CreateOrUpdateTypeModal.tsx +2 -9
- package/src/features/store/types/ObjectSchemaEditor.tsx +4 -5
- package/src/features/store/types/TableLayoutEditor.tsx +4 -4
- package/src/features/store/types/index.ts +0 -2
- package/src/features/user/UserInfo.tsx +1 -2
- package/src/features/utils/rendition.ts +23 -1
- package/src/layout/FullHeightLayout.tsx +2 -2
- package/src/session/UserSession.ts +2 -2
- package/src/session/auth/composable.ts +1 -1
- package/src/session/constants.ts +2 -0
- package/src/widgets/codemirror/CodeMirrorEditor.tsx +2 -2
- package/src/widgets/properties/PropertiesView.tsx +10 -2
- package/src/widgets/schema-editor/editor/SchemaEditor.tsx +1 -1
- package/lib/esm/features/store/collections/CollectionView.js +0 -53
- package/lib/esm/features/store/collections/CollectionView.js.map +0 -1
- package/lib/esm/features/store/collections/CollectionsView.js.map +0 -1
- package/lib/esm/features/store/types/ContentObjectTypeView.js +0 -158
- package/lib/esm/features/store/types/ContentObjectTypeView.js.map +0 -1
- package/lib/esm/features/store/types/ContentObjectTypesView.js +0 -55
- package/lib/esm/features/store/types/ContentObjectTypesView.js.map +0 -1
- package/lib/types/features/store/collections/CollectionView.d.ts +0 -5
- package/lib/types/features/store/types/ContentObjectTypeView.d.ts +0 -5
- package/lib/types/features/store/types/ContentObjectTypesView.d.ts +0 -8
- package/src/features/store/collections/CollectionView.tsx +0 -94
- package/src/features/store/types/ContentObjectTypeView.tsx +0 -244
- package/src/features/store/types/ContentObjectTypesView.tsx +0 -71
|
@@ -1,708 +1,708 @@
|
|
|
1
1
|
import { AsyncExecutionResult, VertesiaClient } from "@vertesia/client";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
AgentMessage,
|
|
4
|
+
AgentMessageType,
|
|
5
|
+
Plan,
|
|
6
|
+
UserInputSignal
|
|
7
7
|
} from "@vertesia/common";
|
|
8
8
|
import { Button, MessageBox, Spinner, useToast } from "@vertesia/ui/core";
|
|
9
9
|
import { useUserSession } from "@vertesia/ui/session";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
Bot,
|
|
12
|
+
Cpu,
|
|
13
|
+
SendIcon,
|
|
14
|
+
XIcon
|
|
15
15
|
} from "lucide-react";
|
|
16
16
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
17
17
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
AnimatedThinkingDots,
|
|
19
|
+
PulsatingCircle
|
|
20
20
|
} from "./AnimatedThinkingDots";
|
|
21
21
|
import AllMessagesMixed from "./ModernAgentOutput/AllMessagesMixed";
|
|
22
22
|
import Header from "./ModernAgentOutput/Header";
|
|
23
23
|
import MessageInput from "./ModernAgentOutput/MessageInput";
|
|
24
24
|
import PlanPanel from "./ModernAgentOutput/PlanPanel";
|
|
25
25
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
getWorkstreamId,
|
|
27
|
+
insertMessageInTimeline,
|
|
28
|
+
isInProgress,
|
|
29
29
|
} from "./ModernAgentOutput/utils";
|
|
30
30
|
import { ThinkingMessages } from "./WaitingMessages";
|
|
31
31
|
|
|
32
32
|
type StartWorkflowFn = (
|
|
33
|
-
|
|
33
|
+
initialMessage?: string,
|
|
34
34
|
) => Promise<{ run_id: string; workflow_id: string } | undefined>;
|
|
35
35
|
|
|
36
36
|
interface ModernAgentConversationProps {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
run?: AsyncExecutionResult | { workflow_id: string; run_id: string };
|
|
38
|
+
title?: string;
|
|
39
|
+
interactive?: boolean;
|
|
40
|
+
onClose?: () => void;
|
|
41
|
+
isModal?: boolean;
|
|
42
|
+
initialMessage?: string;
|
|
43
|
+
startWorkflow?: StartWorkflowFn;
|
|
44
|
+
startButtonText?: string;
|
|
45
|
+
placeholder?: string;
|
|
46
|
+
hideUserInput?: boolean;
|
|
47
|
+
resetWorkflow?: () => void;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export function ModernAgentConversation(
|
|
51
|
-
|
|
51
|
+
props: ModernAgentConversationProps,
|
|
52
52
|
) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
const { run, startWorkflow } = props;
|
|
54
|
+
|
|
55
|
+
if (run) {
|
|
56
|
+
// If we have a run, convert it to AsyncExecutionResult format if needed
|
|
57
|
+
const execRun: AsyncExecutionResult =
|
|
58
|
+
"runId" in run
|
|
59
|
+
? run
|
|
60
|
+
: {
|
|
61
|
+
runId: run.run_id,
|
|
62
|
+
workflowId: run.workflow_id,
|
|
63
|
+
};
|
|
64
|
+
return <ModernAgentConversationInner {...props} run={execRun} />;
|
|
65
|
+
} else if (startWorkflow) {
|
|
66
|
+
// If we have startWorkflow capability but no run yet
|
|
67
|
+
return <StartWorkflowView {...props} />;
|
|
68
|
+
} else {
|
|
69
|
+
// Empty state
|
|
70
|
+
return <EmptyState />;
|
|
71
|
+
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// Empty state when no agent is running
|
|
75
75
|
function EmptyState() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
return (
|
|
77
|
+
<MessageBox
|
|
78
|
+
status="info"
|
|
79
|
+
icon={<Bot className="size-16 text-muted mb-4" />}
|
|
80
|
+
>
|
|
81
|
+
<div className="text-base font-medium text-muted">
|
|
82
|
+
No agent currently running
|
|
83
|
+
</div>
|
|
84
|
+
<div className="mt-3 text-sm text-muted">
|
|
85
|
+
Select an interaction and click Start to start an agent
|
|
86
|
+
</div>
|
|
87
|
+
</MessageBox>
|
|
88
|
+
);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
// Start workflow view - allows initiating a new agent conversation
|
|
92
92
|
function StartWorkflowView({
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
initialMessage,
|
|
94
|
+
startWorkflow,
|
|
95
|
+
onClose,
|
|
96
|
+
isModal = false,
|
|
97
|
+
placeholder = "Type your message...",
|
|
98
|
+
startButtonText = "Start Agent",
|
|
99
|
+
title = "Start New Conversation",
|
|
100
100
|
}: ModernAgentConversationProps) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const message = inputValue.trim();
|
|
119
|
-
if (!message || isSending) return;
|
|
120
|
-
|
|
121
|
-
setIsSending(true);
|
|
122
|
-
try {
|
|
123
|
-
// Reset plan panel state when starting a new agent
|
|
124
|
-
sessionStorage.removeItem("plan-panel-shown");
|
|
125
|
-
|
|
126
|
-
toast({
|
|
127
|
-
title: "Starting agent...",
|
|
128
|
-
status: "info",
|
|
129
|
-
duration: 3000,
|
|
130
|
-
});
|
|
131
|
-
const newRun = await startWorkflow(message);
|
|
132
|
-
if (newRun) {
|
|
133
|
-
setRun({
|
|
134
|
-
runId: newRun.run_id,
|
|
135
|
-
workflowId: newRun.workflow_id,
|
|
136
|
-
});
|
|
137
|
-
setInputValue("");
|
|
138
|
-
toast({
|
|
139
|
-
title: "Agent started",
|
|
140
|
-
status: "success",
|
|
141
|
-
duration: 3000,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
} catch (err: any) {
|
|
145
|
-
toast({
|
|
146
|
-
title: "Error starting workflow",
|
|
147
|
-
status: "error",
|
|
148
|
-
duration: 3000,
|
|
149
|
-
description: err instanceof Error ? err.message : "Unknown error",
|
|
150
|
-
});
|
|
151
|
-
} finally {
|
|
152
|
-
setIsSending(false);
|
|
153
|
-
}
|
|
154
|
-
};
|
|
101
|
+
const [inputValue, setInputValue] = useState<string>("");
|
|
102
|
+
const [isSending, setIsSending] = useState(false);
|
|
103
|
+
const [run, setRun] = useState<AsyncExecutionResult>();
|
|
104
|
+
const toast = useToast();
|
|
105
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
106
|
+
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
// Focus the input field when component mounts
|
|
109
|
+
if (inputRef.current) {
|
|
110
|
+
inputRef.current.focus();
|
|
111
|
+
}
|
|
112
|
+
}, []);
|
|
113
|
+
|
|
114
|
+
// Start a new workflow with the message
|
|
115
|
+
const startWorkflowWithMessage = async () => {
|
|
116
|
+
if (!startWorkflow) return;
|
|
155
117
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
118
|
+
const message = inputValue.trim();
|
|
119
|
+
if (!message || isSending) return;
|
|
120
|
+
|
|
121
|
+
setIsSending(true);
|
|
122
|
+
try {
|
|
123
|
+
// Reset plan panel state when starting a new agent
|
|
124
|
+
sessionStorage.removeItem("plan-panel-shown");
|
|
125
|
+
|
|
126
|
+
toast({
|
|
127
|
+
title: "Starting agent...",
|
|
128
|
+
status: "info",
|
|
129
|
+
duration: 3000,
|
|
130
|
+
});
|
|
131
|
+
const newRun = await startWorkflow(message);
|
|
132
|
+
if (newRun) {
|
|
133
|
+
setRun({
|
|
134
|
+
runId: newRun.run_id,
|
|
135
|
+
workflowId: newRun.workflow_id,
|
|
136
|
+
});
|
|
137
|
+
setInputValue("");
|
|
138
|
+
toast({
|
|
139
|
+
title: "Agent started",
|
|
140
|
+
status: "success",
|
|
141
|
+
duration: 3000,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
} catch (err: any) {
|
|
145
|
+
toast({
|
|
146
|
+
title: "Error starting workflow",
|
|
147
|
+
status: "error",
|
|
148
|
+
duration: 3000,
|
|
149
|
+
description: err instanceof Error ? err.message : "Unknown error",
|
|
150
|
+
});
|
|
151
|
+
} finally {
|
|
152
|
+
setIsSending(false);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
157
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
startWorkflowWithMessage();
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// If a run has been started, show the conversation
|
|
164
|
+
if (run) {
|
|
165
|
+
return (
|
|
166
|
+
<ModernAgentConversationInner
|
|
167
|
+
{...{ onClose, isModal, initialMessage, placeholder }}
|
|
168
|
+
run={run}
|
|
169
|
+
title={title}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
160
172
|
}
|
|
161
|
-
};
|
|
162
173
|
|
|
163
|
-
// If a run has been started, show the conversation
|
|
164
|
-
if (run) {
|
|
165
174
|
return (
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
175
|
+
<div className="flex flex-col h-full bg-white dark:bg-gray-900 overflow-hidden border-0">
|
|
176
|
+
{/* Header */}
|
|
177
|
+
<div className="flex items-center justify-between py-2 px-3 border-b border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900">
|
|
178
|
+
<div className="flex items-center space-x-2">
|
|
179
|
+
<div className="p-1">
|
|
180
|
+
<Cpu className="h-3.5 w-3.5 text-gray-400 dark:text-gray-500" />
|
|
181
|
+
</div>
|
|
182
|
+
<span className="font-medium text-sm text-gray-700 dark:text-gray-300">
|
|
183
|
+
{title}
|
|
184
|
+
</span>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
{/* Close button if needed */}
|
|
188
|
+
{onClose && !isModal && (
|
|
189
|
+
<Button
|
|
190
|
+
size="xs"
|
|
191
|
+
variant="ghost"
|
|
192
|
+
onClick={onClose}
|
|
193
|
+
title="Close"
|
|
194
|
+
className="text-slate-500 hover:text-slate-700"
|
|
195
|
+
>
|
|
196
|
+
<XIcon className="h-4 w-4" />
|
|
197
|
+
</Button>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
186
200
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
className="px-3 py-2 bg-gray-800 dark:bg-gray-700 hover:bg-gray-700 dark:hover:bg-gray-600 text-white text-xs rounded-md transition-colors"
|
|
238
|
-
>
|
|
239
|
-
{isSending ? (
|
|
240
|
-
<Spinner size="sm" className="mr-1.5" />
|
|
241
|
-
) : (
|
|
242
|
-
<SendIcon className="h-3.5 w-3.5 mr-1.5" />
|
|
243
|
-
)}
|
|
244
|
-
{startButtonText}
|
|
245
|
-
</Button>
|
|
246
|
-
</div>
|
|
247
|
-
<div className="text-xs text-gray-400 dark:text-gray-500 mt-2 text-center">
|
|
248
|
-
Type a message to start the conversation
|
|
201
|
+
{/* Empty conversation area with instructions */}
|
|
202
|
+
<div className="flex-1 overflow-y-auto px-4 py-6 bg-white dark:bg-gray-900 flex flex-col items-center justify-center">
|
|
203
|
+
{initialMessage && (
|
|
204
|
+
<div className="px-4 py-3 mb-4 bg-blue-50/80 dark:bg-blue-900/30 border-l-2 border-blue-400 dark:border-blue-500 text-blue-700 dark:text-blue-300 max-w-md">
|
|
205
|
+
{initialMessage}
|
|
206
|
+
</div>
|
|
207
|
+
)}
|
|
208
|
+
|
|
209
|
+
<div className="bg-white dark:bg-slate-800 p-4 max-w-md border-l-2 border-blue-400 dark:border-blue-500">
|
|
210
|
+
<div className="text-base text-slate-600 dark:text-slate-300 font-medium">
|
|
211
|
+
Enter a message to start a conversation
|
|
212
|
+
</div>
|
|
213
|
+
<div className="mt-3 text-sm text-slate-500 dark:text-slate-400">
|
|
214
|
+
Type your question below and press Enter or click {startButtonText}{" "}
|
|
215
|
+
to begin
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
{/* Input Area */}
|
|
221
|
+
<div className="py-3 px-3 border-t border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900">
|
|
222
|
+
<div className="flex items-center gap-2">
|
|
223
|
+
<div className="flex-1">
|
|
224
|
+
<input
|
|
225
|
+
ref={inputRef}
|
|
226
|
+
value={inputValue}
|
|
227
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
228
|
+
onKeyDown={handleKeyDown}
|
|
229
|
+
placeholder={placeholder}
|
|
230
|
+
disabled={isSending}
|
|
231
|
+
className="w-full py-2 px-3 text-sm border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-white focus:border-gray-300 dark:focus:border-gray-600 focus:ring-0 rounded-md"
|
|
232
|
+
/>
|
|
233
|
+
</div>
|
|
234
|
+
<Button
|
|
235
|
+
onClick={startWorkflowWithMessage}
|
|
236
|
+
disabled={!inputValue.trim() || isSending}
|
|
237
|
+
className="px-3 py-2 bg-gray-800 dark:bg-gray-700 hover:bg-gray-700 dark:hover:bg-gray-600 text-white text-xs rounded-md transition-colors"
|
|
238
|
+
>
|
|
239
|
+
{isSending ? (
|
|
240
|
+
<Spinner size="sm" className="mr-1.5" />
|
|
241
|
+
) : (
|
|
242
|
+
<SendIcon className="h-3.5 w-3.5 mr-1.5" />
|
|
243
|
+
)}
|
|
244
|
+
{startButtonText}
|
|
245
|
+
</Button>
|
|
246
|
+
</div>
|
|
247
|
+
<div className="text-xs text-gray-400 dark:text-gray-500 mt-2 text-center">
|
|
248
|
+
Type a message to start the conversation
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
249
251
|
</div>
|
|
250
|
-
|
|
251
|
-
</div>
|
|
252
|
-
);
|
|
252
|
+
);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
// Inner component that handles the agent conversation - similar to ModernAgentOutput
|
|
256
256
|
function ModernAgentConversationInner({
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
257
|
+
run,
|
|
258
|
+
title,
|
|
259
|
+
interactive = true,
|
|
260
|
+
onClose,
|
|
261
|
+
isModal = false,
|
|
262
|
+
placeholder = "Type your message...",
|
|
263
|
+
resetWorkflow,
|
|
264
264
|
}: ModernAgentConversationProps & { run: AsyncExecutionResult }) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
265
|
+
const { client } = useUserSession();
|
|
266
|
+
const bottomRef = useRef<HTMLDivElement | null>(null);
|
|
267
|
+
const [messages, setMessages] = useState<AgentMessage[]>([]);
|
|
268
|
+
const [isCompleted, setIsCompleted] = useState(false);
|
|
269
|
+
const [inputValue, setInputValue] = useState<string>("");
|
|
270
|
+
const [isSending, setIsSending] = useState(false);
|
|
271
|
+
const [viewMode, setViewMode] = useState<"stacked" | "sliding">("sliding");
|
|
272
|
+
//TODO _setShowPlanPanel state not used
|
|
273
|
+
const [showPlanPanel, _setShowPlanPanel] = useState<boolean>(false);
|
|
274
|
+
const [showSlidingPanel, setShowSlidingPanel] = useState<boolean>(false);
|
|
275
|
+
// Keep track of multiple plans and their timestamps
|
|
276
|
+
const [plans, setPlans] = useState<Array<{ plan: Plan; timestamp: number }>>(
|
|
277
|
+
[],
|
|
278
|
+
);
|
|
279
|
+
// Track which plan is currently active in the UI
|
|
280
|
+
const [activePlanIndex, setActivePlanIndex] = useState<number>(0);
|
|
281
|
+
// Store workstream status for each plan separately
|
|
282
|
+
const [workstreamStatusMap, setWorkstreamStatusMap] = useState<
|
|
283
|
+
Map<
|
|
284
|
+
number,
|
|
285
|
+
Map<string, "pending" | "in_progress" | "completed" | "skipped">
|
|
286
|
+
>
|
|
287
|
+
>(new Map());
|
|
288
|
+
const [thinkingMessageIndex, setThinkingMessageIndex] = useState(0);
|
|
289
|
+
const toast = useToast();
|
|
290
|
+
const [showInput, setShowInput] = useState(interactive);
|
|
291
|
+
const [workflowStatus, setWorkflowStatus] = useState<string | null>(null);
|
|
292
|
+
|
|
293
|
+
// Helper function to get the current active plan and its workstream status
|
|
294
|
+
const getActivePlan = useMemo(() => {
|
|
295
|
+
const currentPlanData = plans[activePlanIndex] || {
|
|
296
|
+
plan: { plan: [] },
|
|
297
|
+
timestamp: 0,
|
|
298
|
+
};
|
|
299
|
+
const currentWorkstreamStatus =
|
|
300
|
+
workstreamStatusMap.get(currentPlanData.timestamp) || new Map();
|
|
301
|
+
return {
|
|
302
|
+
plan: currentPlanData.plan,
|
|
303
|
+
workstreamStatus: currentWorkstreamStatus,
|
|
304
|
+
};
|
|
305
|
+
}, [plans, activePlanIndex, workstreamStatusMap]);
|
|
306
|
+
|
|
307
|
+
// Show rotating thinking messages
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
if (!isCompleted) {
|
|
310
|
+
const interval = setInterval(() => {
|
|
311
|
+
setThinkingMessageIndex(() =>
|
|
312
|
+
Math.floor(Math.random() * (ThinkingMessages.length - 1)),
|
|
313
|
+
);
|
|
314
|
+
}, 4000);
|
|
315
|
+
return () => clearInterval(interval);
|
|
316
|
+
}
|
|
317
|
+
}, [isCompleted]);
|
|
318
|
+
|
|
319
|
+
const checkWorkflowStatus = async () => {
|
|
320
|
+
try {
|
|
321
|
+
const statusResult = await client.store.workflows.getRunDetails(run.runId, run.workflowId);
|
|
322
|
+
setWorkflowStatus(statusResult.status as string);
|
|
323
|
+
} catch (error) {
|
|
324
|
+
console.error('Failed to check workflow status:', error);
|
|
325
|
+
}
|
|
325
326
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
327
|
+
|
|
328
|
+
// Stream messages from the agent
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
// Reset all state when runId changes (new agent)
|
|
331
|
+
setMessages([]);
|
|
332
|
+
setPlans([]);
|
|
333
|
+
setActivePlanIndex(0);
|
|
334
|
+
setWorkstreamStatusMap(new Map());
|
|
335
|
+
setShowSlidingPanel(false);
|
|
336
|
+
setWorkflowStatus(null);
|
|
337
|
+
|
|
338
|
+
checkWorkflowStatus();
|
|
339
|
+
client.store.workflows.streamMessages(run.workflowId, run.runId, (message) => {
|
|
340
|
+
if (message.message) {
|
|
341
|
+
setMessages((prev_messages) => {
|
|
342
|
+
if (!prev_messages.find((m) => m.timestamp === message.timestamp)) {
|
|
343
|
+
insertMessageInTimeline(prev_messages, message);
|
|
344
|
+
return [...prev_messages];
|
|
345
|
+
} else {
|
|
346
|
+
return prev_messages;
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
348
350
|
});
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
351
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
// Update plans and workstream status based on incoming messages
|
|
374
|
-
useEffect(() => {
|
|
375
|
-
// Only show the sliding panel for the very first plan and only once
|
|
376
|
-
if (
|
|
377
|
-
plans.length === 1 &&
|
|
378
|
-
!showSlidingPanel &&
|
|
379
|
-
!sessionStorage.getItem("plan-panel-shown")
|
|
380
|
-
) {
|
|
381
|
-
// For first-time plan detection only, show the panel with a delay
|
|
382
|
-
const notificationTimeout = setTimeout(() => {
|
|
383
|
-
setShowSlidingPanel(true);
|
|
384
|
-
// Mark that we've shown the panel once
|
|
385
|
-
sessionStorage.setItem("plan-panel-shown", "true");
|
|
386
|
-
}, 500); // Short delay to ensure the UI has fully rendered
|
|
387
|
-
|
|
388
|
-
return () => clearTimeout(notificationTimeout);
|
|
389
|
-
}
|
|
352
|
+
// Clear messages and unsubscribe when component unmounts or runId changes
|
|
353
|
+
return () => {
|
|
354
|
+
setMessages([]);
|
|
355
|
+
// Client handles unsubscribing from the message stream internally
|
|
356
|
+
};
|
|
357
|
+
}, [run.runId, client.store.workflows]);
|
|
358
|
+
|
|
359
|
+
// Update completion status when messages change
|
|
360
|
+
// This now accounts for multiple workstreams
|
|
361
|
+
useEffect(() => {
|
|
362
|
+
setIsCompleted(!isInProgress(messages));
|
|
363
|
+
|
|
364
|
+
// Only automatically hide the panel when there are no plans
|
|
365
|
+
// But don't auto-show it when plans appear
|
|
366
|
+
if (plans.length === 0) {
|
|
367
|
+
// If there are no plans, make sure the plan panel is hidden
|
|
368
|
+
setShowSlidingPanel(false);
|
|
369
|
+
}
|
|
370
|
+
// We removed the auto-show functionality to allow users to keep the panel closed if they want
|
|
371
|
+
}, [messages, plans.length]);
|
|
390
372
|
|
|
391
|
-
//
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
373
|
+
// Update plans and workstream status based on incoming messages
|
|
374
|
+
useEffect(() => {
|
|
375
|
+
// Only show the sliding panel for the very first plan and only once
|
|
376
|
+
if (
|
|
377
|
+
plans.length === 1 &&
|
|
378
|
+
!showSlidingPanel &&
|
|
379
|
+
!sessionStorage.getItem("plan-panel-shown")
|
|
380
|
+
) {
|
|
381
|
+
// For first-time plan detection only, show the panel with a delay
|
|
382
|
+
const notificationTimeout = setTimeout(() => {
|
|
383
|
+
setShowSlidingPanel(true);
|
|
384
|
+
// Mark that we've shown the panel once
|
|
385
|
+
sessionStorage.setItem("plan-panel-shown", "true");
|
|
386
|
+
}, 500); // Short delay to ensure the UI has fully rendered
|
|
387
|
+
|
|
388
|
+
return () => clearTimeout(notificationTimeout);
|
|
389
|
+
}
|
|
397
390
|
|
|
398
|
-
|
|
391
|
+
// Process messages to extract plan information
|
|
392
|
+
messages.forEach((message) => {
|
|
393
|
+
if (message.type === AgentMessageType.PLAN) {
|
|
394
|
+
try {
|
|
395
|
+
// Log message details for debugging
|
|
396
|
+
console.log("PLAN message received:", message.type);
|
|
397
|
+
|
|
398
|
+
let newPlanDetails: Plan | null = null;
|
|
399
|
+
|
|
400
|
+
// Extract the plan from the message details object
|
|
401
|
+
if (message.details && typeof message.details === "object") {
|
|
402
|
+
// For a PLAN type message like the example you provided
|
|
403
|
+
if (message.details.plan && Array.isArray(message.details.plan)) {
|
|
404
|
+
console.log("Valid plan array found in message.details.plan");
|
|
405
|
+
newPlanDetails = { plan: message.details.plan } as Plan;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Only proceed if we have a valid plan
|
|
410
|
+
if (newPlanDetails) {
|
|
411
|
+
const timestamp =
|
|
412
|
+
typeof message.timestamp === "number"
|
|
413
|
+
? message.timestamp
|
|
414
|
+
: new Date(message.timestamp).getTime();
|
|
415
|
+
|
|
416
|
+
// Check if we already have this plan
|
|
417
|
+
const existingPlanIndex = plans.findIndex(
|
|
418
|
+
(p) => p.timestamp === timestamp,
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
if (existingPlanIndex === -1 && newPlanDetails) {
|
|
422
|
+
console.log("Adding new plan to plans array");
|
|
423
|
+
// This is a new plan - add it to our plans array
|
|
424
|
+
const newPlan = {
|
|
425
|
+
plan: newPlanDetails,
|
|
426
|
+
timestamp,
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// Add new plan to the beginning of the array (newest first)
|
|
430
|
+
console.log("Adding plan to plans array:", newPlan);
|
|
431
|
+
setPlans((prev) => {
|
|
432
|
+
const newPlans = [newPlan, ...prev];
|
|
433
|
+
console.log("New plans array:", newPlans);
|
|
434
|
+
return newPlans;
|
|
435
|
+
});
|
|
436
|
+
// Set this as the active plan
|
|
437
|
+
setActivePlanIndex(0);
|
|
438
|
+
|
|
439
|
+
// Automatically show sliding plan panel when a plan is detected
|
|
440
|
+
console.log("Setting showSlidingPanel to true");
|
|
441
|
+
setShowSlidingPanel(true);
|
|
442
|
+
|
|
443
|
+
// Initialize workstreams as pending based on the plan tasks
|
|
444
|
+
const newWorkstreamStatus = new Map<
|
|
445
|
+
string,
|
|
446
|
+
"pending" | "in_progress" | "completed" | "skipped"
|
|
447
|
+
>();
|
|
448
|
+
|
|
449
|
+
// Always initialize main workstream
|
|
450
|
+
newWorkstreamStatus.set("main", "in_progress");
|
|
451
|
+
|
|
452
|
+
// Initialize each task in the plan with its status
|
|
453
|
+
if (Array.isArray(newPlanDetails.plan)) {
|
|
454
|
+
newPlanDetails.plan.forEach((task) => {
|
|
455
|
+
if (task && typeof task === "object" && task.id) {
|
|
456
|
+
const taskId = task.id.toString();
|
|
457
|
+
// Use the task's status if available, otherwise default to pending
|
|
458
|
+
newWorkstreamStatus.set(taskId, task.status || "pending");
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Update the workstream status map with the new status for this plan
|
|
464
|
+
setWorkstreamStatusMap((prev) => {
|
|
465
|
+
const newMap = new Map(prev);
|
|
466
|
+
newMap.set(timestamp, newWorkstreamStatus);
|
|
467
|
+
return newMap;
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
} catch (error) {
|
|
472
|
+
console.error("Failed to parse plan from message:", error);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
399
475
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
476
|
+
// Handle UPDATE type messages with plan updates
|
|
477
|
+
if (message.type === AgentMessageType.UPDATE && message.details) {
|
|
478
|
+
// We no longer process UPDATE messages with details.updates
|
|
479
|
+
// Instead, we rely on the PLAN message that follows with the complete plan
|
|
480
|
+
if (message.details.updates && Array.isArray(message.details.updates)) {
|
|
481
|
+
console.log(
|
|
482
|
+
"Ignoring UPDATE message with details.updates - waiting for PLAN message with full plan",
|
|
483
|
+
);
|
|
484
|
+
// This is an initial update notification, but we'll wait for the PLAN message that follows
|
|
485
|
+
// with the complete updated plan before making any UI changes
|
|
486
|
+
}
|
|
406
487
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
setActivePlanIndex(0);
|
|
438
|
-
|
|
439
|
-
// Automatically show sliding plan panel when a plan is detected
|
|
440
|
-
console.log("Setting showSlidingPanel to true");
|
|
441
|
-
setShowSlidingPanel(true);
|
|
442
|
-
|
|
443
|
-
// Initialize workstreams as pending based on the plan tasks
|
|
444
|
-
const newWorkstreamStatus = new Map<
|
|
445
|
-
string,
|
|
446
|
-
"pending" | "in_progress" | "completed" | "skipped"
|
|
447
|
-
>();
|
|
448
|
-
|
|
449
|
-
// Always initialize main workstream
|
|
450
|
-
newWorkstreamStatus.set("main", "in_progress");
|
|
451
|
-
|
|
452
|
-
// Initialize each task in the plan with its status
|
|
453
|
-
if (Array.isArray(newPlanDetails.plan)) {
|
|
454
|
-
newPlanDetails.plan.forEach((task) => {
|
|
455
|
-
if (task && typeof task === "object" && task.id) {
|
|
456
|
-
const taskId = task.id.toString();
|
|
457
|
-
// Use the task's status if available, otherwise default to pending
|
|
458
|
-
newWorkstreamStatus.set(taskId, task.status || "pending");
|
|
459
|
-
}
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
const lastMessage = messages[messages.length - 1];
|
|
491
|
+
if (lastMessage) {
|
|
492
|
+
if (interactive) {
|
|
493
|
+
setShowInput(true);
|
|
494
|
+
} else {
|
|
495
|
+
setShowInput(lastMessage.type === AgentMessageType.REQUEST_INPUT);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}, [messages, plans, activePlanIndex]);
|
|
499
|
+
|
|
500
|
+
// Send a message to the agent
|
|
501
|
+
const handleSendMessage = () => {
|
|
502
|
+
const message = inputValue.trim();
|
|
503
|
+
if (!message || isSending) return;
|
|
504
|
+
|
|
505
|
+
setIsSending(true);
|
|
506
|
+
setInputValue("");
|
|
507
|
+
|
|
508
|
+
client.store.workflows
|
|
509
|
+
.sendSignal(run.workflowId, run.runId, "UserInput", {
|
|
510
|
+
message,
|
|
511
|
+
} as UserInputSignal)
|
|
512
|
+
.then(() => {
|
|
513
|
+
setIsCompleted(false);
|
|
514
|
+
toast({
|
|
515
|
+
status: "success",
|
|
516
|
+
title: "Message Sent",
|
|
517
|
+
duration: 2000,
|
|
460
518
|
});
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
519
|
+
})
|
|
520
|
+
.catch((err) => {
|
|
521
|
+
toast({
|
|
522
|
+
status: "error",
|
|
523
|
+
title: "Failed to Send Message",
|
|
524
|
+
description: err instanceof Error ? err.message : "Unknown error",
|
|
525
|
+
duration: 3000,
|
|
526
|
+
});
|
|
527
|
+
})
|
|
528
|
+
.finally(() => {
|
|
529
|
+
setIsSending(false);
|
|
530
|
+
});
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// Calculate number of active tasks for the status indicator
|
|
534
|
+
const getActiveTaskCount = (): number => {
|
|
535
|
+
if (!messages.length) return 0;
|
|
536
|
+
|
|
537
|
+
// Group messages by workstream
|
|
538
|
+
const workstreamMessages = new Map<string, AgentMessage[]>();
|
|
539
|
+
|
|
540
|
+
messages.forEach((message) => {
|
|
541
|
+
const workstreamId = getWorkstreamId(message);
|
|
542
|
+
if (workstreamId !== "main" && workstreamId !== "all") {
|
|
543
|
+
if (!workstreamMessages.has(workstreamId)) {
|
|
544
|
+
workstreamMessages.set(workstreamId, []);
|
|
545
|
+
}
|
|
546
|
+
workstreamMessages.get(workstreamId)!.push(message);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// Count workstreams that don't have completion messages
|
|
551
|
+
let activeCount = 0;
|
|
552
|
+
|
|
553
|
+
for (const [_, msgs] of workstreamMessages.entries()) {
|
|
554
|
+
if (msgs.length > 0) {
|
|
555
|
+
const lastMessage = msgs[msgs.length - 1];
|
|
556
|
+
// If the last message isn't a completion message, the workstream is active
|
|
557
|
+
if (
|
|
558
|
+
![AgentMessageType.COMPLETE, AgentMessageType.IDLE].includes(
|
|
559
|
+
lastMessage.type,
|
|
560
|
+
)
|
|
561
|
+
) {
|
|
562
|
+
activeCount++;
|
|
563
|
+
}
|
|
469
564
|
}
|
|
470
|
-
}
|
|
471
|
-
} catch (error) {
|
|
472
|
-
console.error("Failed to parse plan from message:", error);
|
|
473
565
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
566
|
+
|
|
567
|
+
return activeCount;
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
const actualTitle =
|
|
571
|
+
title || run.workflowId.split(":")[2] || "Agent Conversation";
|
|
572
|
+
|
|
573
|
+
// Handle downloading conversation
|
|
574
|
+
const downloadConversation = async () => {
|
|
575
|
+
try {
|
|
576
|
+
const url = await getConversationUrl(client, run.runId);
|
|
577
|
+
if (url) window.open(url, "_blank");
|
|
578
|
+
} catch (err) {
|
|
579
|
+
console.error("Failed to download conversation", err);
|
|
580
|
+
toast({
|
|
581
|
+
status: "error",
|
|
582
|
+
title: "Failed to download conversation",
|
|
583
|
+
duration: 3000,
|
|
584
|
+
});
|
|
486
585
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
if (interactive) {
|
|
493
|
-
setShowInput(true);
|
|
494
|
-
} else {
|
|
495
|
-
setShowInput(lastMessage.type === AgentMessageType.REQUEST_INPUT);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}, [messages, plans, activePlanIndex]);
|
|
499
|
-
|
|
500
|
-
// Send a message to the agent
|
|
501
|
-
const handleSendMessage = () => {
|
|
502
|
-
const message = inputValue.trim();
|
|
503
|
-
if (!message || isSending) return;
|
|
504
|
-
|
|
505
|
-
setIsSending(true);
|
|
506
|
-
setInputValue("");
|
|
507
|
-
|
|
508
|
-
client.store.workflows
|
|
509
|
-
.sendSignal(run.workflowId, run.runId, "UserInput", {
|
|
510
|
-
message,
|
|
511
|
-
} as UserInputSignal)
|
|
512
|
-
.then(() => {
|
|
513
|
-
setIsCompleted(false);
|
|
514
|
-
toast({
|
|
515
|
-
status: "success",
|
|
516
|
-
title: "Message Sent",
|
|
517
|
-
duration: 2000,
|
|
518
|
-
});
|
|
519
|
-
})
|
|
520
|
-
.catch((err) => {
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
// Handle copying run ID
|
|
589
|
+
const copyRunId = () => {
|
|
590
|
+
navigator.clipboard.writeText(run.runId);
|
|
521
591
|
toast({
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
duration: 3000,
|
|
592
|
+
status: "success",
|
|
593
|
+
title: "Run ID copied",
|
|
594
|
+
duration: 2000,
|
|
526
595
|
});
|
|
527
|
-
|
|
528
|
-
.finally(() => {
|
|
529
|
-
setIsSending(false);
|
|
530
|
-
});
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
// Calculate number of active tasks for the status indicator
|
|
534
|
-
const getActiveTaskCount = (): number => {
|
|
535
|
-
if (!messages.length) return 0;
|
|
536
|
-
|
|
537
|
-
// Group messages by workstream
|
|
538
|
-
const workstreamMessages = new Map<string, AgentMessage[]>();
|
|
539
|
-
|
|
540
|
-
messages.forEach((message) => {
|
|
541
|
-
const workstreamId = getWorkstreamId(message);
|
|
542
|
-
if (workstreamId !== "main" && workstreamId !== "all") {
|
|
543
|
-
if (!workstreamMessages.has(workstreamId)) {
|
|
544
|
-
workstreamMessages.set(workstreamId, []);
|
|
545
|
-
}
|
|
546
|
-
workstreamMessages.get(workstreamId)!.push(message);
|
|
547
|
-
}
|
|
548
|
-
});
|
|
596
|
+
};
|
|
549
597
|
|
|
550
|
-
|
|
551
|
-
|
|
598
|
+
return (
|
|
599
|
+
<div
|
|
600
|
+
className={`flex flex-col h-full min-h-0 ${isModal ? "rounded-lg overflow-hidden" : ""}`}
|
|
601
|
+
>
|
|
602
|
+
<Header
|
|
603
|
+
title={actualTitle}
|
|
604
|
+
isCompleted={isCompleted}
|
|
605
|
+
onClose={onClose}
|
|
606
|
+
isModal={isModal}
|
|
607
|
+
run={run}
|
|
608
|
+
viewMode={viewMode}
|
|
609
|
+
onViewModeChange={setViewMode}
|
|
610
|
+
showPlanPanel={showSlidingPanel}
|
|
611
|
+
hasPlan={plans.length > 0}
|
|
612
|
+
onTogglePlanPanel={() => {
|
|
613
|
+
setShowSlidingPanel(!showSlidingPanel);
|
|
614
|
+
// When opening the plan panel, mark that we've shown it
|
|
615
|
+
if (!showSlidingPanel) {
|
|
616
|
+
sessionStorage.setItem("plan-panel-shown", "true");
|
|
617
|
+
}
|
|
618
|
+
}}
|
|
619
|
+
onDownload={downloadConversation}
|
|
620
|
+
onCopyRunId={copyRunId}
|
|
621
|
+
resetWorkflow={resetWorkflow}
|
|
622
|
+
/>
|
|
552
623
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
) {
|
|
562
|
-
activeCount++;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
624
|
+
{/* Inline Plan Panel - only shown when toggle is clicked */}
|
|
625
|
+
{showPlanPanel && !showSlidingPanel && plans.length > 0 && (
|
|
626
|
+
<PlanPanel
|
|
627
|
+
plan={getActivePlan.plan}
|
|
628
|
+
workstreamStatus={getActivePlan.workstreamStatus}
|
|
629
|
+
isVisible={true}
|
|
630
|
+
/>
|
|
631
|
+
)}
|
|
566
632
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
/>
|
|
631
|
-
)}
|
|
632
|
-
|
|
633
|
-
{messages.length === 0 && !isCompleted ? (
|
|
634
|
-
<div className="flex-1 flex flex-col items-center justify-center h-full text-center py-6 bg-white dark:bg-gray-900">
|
|
635
|
-
<div className="bg-white dark:bg-slate-800 p-5 max-w-md border border-blue-200 dark:border-blue-900/50 rounded-lg shadow-sm">
|
|
636
|
-
<div className="flex items-center space-x-3 mb-3">
|
|
637
|
-
<PulsatingCircle size="sm" color="blue" />
|
|
638
|
-
<div className="text-sm text-slate-600 dark:text-slate-300 font-medium">
|
|
639
|
-
{ThinkingMessages[thinkingMessageIndex]}
|
|
640
|
-
</div>
|
|
641
|
-
</div>
|
|
642
|
-
<div className="mt-4 flex justify-center">
|
|
643
|
-
<AnimatedThinkingDots color="blue" className="mt-1" />
|
|
644
|
-
</div>
|
|
645
|
-
</div>
|
|
633
|
+
{messages.length === 0 && !isCompleted ? (
|
|
634
|
+
<div className="flex-1 flex flex-col items-center justify-center h-full text-center py-6 bg-white dark:bg-gray-900">
|
|
635
|
+
<div className="bg-white dark:bg-slate-800 p-5 max-w-md border border-blue-200 dark:border-blue-900/50 rounded-lg shadow-sm">
|
|
636
|
+
<div className="flex items-center space-x-3 mb-3">
|
|
637
|
+
<PulsatingCircle size="sm" color="blue" />
|
|
638
|
+
<div className="text-sm text-slate-600 dark:text-slate-300 font-medium">
|
|
639
|
+
{ThinkingMessages[thinkingMessageIndex]}
|
|
640
|
+
</div>
|
|
641
|
+
</div>
|
|
642
|
+
<div className="mt-4 flex justify-center">
|
|
643
|
+
<AnimatedThinkingDots color="blue" className="mt-1" />
|
|
644
|
+
</div>
|
|
645
|
+
</div>
|
|
646
|
+
</div>
|
|
647
|
+
) : (
|
|
648
|
+
<AllMessagesMixed
|
|
649
|
+
messages={messages}
|
|
650
|
+
bottomRef={bottomRef as React.RefObject<HTMLDivElement>}
|
|
651
|
+
viewMode={viewMode}
|
|
652
|
+
isCompleted={isCompleted}
|
|
653
|
+
plan={getActivePlan.plan}
|
|
654
|
+
workstreamStatus={getActivePlan.workstreamStatus}
|
|
655
|
+
showPlanPanel={showSlidingPanel}
|
|
656
|
+
onTogglePlanPanel={() => {
|
|
657
|
+
console.log(
|
|
658
|
+
"Toggle plan panel called, current state:",
|
|
659
|
+
showSlidingPanel,
|
|
660
|
+
);
|
|
661
|
+
setShowSlidingPanel(!showSlidingPanel);
|
|
662
|
+
}}
|
|
663
|
+
plans={plans}
|
|
664
|
+
activePlanIndex={activePlanIndex}
|
|
665
|
+
onChangePlan={(index) => setActivePlanIndex(index)}
|
|
666
|
+
taskLabels={getActivePlan.plan.plan?.reduce((acc, task) => {
|
|
667
|
+
if (task.id && task.goal) {
|
|
668
|
+
acc.set(task.id.toString(), task.goal);
|
|
669
|
+
}
|
|
670
|
+
return acc;
|
|
671
|
+
}, new Map<string, string>())}
|
|
672
|
+
/>
|
|
673
|
+
)}
|
|
674
|
+
|
|
675
|
+
{workflowStatus && (
|
|
676
|
+
workflowStatus !== "RUNNING" ? (
|
|
677
|
+
<MessageBox
|
|
678
|
+
status={workflowStatus === "COMPLETED" ? 'success' : 'done'}
|
|
679
|
+
icon={null}
|
|
680
|
+
className="flex-shrink-0 m-2"
|
|
681
|
+
>
|
|
682
|
+
This Workflow is {workflowStatus}
|
|
683
|
+
</MessageBox>
|
|
684
|
+
) : showInput && (
|
|
685
|
+
<MessageInput
|
|
686
|
+
value={inputValue}
|
|
687
|
+
onChange={setInputValue}
|
|
688
|
+
onSend={handleSendMessage}
|
|
689
|
+
disabled={false}
|
|
690
|
+
isSending={isSending}
|
|
691
|
+
isCompleted={isCompleted}
|
|
692
|
+
activeTaskCount={getActiveTaskCount()}
|
|
693
|
+
placeholder={placeholder}
|
|
694
|
+
/>
|
|
695
|
+
))}
|
|
646
696
|
</div>
|
|
647
|
-
|
|
648
|
-
<AllMessagesMixed
|
|
649
|
-
messages={messages}
|
|
650
|
-
bottomRef={bottomRef as React.RefObject<HTMLDivElement>}
|
|
651
|
-
viewMode={viewMode}
|
|
652
|
-
isCompleted={isCompleted}
|
|
653
|
-
plan={getActivePlan.plan}
|
|
654
|
-
workstreamStatus={getActivePlan.workstreamStatus}
|
|
655
|
-
showPlanPanel={showSlidingPanel}
|
|
656
|
-
onTogglePlanPanel={() => {
|
|
657
|
-
console.log(
|
|
658
|
-
"Toggle plan panel called, current state:",
|
|
659
|
-
showSlidingPanel,
|
|
660
|
-
);
|
|
661
|
-
setShowSlidingPanel(!showSlidingPanel);
|
|
662
|
-
}}
|
|
663
|
-
plans={plans}
|
|
664
|
-
activePlanIndex={activePlanIndex}
|
|
665
|
-
onChangePlan={(index) => setActivePlanIndex(index)}
|
|
666
|
-
taskLabels={getActivePlan.plan.plan?.reduce((acc, task) => {
|
|
667
|
-
if (task.id && task.goal) {
|
|
668
|
-
acc.set(task.id.toString(), task.goal);
|
|
669
|
-
}
|
|
670
|
-
return acc;
|
|
671
|
-
}, new Map<string, string>())}
|
|
672
|
-
/>
|
|
673
|
-
)}
|
|
674
|
-
|
|
675
|
-
{workflowStatus && (
|
|
676
|
-
workflowStatus !== "RUNNING" ? (
|
|
677
|
-
<MessageBox
|
|
678
|
-
status={workflowStatus === "COMPLETED" ? 'success' : 'done'}
|
|
679
|
-
icon={null}
|
|
680
|
-
className="flex-shrink-0 m-2"
|
|
681
|
-
>
|
|
682
|
-
This Workflow is {workflowStatus}
|
|
683
|
-
</MessageBox>
|
|
684
|
-
) : showInput && (
|
|
685
|
-
<MessageInput
|
|
686
|
-
value={inputValue}
|
|
687
|
-
onChange={setInputValue}
|
|
688
|
-
onSend={handleSendMessage}
|
|
689
|
-
disabled={false}
|
|
690
|
-
isSending={isSending}
|
|
691
|
-
isCompleted={isCompleted}
|
|
692
|
-
activeTaskCount={getActiveTaskCount()}
|
|
693
|
-
placeholder={placeholder}
|
|
694
|
-
/>
|
|
695
|
-
))}
|
|
696
|
-
</div>
|
|
697
|
-
);
|
|
697
|
+
);
|
|
698
698
|
}
|
|
699
699
|
|
|
700
700
|
// Helper function to get conversation URL - used by other components
|
|
701
701
|
export async function getConversationUrl(
|
|
702
|
-
|
|
703
|
-
|
|
702
|
+
vertesia: VertesiaClient,
|
|
703
|
+
workflowRunId: string,
|
|
704
704
|
): Promise<string> {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
705
|
+
return vertesia.files
|
|
706
|
+
.getDownloadUrl(`agents/${workflowRunId}/conversation.json`)
|
|
707
|
+
.then((r) => r.url);
|
|
708
708
|
}
|