diff --git a/frontend/src/lib/components/EditorBar.svelte b/frontend/src/lib/components/EditorBar.svelte
index 5b5681b3b3..91044ead7a 100644
--- a/frontend/src/lib/components/EditorBar.svelte
+++ b/frontend/src/lib/components/EditorBar.svelte
@@ -76,6 +76,7 @@
diffMode?: boolean
showHistoryDrawer?: boolean
right?: import('svelte').Snippet
+ openAiChat?: boolean
}
let {
@@ -98,7 +99,8 @@
lastDeployedCode = undefined,
diffMode = false,
showHistoryDrawer = $bindable(false),
- right
+ right,
+ openAiChat = false
}: Props = $props()
let contextualVariablePicker: ItemPicker | undefined = $state()
@@ -810,7 +812,7 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
{/if}
{#if customUi?.aiGen != false}
-
+
{/if}
diff --git a/frontend/src/lib/components/copilot/ScriptGen.svelte b/frontend/src/lib/components/copilot/ScriptGen.svelte
index 02e48cf20a..cb7ab6c946 100644
--- a/frontend/src/lib/components/copilot/ScriptGen.svelte
+++ b/frontend/src/lib/components/copilot/ScriptGen.svelte
@@ -28,6 +28,7 @@
import { twMerge } from 'tailwind-merge'
import { onDestroy } from 'svelte'
import ProviderModelSelector from './chat/ProviderModelSelector.svelte'
+ import { aiChatManager, AIMode } from './chat/AIChatManager.svelte'
interface Props {
// props
@@ -38,6 +39,7 @@
inlineScript?: boolean
args: Record
transformer?: boolean
+ openAiChat?: boolean
}
let {
@@ -47,7 +49,8 @@
diffEditor,
inlineScript = false,
args,
- transformer = false
+ transformer = false,
+ openAiChat = false
}: Props = $props()
run(() => {
@@ -72,6 +75,54 @@
run(() => {
trimmedDesc = funcDesc.trim()
})
+ async function callCopilot() {
+ if (mode === 'edit') {
+ await copilot(
+ {
+ // @ts-ignore
+ language: transformer && lang === 'frontend' ? 'transformer' : lang!,
+ description: trimmedDesc,
+ code: editor?.getCode() || '',
+ dbSchema: dbSchema,
+ type: 'edit',
+ workspace: $workspaceStore!
+ },
+ generatedCode,
+ abortController
+ )
+ } else {
+ await copilot(
+ {
+ // @ts-ignore
+ language: transformer && lang === 'frontend' ? 'transformer' : lang!,
+ description: trimmedDesc,
+ dbSchema: dbSchema,
+ type: 'gen',
+ workspace: $workspaceStore!
+ },
+ generatedCode,
+ abortController
+ )
+ }
+ }
+
+ function handleAiButtonClick() {
+ if (editor && isInitialCode(editor.getCode())) {
+ mode = 'gen'
+ } else {
+ mode = 'edit'
+ }
+
+ if (openAiChat) {
+ // Open the AI chat in script mode
+ aiChatManager.openChat()
+ aiChatManager.changeMode(AIMode.SCRIPT)
+ } else {
+ setTimeout(() => {
+ autoResize()
+ }, 0)
+ }
+ }
async function onGenerate(closePopup: () => void) {
if (trimmedDesc.length <= 0) {
@@ -82,34 +133,7 @@
genLoading = true
blockPopupOpen = true
abortController = new AbortController()
- if (mode === 'edit') {
- await copilot(
- {
- // @ts-ignore
- language: transformer && lang === 'frontend' ? 'transformer' : lang!,
- description: trimmedDesc,
- code: editor?.getCode() || '',
- dbSchema: dbSchema,
- type: 'edit',
- workspace: $workspaceStore!
- },
- generatedCode,
- abortController
- )
- } else {
- await copilot(
- {
- // @ts-ignore
- language: transformer && lang === 'frontend' ? 'transformer' : lang!,
- description: trimmedDesc,
- dbSchema: dbSchema,
- type: 'gen',
- workspace: $workspaceStore!
- },
- generatedCode,
- abortController
- )
- }
+ await callCopilot()
setupDiff()
diffEditor?.setModified($generatedCode)
blockPopupOpen = false
@@ -205,14 +229,27 @@
}
let promptHistory: string[] = $state([])
- function getPromptHistory() {
+
+ function getPromptStorageKey() {
+ return 'prompts-' + lang
+ }
+
+ function safeLocalStorageOperation(operation: () => T, defaultValue?: T): T | undefined {
try {
- promptHistory = JSON.parse(localStorage.getItem('prompts-' + lang) || '[]')
+ return operation()
} catch (e) {
console.error('error interacting with local storage', e)
+ return defaultValue
}
}
+ function getPromptHistory() {
+ const storageKey = getPromptStorageKey()
+ promptHistory =
+ safeLocalStorageOperation(() => JSON.parse(localStorage.getItem(storageKey) || '[]'), []) ||
+ []
+ }
+
function savePrompt() {
if (promptHistory.includes(trimmedDesc)) {
return
@@ -221,20 +258,14 @@
while (promptHistory.length > 5) {
promptHistory.pop()
}
- try {
- localStorage.setItem('prompts-' + lang, JSON.stringify(promptHistory))
- } catch (e) {
- console.error('error interacting with local storage', e)
- }
+ const storageKey = getPromptStorageKey()
+ safeLocalStorageOperation(() => localStorage.setItem(storageKey, JSON.stringify(promptHistory)))
}
function clearPromptHistory() {
promptHistory = []
- try {
- localStorage.setItem('prompts-' + lang, JSON.stringify(promptHistory))
- } catch (e) {
- console.error('error interacting with local storage', e)
- }
+ const storageKey = getPromptStorageKey()
+ safeLocalStorageOperation(() => localStorage.setItem(storageKey, JSON.stringify(promptHistory)))
}
run(() => {
lang && getPromptHistory()
@@ -266,6 +297,12 @@
;(dbSchema as any).publicOnly = detail === 'true'
}
+ const aiChatScriptModeClasses = $derived(
+ aiChatManager.mode === AIMode.SCRIPT && aiChatManager.isOpen
+ ? 'dark:bg-violet-900 bg-violet-100'
+ : ''
+ )
+
onDestroy(() => {
abortController?.abort()
})
@@ -343,22 +380,9 @@