mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
* wip: openai proxy and other ai proxy integration * fixing migration script * wip: support different ai provider in front, fix proxy openai * wip: adding frontend ai provider * updated copilot types * wip: working on anthropic integration * done AI proxy front * adding new type and support for anthropic * updating gitignore * adding streaming response * added streaming prompt * push lib/gen * wip: fixing anthropic * anthropic fully supported * fix backend missing var error and fully support stream event for anthropic * remove gen directory * fixing openapi file * add support for mistral, and update create workspace components * remove deref.json * remove package-json * openapi * fix ui enable code * added utility function for init workspace ai provider * fix workspace switch bug * update anthropic property and fixed frontend error * fix workspace settings * update error message and fix typo migration file * chore: update openapi file * fix dev file * add .sqlx * all * update sqlx --------- Co-authored-by: dieriba <t.dieriba@gmail.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: Ruben Fiszel <ruben@rubenfiszel.com>
182 lines
4.7 KiB
Svelte
182 lines
4.7 KiB
Svelte
<script lang="ts">
|
|
import { base } from '$lib/base'
|
|
import { Button } from '../common'
|
|
|
|
import { getNonStreamingCompletion, type AiProviderTypes } from './lib'
|
|
import { sendUserToast } from '$lib/toast'
|
|
import Popup from '../common/popup/Popup.svelte'
|
|
import { copilotInfo } from '$lib/stores'
|
|
|
|
import { autoPlacement } from '@floating-ui/core'
|
|
import { ExternalLink, HistoryIcon, Wand2 } from 'lucide-svelte'
|
|
import { createEventDispatcher } from 'svelte'
|
|
|
|
// state
|
|
let funcDesc: string = ''
|
|
let genLoading: boolean = false
|
|
let input: HTMLInputElement | undefined
|
|
let abortController: AbortController | undefined = undefined
|
|
|
|
const dispatch = createEventDispatcher()
|
|
async function onGenerate() {
|
|
if (funcDesc?.length <= 0) {
|
|
return
|
|
}
|
|
savePrompt()
|
|
genLoading = true
|
|
abortController = new AbortController()
|
|
const aiProvider = $copilotInfo.ai_provider
|
|
try {
|
|
const res = await getNonStreamingCompletion(
|
|
[
|
|
{
|
|
role: 'system',
|
|
content:
|
|
'Generate a regex pattern that one can use in a javascript Regex object. Output only the regex itself without any wrapping characters including the / characters. The regex should match the following:'
|
|
},
|
|
{
|
|
role: 'user',
|
|
content: funcDesc
|
|
}
|
|
],
|
|
abortController,
|
|
aiProvider as AiProviderTypes
|
|
)
|
|
dispatch('gen', { res: res, prompt: funcDesc })
|
|
funcDesc = ''
|
|
} catch (err) {
|
|
if (!abortController.signal.aborted) {
|
|
sendUserToast('Failed to generate regex: ' + err, true)
|
|
}
|
|
} finally {
|
|
genLoading = false
|
|
}
|
|
}
|
|
|
|
$: input && setTimeout(() => input?.focus(), 100)
|
|
|
|
let promptHistory: string[] = JSON.parse(getPromptsRegex() || '[]')
|
|
|
|
function getPromptsRegex(): string | undefined {
|
|
try {
|
|
return localStorage.getItem('prompts-regex') ?? undefined
|
|
} catch (e) {
|
|
console.error('error interacting with local storage', e)
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
function savePrompt() {
|
|
if (promptHistory.includes(funcDesc)) {
|
|
return
|
|
}
|
|
promptHistory.unshift(funcDesc)
|
|
while (promptHistory.length > 5) {
|
|
promptHistory.pop()
|
|
}
|
|
try {
|
|
localStorage.setItem('prompts-regex', JSON.stringify(promptHistory))
|
|
} catch (e) {
|
|
console.error('error interacting with local storage', e)
|
|
}
|
|
}
|
|
|
|
function clearPromptHistory() {
|
|
promptHistory = []
|
|
try {
|
|
localStorage.setItem('prompts-regex', JSON.stringify(promptHistory))
|
|
} catch (e) {
|
|
console.error('error interacting with local storage', e)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<Popup
|
|
floatingConfig={{
|
|
middleware: [
|
|
autoPlacement({
|
|
allowedPlacements: ['bottom-start', 'bottom-end', 'top-start', 'top-end', 'top', 'bottom']
|
|
})
|
|
]
|
|
}}
|
|
let:close
|
|
>
|
|
<svelte:fragment slot="button">
|
|
<Button
|
|
title="Generate regexes from prompt"
|
|
btnClasses="text-violet-800 dark:text-violet-400 bg-violet-100 dark:bg-gray-700"
|
|
size="sm"
|
|
color={genLoading ? 'red' : 'light'}
|
|
spacingSize="md"
|
|
startIcon={{ icon: Wand2 }}
|
|
loading={genLoading}
|
|
propagateEvent
|
|
clickableWhileLoading
|
|
on:click={genLoading ? () => abortController?.abort() : () => {}}
|
|
/>
|
|
</svelte:fragment>
|
|
<div class="block text-primary z-[2000]">
|
|
{#if $copilotInfo.exists_ai_resource}
|
|
<div class="flex flex-col gap-4">
|
|
<div class="flex w-96">
|
|
<input
|
|
type="text"
|
|
bind:this={input}
|
|
bind:value={funcDesc}
|
|
on:keypress={({ key }) => {
|
|
if (key === 'Enter' && funcDesc?.length > 0) {
|
|
close(input || null)
|
|
onGenerate()
|
|
}
|
|
}}
|
|
placeholder={'Describe what the regex should do'}
|
|
/>
|
|
<Button
|
|
size="xs"
|
|
color="light"
|
|
buttonType="button"
|
|
btnClasses="!ml-2 text-violet-800 dark:text-violet-400 bg-violet-100 dark:bg-gray-700"
|
|
aria-label="Generate"
|
|
on:click={() => {
|
|
close(input || null)
|
|
onGenerate()
|
|
}}
|
|
disabled={funcDesc?.length <= 0}
|
|
iconOnly
|
|
startIcon={{ icon: Wand2 }}
|
|
/>
|
|
</div>
|
|
{#if promptHistory.length > 0}
|
|
<div class="w-96 flex flex-col gap-1">
|
|
{#each promptHistory as p}
|
|
<Button
|
|
size="xs2"
|
|
color="light"
|
|
btnClasses="justify-start overflow-x-scroll no-scrollbar"
|
|
startIcon={{ icon: HistoryIcon, classes: 'shrink-0' }}
|
|
on:click={() => {
|
|
funcDesc = p
|
|
}}>{p}</Button
|
|
>
|
|
{/each}
|
|
<button
|
|
class="underline text-xs text-start px-2 text-secondary font-normal"
|
|
on:click={clearPromptHistory}>clear history</button
|
|
>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{:else}
|
|
<p class="text-sm">
|
|
Enable Windmill AI in the <a
|
|
href="{base}/workspace_settings?tab=ai"
|
|
target="_blank"
|
|
class="inline-flex flex-row items-center gap-1"
|
|
>
|
|
workspace settings <ExternalLink size={16} />
|
|
</a>
|
|
</p>
|
|
{/if}
|
|
</div>
|
|
</Popup>
|