Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Workflows function calling support #603

Merged
merged 31 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3cf2b99
feat: Function calling
ramedina86 Oct 16, 2024
c98c121
fix: switch to `create_function_call` function due to lack of default…
mmikita95 Oct 16, 2024
8113e17
fix: optimized clearing registry and tool calls pool
mmikita95 Oct 16, 2024
4a5013d
feat: Function calling support
ramedina86 Oct 21, 2024
9728f0e
feat: Function calling support
ramedina86 Oct 26, 2024
48759f2
feat: Tools field
ramedina86 Oct 26, 2024
2ad1a75
fix: Copy paste for workflows
ramedina86 Oct 26, 2024
8bd9ba1
chore: Refactor, improved connection interaction
ramedina86 Oct 26, 2024
1133753
chore: Add border color transition
ramedina86 Oct 26, 2024
b2c9d2c
feat: Make workflow components not draggable
ramedina86 Oct 26, 2024
673a568
Merge branch 'dev' into feat-workflows-tools-1
ramedina86 Oct 26, 2024
59ccc1c
feat: Added tools
ramedina86 Oct 28, 2024
4fbc4e6
chore: Expanded settings width
ramedina86 Oct 28, 2024
2cb5900
feat: Embedded code editor component
ramedina86 Oct 28, 2024
2b94f38
chore: Tool field
ramedina86 Oct 28, 2024
45048dc
fix: Added real time, replaced placeholder
ramedina86 Oct 28, 2024
ab306f2
chore: Add tool field and category
ramedina86 Oct 28, 2024
4f29fe5
chore: Added execution time
ramedina86 Oct 28, 2024
3e9d5c3
chore: Added time measurement
ramedina86 Oct 28, 2024
ca564e1
chore: Time measurement
ramedina86 Oct 28, 2024
ea5a48c
feat: Tools field
ramedina86 Oct 28, 2024
c2044a2
fix: Mypy/linting fixes
ramedina86 Oct 28, 2024
fd91113
fix: Sync definitions of renderProxiedComponent
ramedina86 Oct 28, 2024
55e5b14
chore: Added instance number
ramedina86 Oct 28, 2024
3b66487
chore: Shrink settings width
ramedina86 Oct 28, 2024
0345c5b
Update src/ui/src/builder/BuilderEmbeddedCodeEditor.vue
ramedina86 Oct 29, 2024
0022cc0
Update src/ui/src/builder/BuilderFieldsTools.vue
ramedina86 Oct 29, 2024
f4e78dd
Revert "Update src/ui/src/builder/BuilderFieldsTools.vue"
ramedina86 Oct 29, 2024
9d324c5
feat: Support tools field
ramedina86 Oct 29, 2024
fccd9df
fix: Linting
ramedina86 Oct 29, 2024
0a95b67
chore: Simplify Ref
ramedina86 Oct 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions src/ui/src/builder/BuilderEmbeddedCodeEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<div ref="builderEditor" class="BuilderEmbeddedCodeEditor">
<div ref="editorContainer" class="editorContainer"></div>
</div>
</template>

<script setup lang="ts">
import * as monaco from "monaco-editor";
Copy link
Collaborator

@madeindjs madeindjs Oct 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might need to use the ESM import, it might improve bundle size. From their sample, they use

Suggested change
import * as monaco from "monaco-editor";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";

Not tested though

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Monaco import was a mess back in the day. I'll create a task and you can look into it in detail, perform tests, etc.

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.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.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.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

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.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
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.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.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.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

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.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
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.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.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.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

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.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

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(() => {
window.removeEventListener("resize", updateDimensions.bind(this));
ramedina86 marked this conversation as resolved.
Show resolved Hide resolved
});
</script>

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

.BuilderEditor {
}

.editorContainer {
height: 200px;
}
</style>
282 changes: 282 additions & 0 deletions src/ui/src/builder/BuilderFieldsTools.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
<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>
Comment on lines +7 to +17
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's clickable, it should be a button (with type="button", otherwise it sends parent form)

Suggested change
<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>
<button
v-for="(tool, toolName) in tools"
:key="toolName"
class="tool"
type="button"
@click="editTool(toolName)"
>
<div class="toolName">{{ toolName }}</div>
<button class="delete" @click.stop="deleteTool(toolName)">
<i class="material-symbols-outlined">delete</i>
</button>
</button>

Otherwise, you need to declare more attributes

Suggested change
<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
v-for="(tool, toolName) in tools"
:key="toolName"
class="tool"
tabindex="0"
@click="editTool(toolName)"
@keydown.enter="editTool(toolName)"
>
<div class="toolName">{{ toolName }}</div>
<button class="delete" @click.stop="deleteTool(toolName)">
<i class="material-symbols-outlined">delete</i>
</button>
</div>

Copy link
Collaborator Author

@ramedina86 ramedina86 Oct 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise it sends parent form

I don't understand this one

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that it needs tabindex and keydown.enter though

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise it sends parent form

I was referring to the type attribute of the <button>. If you don't specify the type="button", it's by default <button type="submit"> (doc). This can make the button submit the parent form if there is any

<form onsubmit="alert('submited')">
  <input type="submit" value="This button triggers submit form" />
  <button type="submit">This button triggers submit form</button>
  <button>This button triggers submit form</button>

  <button type="button">This button doesn't triggers submit form</button>
</form>

Check this codepen

So it's always good to specify type="button" to avoid weird behavior

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I didn't know! Thought it was button by default

</div>

<WdsButton
variant="builder"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variant doesn't exist, no ?

type WdsButtonVariant = "primary" | "secondary" | "tertiary";

size="small"
@click="resetAndShowToolFormModal"
>
<i class="material-symbols-outlined">add</i>
Add tool</WdsButton
>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we create a task to have icon attribute in WdsButton ? For example, here you should have a gap between the icon and the test Figma

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does have a gap, the WdsButton is actually a flex with a gap in it, so whatever you put in the slot comes with a gap.

<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 variant="builder" @click="saveToolForm"
>Save</WdsButton
>
</div>
</BuilderModal>
</div>
</template>

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

Check warning on line 58 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 58 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 58 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 58 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 58 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 58 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 58 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 58 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 58 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 58 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 58 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 58 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
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 63 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 63 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 63 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 63 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 63 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 63 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 63 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 63 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 63 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 63 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 63 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 63 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
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";
name: string;
code: string;
graphId: string;
};

const wf = inject(injectionKeys.core);
const ssbm = inject(injectionKeys.builderManager);
const { setContentValue } = useComponentActions(wf, ssbm);

const initFunctionToolCode = `
{
"description": "An example tool",
"parameters": {
"city": string
}
}
`.trim();

const toolFormInitValue = {
isShown: false,
type: "function" as "function" | "graph",
name: "new_tool",
code: initFunctionToolCode,
graphId: "999-999",
};

const toolForm: Ref<ToolForm> = ref(toolFormInitValue);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const toolForm: Ref<ToolForm> = ref(toolFormInitValue);
const toolForm = ref<ToolForm>(toolFormInitValue);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax is really nice, I didn't know it existed, thanks for bringing it up.


const props = defineProps<{
componentId: Component["id"];
fieldKey: string;
}>();
const { componentId, fieldKey } = toRefs(props);
const component = computed(() => wf.getComponentById(componentId.value));

const tools: ComputedRef<Record<string, Tool>> = computed(() => {
let value = {};
try {
value = JSON.parse(component.value.content[fieldKey.value]);
} catch {
value = {};
}
return value;
});
ramedina86 marked this conversation as resolved.
Show resolved Hide resolved

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 { name } = form;
if (!name) {
errors.push("The name cannot be empty.");
}
if (Object.keys(tools.value).includes(name)) {
errors.push("An existing tool with the specified name already exists.");
}
return errors;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional, but I think it's a better pattern to use computed here. For example.

Suggested change
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 { name } = form;
if (!name) {
errors.push("The name cannot be empty.");
}
if (Object.keys(tools.value).includes(name)) {
errors.push("An existing tool with the specified name already exists.");
}
return errors;
}
const tooolFromForm = computed<Tool | null>(() => {
const { type, code, graphId } = toolForm.value;
if (type == "function") {
return {
...JSON.parse(code),
type,
};
}
if (type == "graph") {
return {
type,
graph_ids: [graphId],
};
}
return null;
});
const toolFormErrors = computed<string[]>(() => {
let errors = [];
const { name } = form;
if (!name) {
errors.push("The name cannot be empty.");
}
if (Object.keys(tools.value).includes(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.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",
name: toolName,
graphId: "",
code: JSON.stringify(tool, undefined, 2),
};
}
if (type == "graph") {
return {
isShown: true,
type: "graph",
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>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't it be scoped ?

@import "@/renderer/colorTransformations.css";

.BuilderFieldsTool {
}

.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>
12 changes: 11 additions & 1 deletion src/ui/src/builder/BuilderLogWorkflowExecution.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
entry.outcome
}}
</td>
<td>1s</td>
<td>{{ formatExecutionTime(entry.executionTimeInSeconds) }}</td>
</tr>
</table>
</div>
Expand Down Expand Up @@ -55,6 +55,16 @@ async function selectBlock(componentId: Component["id"]) {
await nextTick();
wfbm.setSelection(componentId, undefined, "log");
}

function formatExecutionTime(timeInSeconds: number): string {
if (timeInSeconds < 0) {
return "N/A";
}
if (timeInSeconds < 0.1) {
return "< 0.1s";
}
return `${timeInSeconds.toFixed(2)}s`;
}
</script>

<style scoped>
Expand Down
Loading
Loading