diff --git a/frontend/src/lib/components/AskAiButton.svelte b/frontend/src/lib/components/AskAiButton.svelte index 0ad318e889..80230e923d 100644 --- a/frontend/src/lib/components/AskAiButton.svelte +++ b/frontend/src/lib/components/AskAiButton.svelte @@ -11,7 +11,7 @@ const { label, initialInput, onClick: onClickProp }: Props = $props() - const onClick = () => { + export function onClick() { globalChatOpen.set(true) if (initialInput) { globalChatInitialInput.set(initialInput) diff --git a/frontend/src/lib/components/chat/GlobalChat.svelte b/frontend/src/lib/components/chat/GlobalChat.svelte index 8a1796be9e..5e1938481f 100644 --- a/frontend/src/lib/components/chat/GlobalChat.svelte +++ b/frontend/src/lib/components/chat/GlobalChat.svelte @@ -1,112 +1,26 @@
- +
diff --git a/frontend/src/lib/components/copilot/chat/AIChat.svelte b/frontend/src/lib/components/copilot/chat/AIChat.svelte index d2fd5a2118..ee8a945f54 100644 --- a/frontend/src/lib/components/copilot/chat/AIChat.svelte +++ b/frontend/src/lib/components/copilot/chat/AIChat.svelte @@ -30,15 +30,13 @@ ChatCompletionMessageParam, ChatCompletionSystemMessageParam } from 'openai/resources/index.mjs' -<<<<<<< HEAD import { chatMode, copilotSessionModel, dbSchemas, workspaceStore } from '$lib/stores' -======= import { navigatorTools, prepareNavigatorSystemMessage, prepareNavigatorUserMessage } from './navigator/core' ->>>>>>> 332040744 (integrate navigator mode) + import { globalChatInitialInput } from '$lib/stores' interface Props { scriptOptions?: ScriptOptions flowHelpers?: FlowAIChatHelpers & { @@ -49,6 +47,9 @@ applyCode?: (code: string) => void headerLeft?: Snippet headerRight?: Snippet + suggestions?: string[] + disabled?: boolean + disabledMessage?: string } let { @@ -58,7 +59,10 @@ showDiffMode, headerLeft, headerRight, - navigatorMode = false + navigatorMode = false, + disabled = false, + disabledMessage = '', + suggestions = [] }: Props = $props() let instructions = $state('') @@ -69,23 +73,14 @@ flow: flowHelpers !== undefined, navigator: navigatorMode }) -<<<<<<< HEAD - - async function updateMode(currentMode: 'script' | 'flow') { - if (!allowedModes[currentMode]) { - chatMode.set(currentMode === 'script' ? 'flow' : 'script') -======= - let mode: 'script' | 'flow' | 'navigator' = $state( - flowHelpers ? 'flow' : scriptOptions ? 'script' : 'navigator' - ) async function updateMode(currentMode: 'script' | 'flow' | 'navigator') { if (!allowedModes[currentMode] && Object.keys(allowedModes).length === 1) { const firstKey = Object.keys(allowedModes)[0] - mode = firstKey as 'script' | 'flow' | 'navigator' ->>>>>>> 332040744 (integrate navigator mode) + chatMode.set(firstKey as 'script' | 'flow' | 'navigator') } } + $effect(() => { updateMode(untrack(() => $chatMode)) }) @@ -94,6 +89,14 @@ let abortController: AbortController | undefined = undefined let messages: ChatCompletionMessageParam[] = $state([]) + $effect(() => { + if ($globalChatInitialInput.length > 0) { + instructions = $globalChatInitialInput + globalChatInitialInput.set('') + sendRequest() + } + }) + setContext('AIChatContext', { loading, currentReply, @@ -141,15 +144,11 @@ instructions = '' const systemMessage = -<<<<<<< HEAD - $chatMode === 'script' ? prepareScriptSystemMessage() : prepareFlowSystemMessage() -======= - mode === 'script' + $chatMode === 'script' ? prepareScriptSystemMessage() - : mode === 'flow' + : $chatMode === 'flow' ? prepareFlowSystemMessage() : prepareNavigatorSystemMessage() ->>>>>>> 332040744 (integrate navigator mode) if ($chatMode === 'flow' && !flowHelpers) { throw new Error('No flow helpers passed') @@ -402,4 +401,7 @@ !!scriptOptions.lastDeployedCode && scriptOptions.lastDeployedCode !== scriptOptions.code} diffMode={scriptOptions?.diffMode ?? false} + {disabled} + {disabledMessage} + {suggestions} > diff --git a/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte b/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte index f47272fc40..7e72e5c995 100644 --- a/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte +++ b/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte @@ -15,6 +15,7 @@ import ProviderModelSelector from './ProviderModelSelector.svelte' import ChatMode from './ChatMode.svelte' import { chatMode } from '$lib/stores' + import Markdown from 'svelte-exmarkdown' let { allowedModes, @@ -32,7 +33,10 @@ cancel, askAi = () => {}, // todo: remove default, headerLeft, - headerRight + headerRight, + disabled = false, + disabledMessage = '', + suggestions = [] }: { allowedModes: { script: boolean @@ -54,6 +58,9 @@ askAi?: (instructions: string, options?: { withCode?: boolean; withDiff?: boolean }) => void headerLeft?: Snippet headerRight?: Snippet + disabled?: boolean + disabledMessage?: string + suggestions?: string[] } = $props() const { loading, currentReply } = getContext('AIChatContext') @@ -106,6 +113,11 @@ return -1 } + function submitSuggestion(suggestion: string) { + instructions = suggestion + sendRequest() + } + const lastUserMessageIndex = $derived(findLastIndex(messages, (m) => m.role === 'user')) @@ -294,6 +306,7 @@ } }} on:updateInstructions={(e) => (instructions = e.detail.value)} + {disabled} /> {:else}
@@ -309,6 +322,7 @@ rows={3} placeholder={messages.length === 0 ? 'Ask anything' : 'Ask followup'} class="resize-none" + {disabled} >
{/if} @@ -320,10 +334,32 @@ {#if $chatMode === 'script' && hasDiff} {/if} -
- - -
+ {#if disabled} +
+ +
+ {:else} +
+ + +
+ {/if} + {#if suggestions.length > 0 && messages.filter((m) => m.role === 'user').length === 0 && !disabled} +
+
+ {#each suggestions as suggestion} + + {/each} +
+
+ {/if} diff --git a/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte b/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte index e4ce6f93ac..75b2a4ecb1 100644 --- a/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte +++ b/frontend/src/lib/components/copilot/chat/AssistantMessage.svelte @@ -3,6 +3,7 @@ import { gfmPlugin } from 'svelte-exmarkdown/gfm' import type { DisplayMessage } from './shared' import CodeDisplay from './script/CodeDisplay.svelte' + import LinkRenderer from './LinkRenderer.svelte' import { setContext } from 'svelte' export let message: DisplayMessage @@ -21,7 +22,8 @@ gfmPlugin(), { renderer: { - pre: CodeDisplay + pre: CodeDisplay, + a: LinkRenderer } } ]} diff --git a/frontend/src/lib/components/copilot/chat/ContextTextarea.svelte b/frontend/src/lib/components/copilot/chat/ContextTextarea.svelte index 964c843a1c..b4d2f04af9 100644 --- a/frontend/src/lib/components/copilot/chat/ContextTextarea.svelte +++ b/frontend/src/lib/components/copilot/chat/ContextTextarea.svelte @@ -8,6 +8,7 @@ export let availableContext: ContextElement[] export let selectedContext: ContextElement[] export let isFirstMessage: boolean + export let disabled: boolean = false const dispatch = createEventDispatcher<{ updateInstructions: { value: string } @@ -319,6 +320,7 @@ style={instructions.length > 0 ? 'color: transparent; -webkit-text-fill-color: transparent;' : ''} + {disabled} > diff --git a/frontend/src/lib/components/copilot/chat/LinkRenderer.svelte b/frontend/src/lib/components/copilot/chat/LinkRenderer.svelte new file mode 100644 index 0000000000..87d131e03e --- /dev/null +++ b/frontend/src/lib/components/copilot/chat/LinkRenderer.svelte @@ -0,0 +1,15 @@ + + +{#if href} + + {@render children?.()} + +{/if} diff --git a/frontend/src/lib/components/copilot/chat/script/CodeDisplay.svelte b/frontend/src/lib/components/copilot/chat/script/CodeDisplay.svelte index e2dfb8df32..9ea3f533d7 100644 --- a/frontend/src/lib/components/copilot/chat/script/CodeDisplay.svelte +++ b/frontend/src/lib/components/copilot/chat/script/CodeDisplay.svelte @@ -189,7 +189,7 @@ color="dark" size="xs2" on:click={() => { - applyCode(code ?? '') + applyCode?.(code ?? '') }} > Apply diff --git a/frontend/src/lib/components/search/GlobalSearchModal.svelte b/frontend/src/lib/components/search/GlobalSearchModal.svelte index 355a5fa385..083518f531 100644 --- a/frontend/src/lib/components/search/GlobalSearchModal.svelte +++ b/frontend/src/lib/components/search/GlobalSearchModal.svelte @@ -239,6 +239,7 @@ let defaultMenuItemLabels = defaultMenuItems.map((item) => item.label) let defaultMenuItemAndHiddenLabels = defaultMenuItemsWithHidden.map((item) => item.label) let switchModeItemLabels = switchModeItems.map((item) => item.label) + let askAiButton: AskAiButton | undefined function fuzzyFilter(filter: string, items: any[], itemsPlainText: string[]) { if (filter === '') { @@ -370,6 +371,9 @@ } } } + if ((itemMap[tab] ?? []).length === 0 && searchTerm.length > 0 && event.key === 'Enter') { + askAiButton?.onClick() + } } } @@ -617,6 +621,7 @@ {#if (itemMap[tab] ?? []).length === 0 && searchTerm.length > 0} {