Skip to content

Commit

Permalink
Merge pull request #603 from writer/feat-workflows-tools-1
Browse files Browse the repository at this point in the history
feat: Workflows function calling support
  • Loading branch information
ramedina86 authored Oct 29, 2024
2 parents c04a196 + 0a95b67 commit dd0df2f
Show file tree
Hide file tree
Showing 21 changed files with 857 additions and 115 deletions.
4 changes: 2 additions & 2 deletions src/ui/src/builder/BuilderApp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ onMounted(() => {
--builderSubtleHighlightColor: rgba(0, 0, 0, 0.05);
--builderSubtleHighlightColorSolid: #f2f2f2;
--builderDisabledColor: rgb(180, 180, 180);
--builderSidebarWidth: max(265px, 27vh);
--builderSettingsWidth: max(265px, 27vh);
--builderSidebarWidth: 265px;
--builderSettingsWidth: 265px;
--builderActionOngoingColor: #333333;
--builderTopBarHeight: 48px;
--builderWarningTextColor: white;
Expand Down
83 changes: 83 additions & 0 deletions src/ui/src/builder/BuilderEmbeddedCodeEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<template>
<div ref="builderEditor" class="BuilderEmbeddedCodeEditor">
<div ref="editorContainer" class="editorContainer"></div>
</div>
</template>

<script setup lang="ts">
import * as monaco from "monaco-editor";
import "./builderEditorWorker";
import { inject, onMounted, onUnmounted, Ref, ref, toRefs, watch } from "vue";

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'watch' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 10 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'watch' is defined but never used. Allowed unused vars must match /^_/u
import injectionKeys from "../injectionKeys";
const wf = inject(injectionKeys.core);

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 13 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'wf' is assigned a value but never used. Allowed unused vars must match /^_/u
const wfbm = inject(injectionKeys.builderManager);

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 14 in src/ui/src/builder/BuilderEmbeddedCodeEditor.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'wfbm' is assigned a value but never used. Allowed unused vars must match /^_/u
const builderEditor: Ref<HTMLElement> = ref(null);
const editorContainer: Ref<HTMLElement> = ref(null);
let editor: monaco.editor.IStandaloneCodeEditor = null;
// const editorCode = editor.getValue();
// <input
// :value="props.modelValue"
// @input="emit('update:modelValue', ($event.target as HTMLInputElement).value)"
// />
const props = defineProps<{
modelValue: string;
}>();
const { modelValue } = toRefs(props);
const emit = defineEmits(["update:modelValue"]);
// watch(modelValue, (newCode) => {
// const currentCode =
// editor.setValue(newCode);
// });
onMounted(() => {
const targetEl = editorContainer.value;
editor = monaco.editor.create(targetEl, {
value: modelValue.value,
language: "json",
minimap: {
enabled: false,
},
lineNumbers: "off",
scrollbar: {
vertical: "auto",
horizontal: "auto",
},
fontSize: 12,
folding: false,
// theme: "",
});
editor.getModel().onDidChangeContent(() => {
const newCode = editor.getValue();
emit("update:modelValue", newCode);
});
window.addEventListener("resize", updateDimensions.bind(this));
});
function updateDimensions() {
editor.layout();
}
onUnmounted(() => {
editor.dispose();
window.removeEventListener("resize", updateDimensions.bind(this));
});
</script>

<style scoped>
@import "./sharedStyles.css";
.BuilderEditor {
}
.editorContainer {
height: 200px;
}
</style>
287 changes: 287 additions & 0 deletions src/ui/src/builder/BuilderFieldsTools.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
<template>
<div
class="BuilderFieldsTools colorTransformer"
:data-automation-key="props.fieldKey"
>
<div class="tools">
<div
v-for="(tool, toolName) in tools"
:key="toolName"
class="tool"
@click="editTool(toolName)"
>
<div class="toolName">{{ toolName }}</div>
<button class="delete" @click.stop="deleteTool(toolName)">
<i class="material-symbols-outlined">delete</i>
</button>
</div>
</div>

<WdsButton size="small" @click="resetAndShowToolFormModal">
<i class="material-symbols-outlined">add</i>
Add tool</WdsButton
>
<BuilderModal
v-if="toolForm.isShown"
:close-action="customHandlerModalCloseAction"
icon="add"
modal-title="Add tool"
>
<WdsDropdownInput v-model="toolForm.type">
<option value="function">Function</option>
<option value="graph">Knowledge graph</option>
</WdsDropdownInput>
<WdsTextInput v-model="toolForm.name"></WdsTextInput>
<template v-if="toolForm.type == 'function'">
<BuilderEmbeddedCodeEditor
v-model="toolForm.code"
></BuilderEmbeddedCodeEditor>
</template>
<template v-if="toolForm.type == 'graph'">
<WdsTextInput v-model="toolForm.graphId"></WdsTextInput>
</template>
<div>
<WdsButton @click="saveToolForm">Save</WdsButton>
</div>
</BuilderModal>
</div>
</template>

<script setup lang="ts">
import { toRefs, inject, computed, ref } from "vue";
import { Component, FieldControl } from "@/writerTypes";

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 52 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'FieldControl' is defined but never used. Allowed unused vars must match /^_/u
import { useComponentActions } from "./useComponentActions";
import injectionKeys from "../injectionKeys";
import WdsButton from "@/wds/WdsButton.vue";
import BuilderModal, { ModalAction } from "./BuilderModal.vue";
import WdsTextareaInput from "@/wds/WdsTextareaInput.vue";

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.10)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.11)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.12)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u

Check warning on line 57 in src/ui/src/builder/BuilderFieldsTools.vue

View workflow job for this annotation

GitHub Actions / build (3.9)

'WdsTextareaInput' is defined but never used. Allowed unused vars must match /^_/u
import WdsTextInput from "@/wds/WdsTextInput.vue";
import WdsDropdownInput from "@/wds/WdsDropdownInput.vue";
import BuilderEmbeddedCodeEditor from "./BuilderEmbeddedCodeEditor.vue";
type FunctionTool = {
type: "function";
description: string;
parameters: Record<
string,
{
type: string;
description: string;
}
>;
};
type GraphTool = {
type: "graph";
graph_ids: string[];
};
type Tool = FunctionTool | GraphTool;
type ToolForm = {
isShown: boolean;
type: "function" | "graph";
originalName?: string;
name: string;
code: string;
graphId: string;
};
const wf = inject(injectionKeys.core);
const ssbm = inject(injectionKeys.builderManager);
const { setContentValue } = useComponentActions(wf, ssbm);
const initFunctionToolCode = `
{
"description": "Gets info for an employee, given an employee id",
"parameters": {
"id": {"type": "string", "description": "Id of the employee"}
}
}
`.trim();
const toolFormInitValue = {
isShown: false,
type: "function" as "function" | "graph",
name: "new_tool",
code: initFunctionToolCode,
graphId: "999-999",
};
const toolForm = ref<ToolForm>(toolFormInitValue);
const props = defineProps<{
componentId: Component["id"];
fieldKey: string;
}>();
const { componentId, fieldKey } = toRefs(props);
const component = computed(() => wf.getComponentById(componentId.value));
const tools = computed<Record<string, Tool>>(() => {
let value = {};
try {
value = JSON.parse(component.value.content[fieldKey.value]);
} catch {
value = {};
}
return value;
});
function resetAndShowToolFormModal() {
toolForm.value = {
...toolFormInitValue,
isShown: true,
};
}
function getToolFromForm(): Tool {
const { type, code, graphId } = toolForm.value;
if (type == "function") {
return {
...JSON.parse(code),
type,
};
}
if (type == "graph") {
return {
type,
graph_ids: [graphId],
};
}
throw "Unexpected tool type.";
}
function validateToolForm(form: ToolForm): string[] {
let errors = [];
const { originalName, name } = form;
if (!name) {
errors.push("The name cannot be empty.");
}
if (
Object.keys(tools.value).includes(name) &&
!(originalName || originalName == name)
) {
errors.push("An existing tool with the specified name already exists.");
}
return errors;
}
function saveToolForm() {
const formErrors = validateToolForm(toolForm.value);
if (formErrors.length > 0) {
formErrors.forEach(alert);
return;
}
let toolFromForm: ReturnType<typeof getToolFromForm>;
try {
toolFromForm = getToolFromForm();
} catch {
alert("Incorrect tool definition");
return;
}
const newFieldValue = JSON.stringify({
...tools.value,
...(toolForm.value.originalName
? { [toolForm.value.originalName]: undefined }
: {}),
[toolForm.value.name]: toolFromForm,
});
setContentValue(component.value.id, fieldKey.value, newFieldValue);
toolForm.value.isShown = false;
}
function getFormFromToolEntry(toolName: string, tool: Tool): ToolForm {
const { type } = tool;
if (type == "function") {
return {
isShown: true,
type: "function",
originalName: toolName,
name: toolName,
graphId: "",
code: JSON.stringify(tool, undefined, 2),
};
}
if (type == "graph") {
return {
isShown: true,
type: "graph",
originalName: toolName,
name: toolName,
graphId: tool.graph_ids?.[0],
code: "",
};
}
throw "Unexpected tool type;";
}
function editTool(toolName: string) {
const tool = tools.value?.[toolName];
if (!tool) return;
toolForm.value = getFormFromToolEntry(toolName, tool);
}
function deleteTool(toolName: string) {
const newFieldValue = JSON.stringify({
...tools.value,
[toolName]: undefined,
});
setContentValue(component.value.id, fieldKey.value, newFieldValue);
}
const customHandlerModalCloseAction: ModalAction = {
desc: "Close",
fn: () => {
toolForm.value.isShown = false;
},
};
</script>

<style scoped>
@import "./sharedStyles.css";
.BuilderFieldsTools {
--separatorColor: var(--builderSeparatorColor);
--intensifiedButtonColor: red;
}
.tools {
margin-bottom: 8px;
}
.tool {
display: flex;
align-items: center;
min-height: 38px;
padding-top: 4px;
margin-top: 4px;
cursor: pointer;
}
.tool:not(:first-of-type) {
border-top: 1px solid var(--builderSeparatorColor);
}
.tool .toolName {
flex: 1 0 auto;
}
.tool .delete {
display: none;
background: var(--builderBackgroundColor);
padding: 2px 4px 2px 4px;
font-size: 1.1rem;
}
.tool:hover .delete {
display: block;
}
.addToolTextarea {
font-family: monospace;
}
</style>

<style scoped>
@import "./sharedStyles.css";
</style>
Loading

0 comments on commit dd0df2f

Please sign in to comment.