From c7a376d86b2f445f5cf8e787171550a8cd214042 Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Tue, 16 Jul 2024 08:19:41 +0000 Subject: [PATCH 1/5] feat: Workflows --- src/ui/src/builder/BuilderApp.vue | 5 + src/ui/src/builder/BuilderSidebar.vue | 15 +- .../BuilderSidebarWorkflowsToolkit.vue | 191 ++++++++++++++++++ src/ui/src/builder/BuilderSwitcher.vue | 9 +- src/ui/src/builder/builderManager.ts | 2 +- .../src/builder/workflows/WorkflowsArrow.vue | 35 ++++ .../src/builder/workflows/WorkflowsCanvas.vue | 169 ++++++++++++++++ .../builder/workflows/WorkflowsNodeBox.vue | 103 ++++++++++ .../src/builder/workflows/nodeTemplateDefs.ts | 126 ++++++++++++ src/ui/src/core/index.ts | 1 + src/ui/src/writerTypes.ts | 33 ++- 11 files changed, 679 insertions(+), 10 deletions(-) create mode 100644 src/ui/src/builder/BuilderSidebarWorkflowsToolkit.vue create mode 100644 src/ui/src/builder/workflows/WorkflowsArrow.vue create mode 100644 src/ui/src/builder/workflows/WorkflowsCanvas.vue create mode 100644 src/ui/src/builder/workflows/WorkflowsNodeBox.vue create mode 100644 src/ui/src/builder/workflows/nodeTemplateDefs.ts diff --git a/src/ui/src/builder/BuilderApp.vue b/src/ui/src/builder/BuilderApp.vue index e98f5fea5..42bf43348 100644 --- a/src/ui/src/builder/BuilderApp.vue +++ b/src/ui/src/builder/BuilderApp.vue @@ -6,6 +6,7 @@
+ +
@@ -135,6 +139,7 @@ import BuilderInstanceTracker from "./BuilderInstanceTracker.vue"; import BuilderInsertionOverlay from "./BuilderInsertionOverlay.vue"; import BuilderInsertionLabel from "./BuilderInsertionLabel.vue"; import { isPlatformMac } from "../core/detectPlatform"; +import WorkflowsCanvas from "./workflows/WorkflowsCanvas.vue"; const wf = inject(injectionKeys.core); const ssbm = inject(injectionKeys.builderManager); diff --git a/src/ui/src/builder/BuilderSidebar.vue b/src/ui/src/builder/BuilderSidebar.vue index 14c2d4ed4..78ab73ffc 100644 --- a/src/ui/src/builder/BuilderSidebar.vue +++ b/src/ui/src/builder/BuilderSidebar.vue @@ -1,13 +1,24 @@ diff --git a/src/ui/src/builder/BuilderSwitcher.vue b/src/ui/src/builder/BuilderSwitcher.vue index 6fef6fedc..9b388e761 100644 --- a/src/ui/src/builder/BuilderSwitcher.vue +++ b/src/ui/src/builder/BuilderSwitcher.vue @@ -14,6 +14,13 @@ logEntryCount }} +
+ preview + Workflows +
= ref(null); -const selectOption = (optionId: "ui" | "code" | "preview") => { +const selectOption = (optionId: "ui" | "code" | "workflows" | "preview") => { selectedId.value = optionId; ssbm.setMode(optionId); if (ssbm.getMode() != "preview") return; diff --git a/src/ui/src/builder/builderManager.ts b/src/ui/src/builder/builderManager.ts index 2547872d0..a5e57c0de 100644 --- a/src/ui/src/builder/builderManager.ts +++ b/src/ui/src/builder/builderManager.ts @@ -44,7 +44,7 @@ export function generateBuilderManager() { }; type State = { - mode: "ui" | "code" | "preview"; + mode: "ui" | "code" | "workflows" | "preview"; selection: { componentId: Component["id"]; instancePath: string; diff --git a/src/ui/src/builder/workflows/WorkflowsArrow.vue b/src/ui/src/builder/workflows/WorkflowsArrow.vue new file mode 100644 index 000000000..bd427560b --- /dev/null +++ b/src/ui/src/builder/workflows/WorkflowsArrow.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/src/ui/src/builder/workflows/WorkflowsCanvas.vue b/src/ui/src/builder/workflows/WorkflowsCanvas.vue new file mode 100644 index 000000000..25bbff756 --- /dev/null +++ b/src/ui/src/builder/workflows/WorkflowsCanvas.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/src/ui/src/builder/workflows/WorkflowsNodeBox.vue b/src/ui/src/builder/workflows/WorkflowsNodeBox.vue new file mode 100644 index 000000000..070d2eec7 --- /dev/null +++ b/src/ui/src/builder/workflows/WorkflowsNodeBox.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/ui/src/builder/workflows/nodeTemplateDefs.ts b/src/ui/src/builder/workflows/nodeTemplateDefs.ts new file mode 100644 index 000000000..c9d0fcbac --- /dev/null +++ b/src/ui/src/builder/workflows/nodeTemplateDefs.ts @@ -0,0 +1,126 @@ +import { FieldType } from "../../writerTypes"; + +const httpcall = { + name: "HTTP call", + description: "Helps you make HTTP calls", + category: "Content", + fields: { + conversation: { + name: "Conversation", + desc: "An array with messages or a writer.ai.Conversation object.", + type: FieldType.Object, + }, + assistantInitials: { + name: "Assistant initials", + default: "AI", + type: FieldType.Text, + }, + userInitials: { + name: "User initials", + default: "YOU", + type: FieldType.Text, + }, + useMarkdown: { + name: "Use Markdown", + desc: "If active, the output will be sanitized; unsafe elements will be removed.", + default: "no", + type: FieldType.Text, + options: { + yes: "Yes", + no: "No", + }, + }, + enableFileUpload: { + name: "Enable file upload", + default: "no", + type: FieldType.Text, + options: { + single: "Single file", + multiple: "Multiple files", + no: "No", + }, + }, + placeholder: { + name: "Placeholder", + default: "What do you need?", + type: FieldType.Text, + }, + }, + outs: { + success: { + name: "Success", + description: "If the HTTP call succeeds.", + style: "success", + }, + exception: { + name: "Error", + description: "If the HTTP call doesn't succeed.", + style: "error", + }, + }, +}; + +const pythonfunc = { + name: "Python function", + description: "Run Python functions", + category: "Content", + fields: { + conversation: { + name: "Conversation", + desc: "An array with messages or a writer.ai.Conversation object.", + type: FieldType.Object, + }, + assistantInitials: { + name: "Assistant initials", + default: "AI", + type: FieldType.Text, + }, + userInitials: { + name: "User initials", + default: "YOU", + type: FieldType.Text, + }, + useMarkdown: { + name: "Use Markdown", + desc: "If active, the output will be sanitized; unsafe elements will be removed.", + default: "no", + type: FieldType.Text, + options: { + yes: "Yes", + no: "No", + }, + }, + enableFileUpload: { + name: "Enable file upload", + default: "no", + type: FieldType.Text, + options: { + single: "Single file", + multiple: "Multiple files", + no: "No", + }, + }, + placeholder: { + name: "Placeholder", + default: "What do you need?", + type: FieldType.Text, + }, + }, + outs: { + success: { + name: "Success", + description: "If the function doesn't raise an Exception.", + style: "success", + }, + exception: { + name: "Exception", + description: "If the function raises an Exception.", + style: "error", + }, + }, +}; + +export default { + httpcall, + pythonfunc, +}; diff --git a/src/ui/src/core/index.ts b/src/ui/src/core/index.ts index 04c434292..9331d454d 100644 --- a/src/ui/src/core/index.ts +++ b/src/ui/src/core/index.ts @@ -6,6 +6,7 @@ import { ComponentMap, InstancePath, MailItem, + UIComponent, UserFunction, } from "../writerTypes"; import { diff --git a/src/ui/src/writerTypes.ts b/src/ui/src/writerTypes.ts index 7ad8500ff..e9c12df3b 100644 --- a/src/ui/src/writerTypes.ts +++ b/src/ui/src/writerTypes.ts @@ -1,9 +1,9 @@ -import { generateCore } from "./core" -import { generateBuilderManager } from "./builder/builderManager" +import { generateCore } from "./core"; +import { generateBuilderManager } from "./builder/builderManager"; -export type Core = ReturnType +export type Core = ReturnType; -type ComponentId = string +type ComponentId = string; /** * Basic building block of applications. @@ -14,15 +14,25 @@ export type Component = { id: ComponentId; parentId: string; type: string; - position: number; content: Record; isCodeManaged?: boolean; handlers?: Record; - visible?: boolean | string; binding?: { eventType: string; stateRef: string; }; + position?: number; + visible?: boolean | string; + x?: number; + y?: number; + outs?: Record< + string, + { + name: string; + description: string; + style: string; + } + >; }; /** @@ -125,3 +135,14 @@ export type ComponentMap = Record; export type MailItem = { type: string; payload: Record }; export type UserFunction = { name: string; args: string[] }; + +export type WorkflowsNode = { + type: string; + content: Record; + x: number; + y: number; + outs: { + outId: string; + toNodeId: string; + }[]; +}; From f88ff0c8ab9e20f9514bf16640981830172d9a29 Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:23:35 +0000 Subject: [PATCH 2/5] feat: Workflows --- src/ui/src/builder/BuilderApp.vue | 15 + src/ui/src/builder/BuilderFieldsText.vue | 3 +- src/ui/src/builder/BuilderSidebarTree.vue | 11 + src/ui/src/builder/builderManager.ts | 2 +- src/ui/src/builder/useComponentActions.ts | 2 +- .../src/builder/workflows/WorkflowsCanvas.vue | 68 +++-- .../builder/workflows/WorkflowsNodeBox.vue | 10 +- src/ui/src/builder/workflows/workflowsCore.ts | 0 src/ui/src/core/index.ts | 8 +- src/ui/src/core/templateMap.ts | 13 +- src/ui/src/core_components/root/CoreRoot.vue | 2 +- .../src/workflow_components/CoreHTTPCall.vue | 91 ++++++ .../CorePythonFunction.vue | 53 ++++ .../src/workflow_components/CoreSetState.vue | 57 ++++ .../src/workflow_components/CoreWorkflow.vue | 260 ++++++++++++++++++ .../CoreWriterCompletion.vue | 55 ++++ .../workflow_components/WorkflowsArrow.vue | 87 ++++++ .../workflow_components/WorkflowsNodeBox.vue | 112 ++++++++ .../workflow_components/WorkflowsNodeOuts.vue | 97 +++++++ src/ui/src/writerTypes.ts | 23 +- src/writer/core.py | 12 +- src/writer/core_ui.py | 3 + 22 files changed, 929 insertions(+), 55 deletions(-) create mode 100644 src/ui/src/builder/workflows/workflowsCore.ts create mode 100644 src/ui/src/workflow_components/CoreHTTPCall.vue create mode 100644 src/ui/src/workflow_components/CorePythonFunction.vue create mode 100644 src/ui/src/workflow_components/CoreSetState.vue create mode 100644 src/ui/src/workflow_components/CoreWorkflow.vue create mode 100644 src/ui/src/workflow_components/CoreWriterCompletion.vue create mode 100644 src/ui/src/workflow_components/WorkflowsArrow.vue create mode 100644 src/ui/src/workflow_components/WorkflowsNodeBox.vue create mode 100644 src/ui/src/workflow_components/WorkflowsNodeOuts.vue diff --git a/src/ui/src/builder/BuilderApp.vue b/src/ui/src/builder/BuilderApp.vue index 42bf43348..83e04c26c 100644 --- a/src/ui/src/builder/BuilderApp.vue +++ b/src/ui/src/builder/BuilderApp.vue @@ -71,6 +71,16 @@
+
+ +
@@ -258,6 +268,11 @@ function handleRendererDrop(ev: DragEvent) { function handleRendererClick(ev: PointerEvent): void { if (builderMode.value === "preview") return; + const unselectableEl: HTMLElement = (ev.target as HTMLElement).closest( + "[data-writer-unselectable]", + ); + if (unselectableEl) return; + const targetEl: HTMLElement = (ev.target as HTMLElement).closest( "[data-writer-id]", ); diff --git a/src/ui/src/builder/BuilderFieldsText.vue b/src/ui/src/builder/BuilderFieldsText.vue index a06dab652..65aa35631 100644 --- a/src/ui/src/builder/BuilderFieldsText.vue +++ b/src/ui/src/builder/BuilderFieldsText.vue @@ -16,7 +16,7 @@ @@ -180,6 +184,13 @@ async function addPage() { await nextTick(); ssbm.setSelection(pageId); } + +async function addWorkflow() { + const pageId = createAndInsertComponent("workflow", "root"); + wf.setActivePageId(pageId); + await nextTick(); + ssbm.setSelection(pageId); +} diff --git a/src/ui/src/workflow_components/CorePythonFunction.vue b/src/ui/src/workflow_components/CorePythonFunction.vue new file mode 100644 index 000000000..6fe2d1a41 --- /dev/null +++ b/src/ui/src/workflow_components/CorePythonFunction.vue @@ -0,0 +1,53 @@ + + + + + + diff --git a/src/ui/src/workflow_components/CoreSetState.vue b/src/ui/src/workflow_components/CoreSetState.vue new file mode 100644 index 000000000..a560b0dc5 --- /dev/null +++ b/src/ui/src/workflow_components/CoreSetState.vue @@ -0,0 +1,57 @@ + + + + + + diff --git a/src/ui/src/workflow_components/CoreWorkflow.vue b/src/ui/src/workflow_components/CoreWorkflow.vue new file mode 100644 index 000000000..fd9422570 --- /dev/null +++ b/src/ui/src/workflow_components/CoreWorkflow.vue @@ -0,0 +1,260 @@ + + + + + + diff --git a/src/ui/src/workflow_components/CoreWriterCompletion.vue b/src/ui/src/workflow_components/CoreWriterCompletion.vue new file mode 100644 index 000000000..72d3b708e --- /dev/null +++ b/src/ui/src/workflow_components/CoreWriterCompletion.vue @@ -0,0 +1,55 @@ + + + + + + diff --git a/src/ui/src/workflow_components/WorkflowsArrow.vue b/src/ui/src/workflow_components/WorkflowsArrow.vue new file mode 100644 index 000000000..cca00c46e --- /dev/null +++ b/src/ui/src/workflow_components/WorkflowsArrow.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/ui/src/workflow_components/WorkflowsNodeBox.vue b/src/ui/src/workflow_components/WorkflowsNodeBox.vue new file mode 100644 index 000000000..87b267b9f --- /dev/null +++ b/src/ui/src/workflow_components/WorkflowsNodeBox.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/src/ui/src/workflow_components/WorkflowsNodeOuts.vue b/src/ui/src/workflow_components/WorkflowsNodeOuts.vue new file mode 100644 index 000000000..525cf8d53 --- /dev/null +++ b/src/ui/src/workflow_components/WorkflowsNodeOuts.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/ui/src/writerTypes.ts b/src/ui/src/writerTypes.ts index e9c12df3b..60bc8afe3 100644 --- a/src/ui/src/writerTypes.ts +++ b/src/ui/src/writerTypes.ts @@ -25,14 +25,10 @@ export type Component = { visible?: boolean | string; x?: number; y?: number; - outs?: Record< - string, - { - name: string; - description: string; - style: string; - } - >; + outs?: { + outId: string; + toNodeId: string; + }[]; }; /** @@ -135,14 +131,3 @@ export type ComponentMap = Record; export type MailItem = { type: string; payload: Record }; export type UserFunction = { name: string; args: string[] }; - -export type WorkflowsNode = { - type: string; - content: Record; - x: number; - y: number; - outs: { - outId: string; - toNodeId: string; - }[]; -}; diff --git a/src/writer/core.py b/src/writer/core.py index 8cb2cf442..0d6e5e63a 100644 --- a/src/writer/core.py +++ b/src/writer/core.py @@ -1092,12 +1092,12 @@ def __init__(self, session_state: WriterState, session_component_tree: core_ui.C self.wf = session_state self.ct = session_component_tree - def evaluate_field(self, instance_path: InstancePath, field_key: str, as_json=False, default_field_value="") -> Any: + def evaluate_field(self, instance_path: InstancePath, field_key: str, as_json=False, default_field_value="", base_context={}) -> Any: def replacer(matched): if matched.string[0] == "\\": # Escaped @, don't evaluate return matched.string expr = matched.group(1).strip() - expr_value = self.evaluate_expression(expr, instance_path) + expr_value = self.evaluate_expression(expr, instance_path, base_context) serialised_value = None try: @@ -1123,8 +1123,8 @@ def replacer(matched): else: raise ValueError(f"Couldn't acquire a component by ID '{component_id}'") - def get_context_data(self, instance_path: InstancePath) -> Dict[str, Any]: - context: Dict[str, Any] = {} + def get_context_data(self, instance_path: InstancePath, base_context={}) -> Dict[str, Any]: + context: Dict[str, Any] = base_context for i in range(len(instance_path)): path_item = instance_path[i] component_id = path_item["componentId"] @@ -1211,10 +1211,10 @@ def parse_expression(self, expr: str, instance_path: Optional[InstancePath] = No return accessors - def evaluate_expression(self, expr: str, instance_path: Optional[InstancePath]) -> Any: + def evaluate_expression(self, expr: str, instance_path: Optional[InstancePath] = None, base_context = {}) -> Any: context_data = None if instance_path: - context_data = self.get_context_data(instance_path) + context_data = self.get_context_data(instance_path, base_context) context_ref: Any = context_data state_ref: Any = self.wf.user_state.state accessors: List[str] = self.parse_expression(expr, instance_path) diff --git a/src/writer/core_ui.py b/src/writer/core_ui.py index d5fbd94d0..a4ca8ee21 100644 --- a/src/writer/core_ui.py +++ b/src/writer/core_ui.py @@ -45,6 +45,9 @@ class Component(BaseModel): handlers: Optional[Dict[str, str]] = None visible: Optional[Union[bool, str]] = None binding: Optional[Dict] = None + outs: Optional[Any] = None + x: Optional[int] = None + y: Optional[int] = None def to_dict(self) -> Dict: """ From b3a864818112de009507c79e40268cbc332accb5 Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Mon, 29 Jul 2024 08:47:50 +0000 Subject: [PATCH 3/5] feat: Workflows --- src/ui/src/core/templateMap.ts | 2 + .../workflow_components/CoreTwitterPost.vue | 85 +++++++++++++++++++ .../src/workflow_components/CoreWorkflow.vue | 34 +++++++- .../CoreWriterCompletion.vue | 14 +++ .../workflow_components/WorkflowsArrow.vue | 11 +-- .../workflow_components/WorkflowsNodeBox.vue | 1 - 6 files changed, 133 insertions(+), 14 deletions(-) create mode 100644 src/ui/src/workflow_components/CoreTwitterPost.vue diff --git a/src/ui/src/core/templateMap.ts b/src/ui/src/core/templateMap.ts index 90bb35223..0c27530a1 100644 --- a/src/ui/src/core/templateMap.ts +++ b/src/ui/src/core/templateMap.ts @@ -64,6 +64,7 @@ import CorePythonFunction from "../workflow_components/CorePythonFunction.vue"; import CoreHTTPCall from "../workflow_components/CoreHTTPCall.vue"; import CoreSetState from "../workflow_components/CoreSetState.vue"; import CoreWriterCompletion from "../workflow_components/CoreWriterCompletion.vue"; +import CoreTwitterPost from "../workflow_components/CoreTwitterPost.vue"; import { WriterComponentDefinition } from "../writerTypes"; import { h } from "vue"; @@ -126,6 +127,7 @@ const templateMap = { httpcall: CoreHTTPCall, setstate: CoreSetState, writercompletion: CoreWriterCompletion, + twitterpost: CoreTwitterPost, }; if (WRITER_LIVE_CCT === "yes") { diff --git a/src/ui/src/workflow_components/CoreTwitterPost.vue b/src/ui/src/workflow_components/CoreTwitterPost.vue new file mode 100644 index 000000000..936075e2d --- /dev/null +++ b/src/ui/src/workflow_components/CoreTwitterPost.vue @@ -0,0 +1,85 @@ + + + + + + diff --git a/src/ui/src/workflow_components/CoreWorkflow.vue b/src/ui/src/workflow_components/CoreWorkflow.vue index fd9422570..cb3d191bb 100644 --- a/src/ui/src/workflow_components/CoreWorkflow.vue +++ b/src/ui/src/workflow_components/CoreWorkflow.vue @@ -25,6 +25,7 @@ }" @drag="(ev: DragEvent) => handleNodeDrag(ev, component.id)" @dragstart="(ev: DragEvent) => handleNodeDragStart(ev)" + @dragend="handleNodeDragend" @click="(ev: MouseEvent) => handleNodeClick(ev, component.id)" @out-select=" (outId: string) => handleNodeOutSelect(component.id, outId) @@ -40,6 +41,7 @@ import WorkflowsNodeBox from "./WorkflowsNodeBox.vue"; import WorkflowsNodeOuts from "./WorkflowsNodeOuts.vue"; import WorkflowsArrow from "./WorkflowsArrow.vue"; import { render } from "vue"; +import { watch } from "vue"; const description = "A container component representing a single page within the application."; @@ -146,6 +148,7 @@ function handleDragstart(ev: DragEvent) { function handleDrag(ev: DragEvent) { ev.preventDefault(); const { x, y } = getAdjustedCoordinates(ev); + if (x < 0 || y < 0) return; renderOffset.value.x = Math.max( 0, renderOffset.value.x - (x - clickOffset.x), @@ -179,6 +182,7 @@ function handleDrop(ev: DragEvent) { if (draggedId) return; const { x, y } = getAdjustedCoordinates(ev); + if (x < 0 || y < 0) return; createNode(draggedType, x, y); } @@ -201,13 +205,20 @@ function handleNodeDrag(ev: DragEvent, componentId: Component["id"]) { ev.preventDefault(); ev.stopPropagation(); const { x, y } = getAdjustedCoordinates(ev); + if (x < 0 || y < 0) return; + const component = wf.getComponentById(componentId); component.x = x - clickOffset.x; component.y = y - clickOffset.y; refreshArrows(); } +function handleNodeDragend(ev: DragEvent) { + ev.preventDefault(); +} + function handleNodeClick(ev: MouseEvent, componentId: Component["id"]) { + console.log("clicko"); if (!activeNodeOut.value) return; if (activeNodeOut.value.fromComponentId == componentId) return; @@ -232,6 +243,23 @@ function createNode(type: string, x: number, y: number) { component.y = y; } +watch(children, async (postChildren, preChildren) => { + // Remove references when a node is deleted + + const preIds = preChildren.map((c) => c.id); + const postIds = postChildren.map((c) => c.id); + const removedIds = preIds.filter((cId) => !postIds.includes(cId)); + console.log(removedIds); + removedIds.forEach((removedId) => { + postChildren.forEach((c) => { + if (!c.outs || c.outs.length == 0) return; + c.outs = c.outs.filter((out) => out.toNodeId !== removedId); + }); + }); + refreshArrows(); + await wf.sendComponentUpdate(); +}); + onMounted(() => { refreshArrows(); }); @@ -248,13 +276,11 @@ onMounted(() => { flex: 1 0 auto; flex-direction: row; align-items: stretch; + position: relative; + overflow: hidden; } .component.CoreWorkflow.selected { background: var(--builderSubtleSeparatorColor); } - -.nodeWrapper { - position: absolute; -} diff --git a/src/ui/src/workflow_components/CoreWriterCompletion.vue b/src/ui/src/workflow_components/CoreWriterCompletion.vue index 72d3b708e..a1070982b 100644 --- a/src/ui/src/workflow_components/CoreWriterCompletion.vue +++ b/src/ui/src/workflow_components/CoreWriterCompletion.vue @@ -21,6 +21,20 @@ export default { control: FieldControl.Textarea, desc: "The text to complete.", }, + modelId: { + name: "Model", + type: FieldType.Text, + options: { + "palmyra-x-003-instruct": "palmyra-x-003-instruct", + "palmyra-x-002-instruct": "palmyra-x-002-instruct", + "palmyra-x-32k-instruct": "palmyra-x-32k-instruct", + "palmyra-x-002-32k": "palmyra-x-002-32k", + "palmyra-med-32k": "palmyra-med-32k", + "palmyra-med": "palmyra-med", + "palmyra-fin-32k": "palmyra-fin-32k", + }, + init: "palmyra-x-002-instruct", + }, }, outs: { success: { diff --git a/src/ui/src/workflow_components/WorkflowsArrow.vue b/src/ui/src/workflow_components/WorkflowsArrow.vue index cca00c46e..cee3637ba 100644 --- a/src/ui/src/workflow_components/WorkflowsArrow.vue +++ b/src/ui/src/workflow_components/WorkflowsArrow.vue @@ -35,14 +35,7 @@ const pathD = computed(() => { const xDif = props.arrow.x2 - props.arrow.x1; const yDif = props.arrow.y2 - props.arrow.y1; - const protrusionLength = Math.max( - Math.min( - Math.sqrt(xDif * xDif + yDif * yDif), - 0.8 * Math.abs(xDif), - 50, - ), - 0, - ); + const protrusionLength = 30; const points = [ { x: props.arrow.x1, y: props.arrow.y1 }, @@ -62,7 +55,7 @@ const pathD = computed(() => { let s: string; - if (xDif > 50) { + if (xDif > protrusionLength) { s = `M ${points[0].x} ${points[0].y}`; s += `C ${points[3].x} ${points[0].y}, ${points[3].x} ${points[6].y}, ${points[6].x} ${points[6].y}`; } else { diff --git a/src/ui/src/workflow_components/WorkflowsNodeBox.vue b/src/ui/src/workflow_components/WorkflowsNodeBox.vue index 87b267b9f..385016aad 100644 --- a/src/ui/src/workflow_components/WorkflowsNodeBox.vue +++ b/src/ui/src/workflow_components/WorkflowsNodeBox.vue @@ -5,7 +5,6 @@
- {{ component.outs }}
{{ out.name }}
Date: Mon, 29 Jul 2024 15:19:23 +0000 Subject: [PATCH 4/5] feat: Workflows --- src/ui/src/core/templateMap.ts | 4 ++ .../workflow_components/CoreCreateFile.vue | 61 +++++++++++++++++ .../workflow_components/CoreWriterKGAdd.vue | 68 +++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 src/ui/src/workflow_components/CoreCreateFile.vue create mode 100644 src/ui/src/workflow_components/CoreWriterKGAdd.vue diff --git a/src/ui/src/core/templateMap.ts b/src/ui/src/core/templateMap.ts index 0c27530a1..8f0f9ed8c 100644 --- a/src/ui/src/core/templateMap.ts +++ b/src/ui/src/core/templateMap.ts @@ -65,6 +65,8 @@ import CoreHTTPCall from "../workflow_components/CoreHTTPCall.vue"; import CoreSetState from "../workflow_components/CoreSetState.vue"; import CoreWriterCompletion from "../workflow_components/CoreWriterCompletion.vue"; import CoreTwitterPost from "../workflow_components/CoreTwitterPost.vue"; +import CoreCreateFile from "../workflow_components/CoreCreateFile.vue"; +import CoreWriterKGAdd from "../workflow_components/CoreWriterKGAdd.vue"; import { WriterComponentDefinition } from "../writerTypes"; import { h } from "vue"; @@ -128,6 +130,8 @@ const templateMap = { setstate: CoreSetState, writercompletion: CoreWriterCompletion, twitterpost: CoreTwitterPost, + createfile: CoreCreateFile, + writerkgadd: CoreWriterKGAdd, }; if (WRITER_LIVE_CCT === "yes") { diff --git a/src/ui/src/workflow_components/CoreCreateFile.vue b/src/ui/src/workflow_components/CoreCreateFile.vue new file mode 100644 index 000000000..a225e9f36 --- /dev/null +++ b/src/ui/src/workflow_components/CoreCreateFile.vue @@ -0,0 +1,61 @@ + + + + + + diff --git a/src/ui/src/workflow_components/CoreWriterKGAdd.vue b/src/ui/src/workflow_components/CoreWriterKGAdd.vue new file mode 100644 index 000000000..60eb8acdc --- /dev/null +++ b/src/ui/src/workflow_components/CoreWriterKGAdd.vue @@ -0,0 +1,68 @@ + + + + + + From 650b63b6de12d96a449873bb4bb1d03166a8e5ce Mon Sep 17 00:00:00 2001 From: Ramiro Medina <64783088+ramedina86@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:49:10 +0000 Subject: [PATCH 5/5] feat: Workflows --- src/ui/src/core/templateMap.ts | 2 + .../workflow_components/CoreCreateFile.vue | 10 ++- .../src/workflow_components/CoreHTTPCall.vue | 21 +++-- .../CorePythonFunction.vue | 6 +- .../src/workflow_components/CoreSetState.vue | 18 +++- .../workflow_components/CoreTwitterPost.vue | 6 +- .../CoreWriterCompletion.vue | 17 +++- .../workflow_components/CoreWriterKGAdd.vue | 38 +++++---- .../src/workflow_components/CoreWriterSQL.vue | 82 +++++++++++++++++++ .../workflow_components/WorkflowsNodeBox.vue | 48 +++++++++-- src/writer/core.py | 42 ++++++---- 11 files changed, 234 insertions(+), 56 deletions(-) create mode 100644 src/ui/src/workflow_components/CoreWriterSQL.vue diff --git a/src/ui/src/core/templateMap.ts b/src/ui/src/core/templateMap.ts index b30f28e51..3a896b5ac 100644 --- a/src/ui/src/core/templateMap.ts +++ b/src/ui/src/core/templateMap.ts @@ -69,6 +69,7 @@ import CoreWriterCompletion from "../workflow_components/CoreWriterCompletion.vu import CoreTwitterPost from "../workflow_components/CoreTwitterPost.vue"; import CoreCreateFile from "../workflow_components/CoreCreateFile.vue"; import CoreWriterKGAdd from "../workflow_components/CoreWriterKGAdd.vue"; +import CoreWriterSQL from "../workflow_components/CoreWriterSQL.vue"; import { WriterComponentDefinition } from "../writerTypes"; import { h } from "vue"; @@ -136,6 +137,7 @@ const templateMap = { createfile: CoreCreateFile, writerkgadd: CoreWriterKGAdd, jsonviewer: CoreJsonViewer, + writersql: CoreWriterSQL, }; if (WRITER_LIVE_CCT === "yes") { diff --git a/src/ui/src/workflow_components/CoreCreateFile.vue b/src/ui/src/workflow_components/CoreCreateFile.vue index a225e9f36..6ab1da4bb 100644 --- a/src/ui/src/workflow_components/CoreCreateFile.vue +++ b/src/ui/src/workflow_components/CoreCreateFile.vue @@ -1,5 +1,9 @@ @@ -19,8 +23,8 @@ export default { name: "File name", type: FieldType.Text, }, - content: { - name: "Content", + data: { + name: "Data", type: FieldType.Text, }, fileType: { diff --git a/src/ui/src/workflow_components/CoreHTTPCall.vue b/src/ui/src/workflow_components/CoreHTTPCall.vue index 0e81d842a..b36fe128d 100644 --- a/src/ui/src/workflow_components/CoreHTTPCall.vue +++ b/src/ui/src/workflow_components/CoreHTTPCall.vue @@ -1,12 +1,16 @@ @@ -76,14 +80,15 @@ const component = computed(() => wf.getComponentById(componentId)); } .content { - gap: 4px; + display: block; } .method { - background-color: #b5eeee; + background-color: #f0f0f0; padding: 2px 4px 2px 4px; + margin: 2px 0 2px 0; border-radius: 4px; - display: inline; + display: inline-block; } .url { diff --git a/src/ui/src/workflow_components/CorePythonFunction.vue b/src/ui/src/workflow_components/CorePythonFunction.vue index 6fe2d1a41..f5e83ec0f 100644 --- a/src/ui/src/workflow_components/CorePythonFunction.vue +++ b/src/ui/src/workflow_components/CorePythonFunction.vue @@ -1,5 +1,9 @@ diff --git a/src/ui/src/workflow_components/CoreSetState.vue b/src/ui/src/workflow_components/CoreSetState.vue index a560b0dc5..c52fc0b48 100644 --- a/src/ui/src/workflow_components/CoreSetState.vue +++ b/src/ui/src/workflow_components/CoreSetState.vue @@ -1,6 +1,11 @@ @@ -45,6 +50,7 @@ import injectionKeys from "../injectionKeys"; const wf = inject(injectionKeys.core); const componentId = inject(injectionKeys.componentId); +const fields = inject(injectionKeys.evaluatedFields); const component = computed(() => wf.getComponentById(componentId)); @@ -54,4 +60,12 @@ const component = computed(() => wf.getComponentById(componentId)); .CoreSetState { } + +.highlight { + background-color: #f0f0f0; + padding: 2px 4px 2px 4px; + margin: 2px 0 2px 0; + border-radius: 4px; + display: inline-block; +} diff --git a/src/ui/src/workflow_components/CoreTwitterPost.vue b/src/ui/src/workflow_components/CoreTwitterPost.vue index 936075e2d..cc5d560b7 100644 --- a/src/ui/src/workflow_components/CoreTwitterPost.vue +++ b/src/ui/src/workflow_components/CoreTwitterPost.vue @@ -1,5 +1,9 @@ diff --git a/src/ui/src/workflow_components/CoreWriterCompletion.vue b/src/ui/src/workflow_components/CoreWriterCompletion.vue index a1070982b..c6c2b5206 100644 --- a/src/ui/src/workflow_components/CoreWriterCompletion.vue +++ b/src/ui/src/workflow_components/CoreWriterCompletion.vue @@ -1,6 +1,10 @@ @@ -57,6 +61,7 @@ import injectionKeys from "../injectionKeys"; const wf = inject(injectionKeys.core); const componentId = inject(injectionKeys.componentId); +const fields = inject(injectionKeys.evaluatedFields); const component = computed(() => wf.getComponentById(componentId)); @@ -66,4 +71,12 @@ const component = computed(() => wf.getComponentById(componentId)); .CoreWriterCompletion { } + +.highlight { + background-color: #f0f0f0; + padding: 2px 4px 2px 4px; + margin: 2px 0 2px 0; + border-radius: 4px; + display: inline-block; +} diff --git a/src/ui/src/workflow_components/CoreWriterKGAdd.vue b/src/ui/src/workflow_components/CoreWriterKGAdd.vue index 60eb8acdc..20c32388f 100644 --- a/src/ui/src/workflow_components/CoreWriterKGAdd.vue +++ b/src/ui/src/workflow_components/CoreWriterKGAdd.vue @@ -1,5 +1,9 @@ @@ -15,25 +19,24 @@ export default { category: "Content", allowedParentTypes: ["workflow"], fields: { - text: { - name: "Text", + data: { + name: "Data", type: FieldType.Text, control: FieldControl.Textarea, - desc: "The text to complete.", }, - modelId: { - name: "Model", + type: { + name: "Type", + type: FieldType.Text, + init: "text/plain", + }, + name: { + name: "Name", + type: FieldType.Text, + init: "myfile.txt", + }, + graphId: { + name: "Graph id", type: FieldType.Text, - options: { - "palmyra-x-003-instruct": "palmyra-x-003-instruct", - "palmyra-x-002-instruct": "palmyra-x-002-instruct", - "palmyra-x-32k-instruct": "palmyra-x-32k-instruct", - "palmyra-x-002-32k": "palmyra-x-002-32k", - "palmyra-med-32k": "palmyra-med-32k", - "palmyra-med": "palmyra-med", - "palmyra-fin-32k": "palmyra-fin-32k", - }, - init: "palmyra-x-002-instruct", }, }, outs: { @@ -64,5 +67,6 @@ const component = computed(() => wf.getComponentById(componentId)); diff --git a/src/ui/src/workflow_components/CoreWriterSQL.vue b/src/ui/src/workflow_components/CoreWriterSQL.vue new file mode 100644 index 000000000..6fc0879f0 --- /dev/null +++ b/src/ui/src/workflow_components/CoreWriterSQL.vue @@ -0,0 +1,82 @@ + + + + + + diff --git a/src/ui/src/workflow_components/WorkflowsNodeBox.vue b/src/ui/src/workflow_components/WorkflowsNodeBox.vue index 385016aad..c99f629e2 100644 --- a/src/ui/src/workflow_components/WorkflowsNodeBox.vue +++ b/src/ui/src/workflow_components/WorkflowsNodeBox.vue @@ -1,8 +1,19 @@