Skip to content

Commit

Permalink
Merge pull request #639 from writer/chore-workflows-tests2
Browse files Browse the repository at this point in the history
chore: Refactor and workflows tests
  • Loading branch information
ramedina86 authored Nov 19, 2024
2 parents bfb30f6 + e01a878 commit 3d426ac
Show file tree
Hide file tree
Showing 39 changed files with 825 additions and 701 deletions.
3 changes: 2 additions & 1 deletion src/ui/src/builder/BuilderHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
variant="primary"
size="small"
class="panelToggler"
title="Toggle Code panel"
data-automation-action="toggle-code-panel"
:class="{ active: ssbm.openPanels.has('code') }"
@click="togglePanel('code')"
>
Expand All @@ -60,6 +60,7 @@
variant="primary"
size="small"
class="panelToggler"
data-automation-action="toggle-log-panel"
title="Toggle Log panel"
:class="{ active: ssbm.openPanels.has('log') }"
@click="togglePanel('log')"
Expand Down
39 changes: 15 additions & 24 deletions src/ui/src/builder/BuilderLogWorkflowExecution.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
</div>
<div class="result">
<BuilderModal
v-if="displayedDetails !== null"
v-if="displayedItemId == itemId"
:close-action="{
desc: 'Close',
fn: () => (displayedDetails = null),
fn: () => (displayedItemId = null),
}"
icon="find_in_page"
modal-title="Details"
Expand All @@ -48,10 +48,10 @@
environment of the direct dependents of this
block. There, it's accessible via @{result}.
</p>
<div class="data">
<div class="data" data-automation-key="result">
<SharedJsonViewer
v-if="displayedDetails?.result"
:data="displayedDetails.result"
v-if="item?.result"
:data="item.result"
:initial-depth="1"
class="data"
/>
Expand All @@ -68,12 +68,8 @@
</p>
<div class="data">
<SharedJsonViewer
v-if="
displayedDetails?.executionEnvironment
"
:data="
displayedDetails.executionEnvironment
"
v-if="item?.executionEnvironment"
:data="item.executionEnvironment"
:initial-depth="1"
class="data"
/>
Expand All @@ -89,10 +85,13 @@
determine the result of 'Run workflow'
blocks and 'Chat completion' tool calls.
</p>
<div class="data">
<div
class="data"
data-automation-key="return-value"
>
<SharedJsonViewer
v-if="displayedDetails?.returnValue"
:data="displayedDetails.returnValue"
v-if="item?.returnValue"
:data="item.returnValue"
:initial-depth="1"
class="data"
/>
Expand All @@ -111,15 +110,7 @@
"
variant="secondary"
size="small"
@click="
() =>
(displayedDetails = {
executionEnvironment:
item.executionEnvironment,
result: item.result,
returnValue: item.returnValue,
})
"
@click="() => (displayedItemId = itemId)"
>
<i class="material-symbols-outlined">find_in_page</i>
Details
Expand Down Expand Up @@ -151,7 +142,7 @@ const { goToComponentParentPage } = useComponentActions(wf, wfbm);
const props = defineProps<{
executionLog: WorkflowExecutionLog;
}>();
const displayedDetails = ref(null);
const displayedItemId = ref<number | null>(null);
type EnrichedExecutionLog = WorkflowExecutionLog & {
summary: {
Expand Down
2 changes: 1 addition & 1 deletion src/ui/src/builder/BuilderSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class="windowAction"
tabindex="0"
title="Close (Esc)"
data-automation-action="close"
data-automation-action="close-settings"
@click="closeSettings"
>
<i class="material-symbols-outlined">close</i>
Expand Down
12 changes: 10 additions & 2 deletions src/ui/src/builder/BuilderSidebarTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,19 @@
</div>
</div>
<div class="add">
<button v-if="rootType == 'root'" @click="addPage">
<button
v-if="rootType == 'root'"
data-automation-action="add-page"
@click="addPage"
>
<i class="material-symbols-outlined"> add </i>
Add Page
</button>
<button v-if="rootType == 'workflows_root'" @click="addWorkflow">
<button
v-if="rootType == 'workflows_root'"
data-automation-action="add-workflow"
@click="addWorkflow"
>
<i class="material-symbols-outlined"> add </i>
Add Workflow
</button>
Expand Down
8 changes: 7 additions & 1 deletion src/ui/src/builder/BuilderSwitcher.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<template>
<div class="BuilderSwitcher">
<div :class="{ active: activeId == 'ui' }" @click="selectOption('ui')">
<div
data-automation-action="set-mode-ui"
:class="{ active: activeId == 'ui' }"
@click="selectOption('ui')"
>
<i class="icon material-symbols-outlined"> brush </i>
UI
</div>
<div
v-if="isWorkflowsFeatureFlagged"
data-automation-action="set-mode-workflows"
:class="{ active: activeId == 'workflows' }"
@click="selectOption('workflows')"
>
Expand All @@ -14,6 +19,7 @@
</div>
<div
:class="{ active: activeId == 'preview' }"
data-automation-action="set-mode-preview"
@click="selectOption('preview')"
>
<i class="icon material-symbols-outlined"> preview </i>
Expand Down
1 change: 1 addition & 0 deletions src/ui/src/components/workflows/WorkflowsWorkflow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
variant="secondary"
size="small"
:data-writer-unselectable="true"
data-automation-action="run-workflow"
@click="handleRun"
>
<i class="material-symbols-outlined">play_arrow</i>
Expand Down
1 change: 1 addition & 0 deletions src/ui/src/core/auditAndFix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ function auditOrphanComponents(components: ComponentMap) {
Object.entries(components).map(([componentId]) => [componentId, false]),
);
traverseComponentTree("root", components, visited);
traverseComponentTree("workflows_root", components, visited);
Object.entries(visited).forEach(([componentId, isVisited]) => {
if (!isVisited) {
console.warn(
Expand Down
31 changes: 31 additions & 0 deletions src/writer/blocks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from writer.blocks.addtostatelist import AddToStateList
from writer.blocks.calleventhandler import CallEventHandler
from writer.blocks.foreach import ForEach
from writer.blocks.httprequest import HTTPRequest
from writer.blocks.logmessage import LogMessage
from writer.blocks.parsejson import ParseJSON
from writer.blocks.returnvalue import ReturnValue
from writer.blocks.runworkflow import RunWorkflow
from writer.blocks.setstate import SetState
from writer.blocks.writeraddchatmessage import WriterAddChatMessage
from writer.blocks.writerchat import WriterChat
from writer.blocks.writerclassification import WriterClassification
from writer.blocks.writercompletion import WriterCompletion
from writer.blocks.writerinitchat import WriterInitChat
from writer.blocks.writernocodeapp import WriterNoCodeApp

SetState.register("workflows_setstate")
WriterClassification.register("workflows_writerclassification")
WriterCompletion.register("workflows_writercompletion")
HTTPRequest.register("workflows_httprequest")
RunWorkflow.register("workflows_runworkflow")
WriterNoCodeApp.register("workflows_writernocodeapp")
ForEach.register("workflows_foreach")
LogMessage.register("workflows_logmessage")
WriterChat.register("workflows_writerchat")
WriterAddChatMessage.register("workflows_writeraddchatmessage")
ParseJSON.register("workflows_parsejson")
CallEventHandler.register("workflows_calleventhandler")
AddToStateList.register("workflows_addtostatelist")
ReturnValue.register("workflows_returnvalue")
WriterInitChat.register("workflows_writerinitchat")
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class AddToStateList(WorkflowBlock):
Expand Down Expand Up @@ -45,15 +45,15 @@ def run(self):
element_expr = self._get_field("element")
value = self._get_field("value")

element = self.evaluator.evaluate_expression(element_expr, self.instance_path, self.execution_env)
element = self.runner.evaluator.evaluate_expression(element_expr, self.instance_path, self.execution_environment)

if not element:
element = []
elif not isinstance(element, list):
element = [element]

element.append(value)
self.evaluator.set_state(element_expr, self.instance_path, element, base_context=self.execution_env)
self._set_state(element_expr, element)
self.outcome = "success"
except BaseException as e:
self.outcome = "error"
Expand Down
43 changes: 43 additions & 0 deletions src/writer/blocks/base_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import TYPE_CHECKING, Any, Dict, Type

import writer.evaluator

if TYPE_CHECKING:
from writer.core_ui import Component
from writer.ss_types import InstancePath
from writer.workflows import WorkflowRunner

WorkflowBlock_T = Type["WorkflowBlock"]
block_map:Dict[str, WorkflowBlock_T] = {}

class WorkflowBlock:

@classmethod
def register(cls, type: str):
block_map[type] = cls

def __init__(self, component: "Component", runner: "WorkflowRunner", execution_environment: Dict):
self.outcome = None
self.component = component
self.runner = runner
self.execution_time_in_seconds = -1.0
self.execution_environment = execution_environment
self.result = None
self.return_value = None
self.instance_path: InstancePath = [{"componentId": self.component.id, "instanceNumber": 0}]
self.evaluator = writer.evaluator.Evaluator(runner.session.session_state, runner.session.session_component_tree)

def _get_field(self, field_key: str, as_json=False, default_field_value=None):
if default_field_value is None:
if as_json:
default_field_value = "{}"
else:
default_field_value = ""
value = self.evaluator.evaluate_field(self.instance_path, field_key, as_json, default_field_value, self.execution_environment)
return value

def _set_state(self, expr: str, value: Any):
self.evaluator.set_state(expr, self.instance_path, value, base_context=self.execution_environment)

def run(self):
pass
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import inspect

import writer.core
import writer.workflows
from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class CallEventHandler(WorkflowBlock):
Expand Down Expand Up @@ -58,7 +57,7 @@ def run(self):

args = {
"state": self.session.session_state,
"context": self.execution_env,
"context": self.execution_environment,
"session": writer.core._event_handler_session_info(),
} | additional_args

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import writer.workflows
from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class ForEach(WorkflowBlock):
Expand Down Expand Up @@ -52,22 +51,23 @@ def register(cls, type: str):
}
))

def _run_workflow_for_item(self, workflow_key, base_execution_env, item_id, item):
return writer.workflows.run_workflow_by_key(self.session, workflow_key, base_execution_env | { "itemId": item_id, "item": item })
def _run_workflow_for_item(self, workflow_key, base_execution_environment, item_id, item):
expanded_execution_environment = base_execution_environment | { "itemId": item_id, "item": item }
return self.runner.run_workflow_by_key(workflow_key, expanded_execution_environment)

def run(self):
try:
workflow_key = self._get_field("workflowKey")
items = self._get_field("items", as_json=True)
base_execution_env = self._get_field("executionEnv", as_json=True)
base_execution_environment = self._get_field("executionEnv", as_json=True)
std_items = items
result = None
if isinstance(items, list):
std_items = enumerate(std_items, 0)
result = [self._run_workflow_for_item(workflow_key, base_execution_env, item_id, item) for item_id, item in std_items]
result = [self._run_workflow_for_item(workflow_key, base_execution_environment, item_id, item) for item_id, item in std_items]
elif isinstance(items, dict):
std_items = items.items()
result = {item_id:self._run_workflow_for_item(workflow_key, base_execution_env, item_id, item) for item_id, item in std_items}
result = {item_id:self._run_workflow_for_item(workflow_key, base_execution_environment, item_id, item) for item_id, item in std_items}

self.result = result
self.outcome = "success"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import requests

from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class HTTPRequest(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import writer.workflows
from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class LogMessage(WorkflowBlock):
Expand Down Expand Up @@ -54,8 +53,11 @@ def run(self):
if message is None:
self.result = "Message cannot be empty."
self.outcome = "error"
return

self.session.session_state.add_log_entry(type, "Workflows message", message)
self.runner.state.add_log_entry(type, "Workflows message", message)
import time
self.runner.state.add_log_entry("error", "Workflows message", f"gato {time.time()}")
self.result = None
self.outcome = "success"
except BaseException as e:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import json

from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class ParseJSON(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import writer.workflows
from writer.abstract import register_abstract_template
from writer.blocks.base_block import WorkflowBlock
from writer.ss_types import AbstractTemplate
from writer.workflows_blocks.blocks import WorkflowBlock


class ReturnValue(WorkflowBlock):
Expand Down
Loading

0 comments on commit 3d426ac

Please sign in to comment.