fix: AI copilot available in the vscode flow editor (#3314)

* all

* foo

* add ai to vscode for flows

* add ai to vscode for flows

* foo

* foo
This commit is contained in:
Ruben Fiszel
2024-02-29 20:22:44 +01:00
committed by GitHub
parent 84e2989b2f
commit 00fbacdab4
9 changed files with 121 additions and 41 deletions
+74 -5
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import SchemaForm from '$lib/components/SchemaForm.svelte'
import TestJobLoader from '$lib/components/TestJobLoader.svelte'
import { Button } from '$lib/components/common'
import { Button, Drawer } from '$lib/components/common'
import { WindmillIcon } from '$lib/components/icons'
import LogPanel from '$lib/components/scriptEditor/LogPanel.svelte'
import {
@@ -11,10 +11,14 @@
OpenAPI,
Preview,
type OpenFlow,
type FlowModule
type FlowModule,
WorkspaceService,
type InputTransform,
RawScript,
type PathScript
} from '$lib/gen'
import { inferArgs } from '$lib/infer'
import { userStore, workspaceStore } from '$lib/stores'
import { copilotInfo, userStore, workspaceStore } from '$lib/stores'
import { emptySchema, sendUserToast } from '$lib/utils'
import { Pane, Splitpanes } from 'svelte-splitpanes'
import { onDestroy, onMount, setContext } from 'svelte'
@@ -34,6 +38,9 @@
import { CornerDownLeft, Play } from 'lucide-svelte'
import Toggle from './Toggle.svelte'
import { setLicense } from '$lib/enterpriseUtils'
import { workspacedOpenai } from './copilot/lib'
import type { FlowCopilotContext, FlowCopilotModule } from './copilot/flow'
import { pickScript } from './flows/flowStateUtils'
$: token = $page.url.searchParams.get('wm_token') ?? undefined
$: workspace = $page.url.searchParams.get('workspace') ?? undefined
@@ -45,8 +52,70 @@
OpenAPI.TOKEN = $page.url.searchParams.get('wm_token')!
}
let flowCopilotContext: FlowCopilotContext = {
drawerStore: writable<Drawer | undefined>(undefined),
modulesStore: writable<FlowCopilotModule[]>([]),
currentStepStore: writable<string | undefined>(undefined),
genFlow,
shouldUpdatePropertyType: writable<{
[key: string]: 'static' | 'javascript' | undefined
}>({}),
exprsToSet: writable<{
[key: string]: InputTransform | any | undefined
}>({}),
generatedExprs: writable<{
[key: string]: string | undefined
}>({}),
stepInputsLoading: writable<boolean>(false)
}
const { modulesStore } = flowCopilotContext
async function genFlow(idx: number, flowModules: FlowModule[], stepOnly = false) {
let module = stepOnly ? $modulesStore[0] : $modulesStore[idx]
if (module && module.selectedCompletion) {
const [hubScriptModule, hubScriptState] = await pickScript(
module.selectedCompletion.path,
`${module.selectedCompletion.summary} (${module.selectedCompletion.app})`,
module.id,
undefined
)
const flowModule: FlowModule & {
value: RawScript | PathScript
} = {
id: module.id,
value: hubScriptModule.value,
summary: hubScriptModule.summary
}
$flowStateStore[module.id] = hubScriptState
flowModules.splice(idx, 0, flowModule)
$flowStore = $flowStore
sendUserToast('Added module', false)
}
}
setContext('FlowCopilotContext', flowCopilotContext)
async function setCopilotInfo() {
if (workspace) {
workspacedOpenai.init(workspace, token)
try {
copilotInfo.set(await WorkspaceService.getCopilotInfo({ workspace }))
} catch (err) {
copilotInfo.set({
exists_openai_resource_path: false,
code_completion_enabled: false
})
console.error('Could not get copilot info')
}
}
}
$: if (workspace) {
$workspaceStore = workspace
setCopilotInfo()
}
$: if (workspace && token) {
@@ -242,7 +311,7 @@
}
}
let mode: 'script' | 'flow' = 'script'
let mode: 'script' | 'flow' = 'flow' //'script'
const flowStore = writable({
summary: '',
@@ -478,7 +547,7 @@
</Pane>
<Pane size={33}>
{#key reload}
<FlowEditorPanel noEditor />
<FlowEditorPanel enableAi noEditor />
{/key}
</Pane>
</Splitpanes>
@@ -17,6 +17,7 @@
export let funcDesc: string
export let modules: FlowModule[]
export let trigger = false
export let disableAi = false
// state
let input: HTMLInputElement | undefined
@@ -131,7 +132,7 @@
/>
{/if}
</div>
{#if funcDesc.length > 0}
{#if !disableAi && funcDesc.length > 0}
<ul class="transition-all divide-y">
<li>
<button
+2 -2
View File
@@ -27,13 +27,13 @@ const openaiConfig: ChatCompletionCreateParamsStreaming = {
class WorkspacedOpenai {
private client: OpenAI | undefined
init(workspace: string) {
init(workspace: string, token: string | undefined = undefined) {
const baseURL = `${location.origin}${OpenAPI.BASE}/w/${workspace}/openai/proxy`
this.client = new OpenAI({
baseURL,
apiKey: 'fakekey',
defaultHeaders: {
Authorization: ''
Authorization: token ? `Bearer ${token}` : ''
},
dangerouslyAllowBrowser: true
})
@@ -30,16 +30,17 @@
<SplitPanesWrapper>
<Splitpanes horizontal>
<Pane size={flowModule ? 60 : 100}>
<Alert
type="info"
title="All branches will be run"
tooltip="Branch all"
documentationLink="https://www.windmill.dev/docs/flows/flow_branches#branch-all"
class="m-4"
>
The result of this step is the list of the result of each branch.
</Alert>
{#if !noEditor}
<Alert
type="info"
title="All branches will be run"
tooltip="Branch all"
documentationLink="https://www.windmill.dev/docs/flows/flow_branches#branch-all"
class="m-4"
>
The result of this step is the list of the result of each branch.
</Alert>
{/if}
<div class="p-4 mt-4 w-full">
<h3 class="mb-4"
>{value.branches.length} branch{value.branches.length > 1 ? 'es' : ''}</h3
@@ -32,15 +32,17 @@
<SplitPanesWrapper>
<Splitpanes horizontal>
<Pane size={flowModule ? 60 : 100}>
<Alert
type="info"
title="Only first branch whose condition is true will be run"
tooltip="Branch one"
documentationLink="https://www.windmill.dev/docs/flows/flow_branches#branch-one"
class="m-4"
>
The result of this step is the result of the branch.
</Alert>
{#if !noEditor}
<Alert
type="info"
title="Only first branch whose condition is true will be run"
tooltip="Branch one"
documentationLink="https://www.windmill.dev/docs/flows/flow_branches#branch-one"
class="m-4"
>
The result of this step is the result of the branch.
</Alert>
{/if}
<div class="p-4">
<h3 class="my-4">
{value.branches.length + 1} branch{value.branches.length + 1 > 1 ? 'es' : ''}
@@ -76,16 +76,19 @@
<Splitpanes horizontal class="!max-h-[calc(100%-48px)]">
<Pane size={60} minSize={20} class="p-4">
<Alert
type="info"
title="For loops"
tooltip="For loops"
documentationLink="https://www.windmill.dev/docs/flows/flow_loops"
class="mb-4"
>
Add steps inside the loop and specify an iterator expression that defines the sequence
over which your subsequent steps will iterate.
</Alert>
{#if !noEditor}
<Alert
type="info"
title="For loops"
tooltip="For loops"
documentationLink="https://www.windmill.dev/docs/flows/flow_loops"
class="mb-4"
>
Add steps inside the loop and specify an iterator expression that defines the sequence
over which your subsequent steps will iterate.
</Alert>
{/if}
{#if mod.value.type === 'forloopflow'}
<div class="flex flex-row gap-8 mt-2 mb-6">
<div>
@@ -56,6 +56,7 @@
export let scriptKind: 'script' | 'trigger' | 'approval' = 'script'
export let scriptTemplate: 'pgsql' | 'mysql' | 'script' | 'docker' | 'powershell' = 'script'
export let noEditor: boolean
export let enableAi: boolean
let editor: Editor
let diffEditor: DiffEditor
@@ -334,7 +335,7 @@
previousModuleId={previousModule?.id}
bind:args={flowModule.value.input_transforms}
extraLib={stepPropPicker.extraLib}
enableAi
{enableAi}
/>
</PropPickerWrapper>
</div>
@@ -144,11 +144,13 @@
failureModule={$selectedId === 'failure'}
{scriptKind}
{scriptTemplate}
{enableAi}
/>
{/if}
{:else if flowModule.value.type === 'forloopflow'}
{#each flowModule.value.modules as submodule, index (index)}
<svelte:self
{noEditor}
bind:flowModule={submodule}
bind:parentModule={flowModule}
previousModule={flowModule.value.modules[index - 1]}
@@ -164,6 +166,7 @@
{:else}
{#each flowModule.value.default as submodule, index}
<svelte:self
{noEditor}
bind:flowModule={submodule}
bind:parentModule={flowModule}
previousModule={flowModule.value.default[index - 1]}
@@ -183,6 +186,7 @@
{:else}
{#each branch.modules as submodule, index}
<svelte:self
{noEditor}
bind:flowModule={submodule}
bind:parentModule={flowModule}
previousModule={flowModule.value.branches[branchIndex].modules[index - 1]}
@@ -198,6 +202,7 @@
{:else}
{#each branch.modules as submodule, index}
<svelte:self
{noEditor}
bind:flowModule={submodule}
bind:parentModule={flowModule}
previousModule={flowModule.value.branches[branchIndex].modules[index - 1]}
@@ -36,9 +36,7 @@
<Cross class="mx-[5px]" size={15} />
</button>
<div id="flow-editor-insert-module">
{#if !disableAi}
<StepGen on:insert {index} bind:funcDesc bind:open {close} {modules} />
{/if}
<StepGen on:insert {index} bind:funcDesc bind:open {close} {modules} {disableAi} />
{#if funcDesc.length === 0}
<div class="font-mono divide-y text-xs w-full text-secondary">