mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 08:02:26 +00:00
fix: optimize public apps rendering
This commit is contained in:
+5
-5
@@ -1,4 +1,4 @@
|
||||
import { aiChatManager } from '$lib/components/copilot/chat/AIChatManager.svelte'
|
||||
import { triggerablesByAi } from '$lib/components/copilot/chat/sharedChatState.svelte'
|
||||
|
||||
export interface TriggerableByAIOptions {
|
||||
id?: string
|
||||
@@ -60,15 +60,15 @@ export function triggerableByAI(element: HTMLElement, options: TriggerableByAIOp
|
||||
|
||||
// register the triggerable
|
||||
const currentData = { description, onTrigger: handleTrigger }
|
||||
aiChatManager.triggerablesByAI[id] = currentData
|
||||
triggerablesByAi[id] = currentData
|
||||
}
|
||||
|
||||
function unregister() {
|
||||
if (isDisabled || !id) return
|
||||
|
||||
// unregister the triggerable
|
||||
if (aiChatManager.triggerablesByAI[id]) {
|
||||
delete aiChatManager.triggerablesByAI[id]
|
||||
if (triggerablesByAi[id]) {
|
||||
delete triggerablesByAi[id]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export function triggerableByAI(element: HTMLElement, options: TriggerableByAIOp
|
||||
|
||||
return {
|
||||
update(newOptions: TriggerableByAIOptions) {
|
||||
;({ id, description, callback, showAnimation = true } = newOptions)
|
||||
; ({ id, description, callback, showAnimation = true } = newOptions)
|
||||
register()
|
||||
},
|
||||
destroy() {
|
||||
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import ComponentInner from './apps/editor/component/ComponentInner.svelte'
|
||||
|
||||
// import AppPreview from './apps/editor/AppPreview.svelte'
|
||||
|
||||
// AppPreview
|
||||
ComponentInner
|
||||
</script>
|
||||
@@ -13,7 +13,8 @@
|
||||
Table2,
|
||||
Braces,
|
||||
Highlighter,
|
||||
ArrowDownFromLine
|
||||
ArrowDownFromLine,
|
||||
Loader2
|
||||
} from 'lucide-svelte'
|
||||
import Portal from '$lib/components/Portal.svelte'
|
||||
import DisplayResultControlBar from './DisplayResultControlBar.svelte'
|
||||
@@ -34,7 +35,6 @@
|
||||
import { convertJsonToCsv } from './table/tableUtils'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import HighlightTheme from './HighlightTheme.svelte'
|
||||
import PdfViewer from './display/PdfViewer.svelte'
|
||||
import type { DisplayResultUi } from './custom_ui'
|
||||
import { getContext, hasContext, createEventDispatcher, onDestroy } from 'svelte'
|
||||
import { toJsonStr } from '$lib/utils'
|
||||
@@ -634,10 +634,14 @@
|
||||
</div>
|
||||
{:else if !forceJson && resultKind === 'pdf'}
|
||||
<div class="h-96 mt-2 border">
|
||||
<PdfViewer
|
||||
allowFullscreen
|
||||
source="data:application/pdf;base64,{contentOrRootString(result.pdf)}"
|
||||
/>
|
||||
{#await import('$lib/components/display/PdfViewer.svelte')}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:then Module}
|
||||
<Module.default
|
||||
allowFullscreen
|
||||
source="data:application/pdf;base64,{contentOrRootString(result.pdf)}"
|
||||
/>
|
||||
{/await}
|
||||
</div>
|
||||
{:else if !forceJson && resultKind === 'plain'}<div class="h-full text-2xs"
|
||||
><pre class="whitespace-pre-wrap"
|
||||
@@ -809,18 +813,22 @@
|
||||
</div>
|
||||
{:else if result?.s3?.endsWith('.pdf')}
|
||||
<div class="h-96 mt-2 border">
|
||||
<PdfViewer
|
||||
allowFullscreen
|
||||
source="{`/api/w/${workspaceId}/${
|
||||
appPath
|
||||
? 'apps_u/download_s3_file/' + appPath
|
||||
: 'job_helpers/load_image_preview'
|
||||
}?${appPath ? 's3' : 'file_key'}=${encodeURIComponent(result.s3)}` +
|
||||
(result.storage ? `&storage=${result.storage}` : '')}{appPath &&
|
||||
result.presigned
|
||||
? `&${result.presigned}`
|
||||
: ''}"
|
||||
/>
|
||||
{#await import('$lib/components/display/PdfViewer.svelte')}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:then Module}
|
||||
<Module.default
|
||||
allowFullscreen
|
||||
source="{`/api/w/${workspaceId}/${
|
||||
appPath
|
||||
? 'apps_u/download_s3_file/' + appPath
|
||||
: 'job_helpers/load_image_preview'
|
||||
}?${appPath ? 's3' : 'file_key'}=${encodeURIComponent(result.s3)}` +
|
||||
(result.storage ? `&storage=${result.storage}` : '')}{appPath &&
|
||||
result.presigned
|
||||
? `&${result.presigned}`
|
||||
: ''}"
|
||||
/>
|
||||
{/await}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -893,12 +901,16 @@
|
||||
{/if}
|
||||
{:else if s3object?.s3?.endsWith('.pdf')}
|
||||
<div class="h-96 mt-2 border" data-interactive>
|
||||
<PdfViewer
|
||||
allowFullscreen
|
||||
source={`/api/w/${workspaceId}/job_helpers/load_image_preview?file_key=${encodeURIComponent(
|
||||
s3object.s3
|
||||
)}` + (s3object.storage ? `&storage=${s3object.storage}` : '')}
|
||||
/>
|
||||
{#await import('$lib/components/display/PdfViewer.svelte')}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:then Module}
|
||||
<Module.default
|
||||
allowFullscreen
|
||||
source={`/api/w/${workspaceId}/job_helpers/load_image_preview?file_key=${encodeURIComponent(
|
||||
s3object.s3
|
||||
)}` + (s3object.storage ? `&storage=${s3object.storage}` : '')}
|
||||
/>
|
||||
{/await}
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import ResolveOpen from '$lib/components/common/menu/ResolveOpen.svelte'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import { untrack } from 'svelte'
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { MenuItem } from '$lib/components/meltComponents'
|
||||
import MenuItem from '$lib/components/meltComponents/MenuItem.svelte'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import type { MenubarMenuElements } from '@melt-ui/svelte'
|
||||
|
||||
@@ -105,13 +105,8 @@
|
||||
vimMode
|
||||
} from '$lib/stores'
|
||||
|
||||
import {
|
||||
createHash as randomHash,
|
||||
editorConfig,
|
||||
langToExt,
|
||||
updateOptions,
|
||||
extToLang
|
||||
} from '$lib/editorUtils'
|
||||
import { editorConfig, updateOptions } from '$lib/editorUtils'
|
||||
import { createHash as randomHash } from '$lib/editorLangUtils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { type Preview, ResourceService, type ScriptLang, UserService } from '$lib/gen'
|
||||
import type { Text } from 'yjs'
|
||||
@@ -156,6 +151,7 @@
|
||||
import { formatResourceTypes } from './copilot/chat/script/core'
|
||||
import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte'
|
||||
import { editorPositionMap } from '$lib/utils'
|
||||
import { extToLang, langToExt } from '$lib/editorLangUtils'
|
||||
// import EditorTheme from './EditorTheme.svelte'
|
||||
|
||||
let divEl: HTMLDivElement | null = null
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
import { base } from '$lib/base'
|
||||
import FlowJobResult from './FlowJobResult.svelte'
|
||||
import FlowPreviewStatus from './preview/FlowPreviewStatus.svelte'
|
||||
import DisplayResult from './DisplayResult.svelte'
|
||||
|
||||
import { createEventDispatcher, getContext, tick } from 'svelte'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { Badge, Button, Skeleton, Tab } from './common'
|
||||
import DisplayResult from './DisplayResult.svelte'
|
||||
import Tabs from './common/tabs/Tabs.svelte'
|
||||
import { type DurationStatus, type FlowStatusViewerContext, type GraphModuleState } from './graph'
|
||||
import ModuleStatus from './ModuleStatus.svelte'
|
||||
|
||||
@@ -1,40 +1,52 @@
|
||||
<script lang="ts">
|
||||
import { debounce, displayDate, msToSec } from '$lib/utils'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { onDestroy, untrack } from 'svelte'
|
||||
import { getDbClockNow } from '$lib/forLater'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import TimelineBar from './TimelineBar.svelte'
|
||||
import type { Writable } from 'svelte/store'
|
||||
import WaitTimeWarning from './common/waitTimeWarning/WaitTimeWarning.svelte'
|
||||
|
||||
export let selfWaitTime: number | undefined = undefined
|
||||
export let aggregateWaitTime: number | undefined = undefined
|
||||
export let flowModules: string[]
|
||||
export let durationStatuses: Writable<
|
||||
Record<
|
||||
string,
|
||||
{
|
||||
byJob: Record<string, { created_at?: number; started_at?: number; duration_ms?: number }>
|
||||
iteration_from?: number
|
||||
iteration_total?: number
|
||||
}
|
||||
interface Props {
|
||||
selfWaitTime?: number | undefined
|
||||
aggregateWaitTime?: number | undefined
|
||||
flowModules: string[]
|
||||
durationStatuses: Writable<
|
||||
Record<
|
||||
string,
|
||||
{
|
||||
byJob: Record<string, { created_at?: number; started_at?: number; duration_ms?: number }>
|
||||
iteration_from?: number
|
||||
iteration_total?: number
|
||||
}
|
||||
>
|
||||
>
|
||||
>
|
||||
export let flowDone = false
|
||||
flowDone?: boolean
|
||||
}
|
||||
|
||||
let min: undefined | number = undefined
|
||||
let max: undefined | number = undefined
|
||||
let total: number | undefined = undefined
|
||||
let {
|
||||
selfWaitTime = undefined,
|
||||
aggregateWaitTime = undefined,
|
||||
flowModules,
|
||||
durationStatuses,
|
||||
flowDone = false
|
||||
}: Props = $props()
|
||||
|
||||
let min: undefined | number = $state(undefined)
|
||||
let max: undefined | number = $state(undefined)
|
||||
let total: number | undefined = $state(undefined)
|
||||
|
||||
let items:
|
||||
| Record<
|
||||
string,
|
||||
Array<{ created_at?: number; started_at?: number; duration_ms?: number; id: string }>
|
||||
>
|
||||
| undefined = undefined
|
||||
| undefined = $state(undefined)
|
||||
|
||||
let { debounced, clearDebounce } = debounce(() => computeItems($durationStatuses), 30)
|
||||
$: flowDone != undefined && $durationStatuses && debounced()
|
||||
$effect(() => {
|
||||
flowDone != undefined && $durationStatuses && untrack(() => debounced())
|
||||
})
|
||||
|
||||
export function reset() {
|
||||
min = undefined
|
||||
@@ -104,7 +116,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
let now = getDbClockNow().getTime()
|
||||
let now = $state(getDbClockNow().getTime())
|
||||
|
||||
let interval = setInterval((x) => {
|
||||
if (!max) {
|
||||
@@ -165,7 +177,7 @@
|
||||
<div class="w-full flex flex-row-reverse sticky top-0">
|
||||
<button
|
||||
class="!text-secondary underline mr-2 text-2xs text-right whitespace-nowrap"
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
let r = $durationStatuses[k]
|
||||
if (r.iteration_from) {
|
||||
r.iteration_from -= 20
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import { page } from '$app/stores'
|
||||
import { replaceState } from '$app/navigation'
|
||||
import JsonInputs from '$lib/components/JsonInputs.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import InputSelectedBadge from './schema/InputSelectedBadge.svelte'
|
||||
import { untrack } from 'svelte'
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
import TableSimple from './TableSimple.svelte'
|
||||
import ConfirmationModal from './common/confirmationModal/ConfirmationModal.svelte'
|
||||
import FileUploadModal from './common/fileUpload/FileUploadModal.svelte'
|
||||
import PdfViewer from './display/PdfViewer.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
let deletionModalOpen = $state(false)
|
||||
@@ -722,11 +721,15 @@
|
||||
</div>
|
||||
{:else if fileMetadata?.fileKey.endsWith('.pdf')}
|
||||
<div class="w-full h-[950px] border">
|
||||
<PdfViewer
|
||||
source={`/api/w/${$workspaceStore}/job_helpers/load_image_preview?file_key=${encodeURIComponent(
|
||||
fileMetadata.fileKey
|
||||
)}` + (storage ? `&storage=${storage}` : '')}
|
||||
/>
|
||||
{#await import('$lib/components/display/PdfViewer.svelte')}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:then Module}
|
||||
<Module.default
|
||||
source={`/api/w/${$workspaceStore}/job_helpers/load_image_preview?file_key=${encodeURIComponent(
|
||||
fileMetadata.fileKey
|
||||
)}` + (storage ? `&storage=${storage}` : '')}
|
||||
/>
|
||||
{/await}
|
||||
</div>
|
||||
{:else if filePreviewLoading}
|
||||
<div class="flex h-6 items-center text-tertiary mb-4">
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
import { getStringError } from './copilot/chat/utils'
|
||||
import type { ScriptOptions } from './copilot/chat/ContextManager.svelte'
|
||||
import { aiChatManager, AIMode } from './copilot/chat/AIChatManager.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
interface Props {
|
||||
// Exported
|
||||
@@ -418,10 +418,13 @@
|
||||
<svelte:window onkeydown={onKeyDown} />
|
||||
|
||||
<!-- Standalone triggerable registration for the script editor -->
|
||||
<div style="display: none" use:triggerableByAI={{
|
||||
id: "script-editor",
|
||||
description: "Component to edit a script"
|
||||
}}></div>
|
||||
<div
|
||||
style="display: none"
|
||||
use:triggerableByAI={{
|
||||
id: 'script-editor',
|
||||
description: 'Component to edit a script'
|
||||
}}
|
||||
></div>
|
||||
|
||||
<Modal title="Invite others" bind:open={showCollabPopup}>
|
||||
<div>Have others join by sharing the following url:</div>
|
||||
|
||||
@@ -57,7 +57,9 @@
|
||||
<script lang="ts">
|
||||
import { BROWSER } from 'esm-env'
|
||||
|
||||
import { createHash, editorConfig, langToExt, updateOptions } from '$lib/editorUtils'
|
||||
import { editorConfig, updateOptions } from '$lib/editorUtils'
|
||||
import { createHash } from '$lib/editorLangUtils'
|
||||
|
||||
// import {
|
||||
// editor as meditor,
|
||||
// KeyCode,
|
||||
@@ -80,6 +82,7 @@
|
||||
import { initVim } from './monaco_keybindings'
|
||||
import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte'
|
||||
import { editorPositionMap } from '$lib/utils'
|
||||
import { langToExt } from '$lib/editorLangUtils'
|
||||
// import { createConfiguredEditor } from 'vscode/monaco'
|
||||
// import type { IStandaloneCodeEditor } from 'vscode/vscode/vs/editor/standalone/browser/standaloneCodeEditor'
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { CornerDownLeft } from 'lucide-svelte'
|
||||
import { CornerDownLeft, Loader2 } from 'lucide-svelte'
|
||||
import Button from './common/button/Button.svelte'
|
||||
import Editor from './Editor.svelte'
|
||||
import type Editor from './Editor.svelte'
|
||||
import { runScriptAndPollResult } from './jobs/utils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
@@ -146,14 +146,18 @@
|
||||
|
||||
<Splitpanes>
|
||||
<Pane class="relative">
|
||||
<Editor
|
||||
bind:this={editor}
|
||||
bind:code
|
||||
lang="sql"
|
||||
scriptLang="mysql"
|
||||
class="w-full h-full"
|
||||
cmdEnterAction={run}
|
||||
/>
|
||||
{#await import('$lib/components/Editor.svelte')}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:then Module}
|
||||
<Module.default
|
||||
bind:this={editor}
|
||||
bind:code
|
||||
lang="sql"
|
||||
scriptLang="mysql"
|
||||
class="w-full h-full"
|
||||
cmdEnterAction={run}
|
||||
/>
|
||||
{/await}
|
||||
<Button
|
||||
wrapperClasses="absolute z-10 bottom-2 right-6"
|
||||
color={isRunning ? 'red' : undefined}
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
import {
|
||||
convertKind,
|
||||
createDocumentationString,
|
||||
createHash,
|
||||
displayPartsToString,
|
||||
editorConfig,
|
||||
updateOptions
|
||||
} from '$lib/editorUtils'
|
||||
import { createHash } from '$lib/editorLangUtils'
|
||||
|
||||
import libStdContent from '$lib/es6.d.ts.txt?raw'
|
||||
import { editor as meditor, Uri as mUri, languages, Range, KeyMod, KeyCode } from 'monaco-editor'
|
||||
import { createEventDispatcher, getContext, onDestroy, onMount } from 'svelte'
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import { AlertTriangle } from 'lucide-svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
export let options: {
|
||||
left?: string
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import InitializeComponent from '../helpers/InitializeComponent.svelte'
|
||||
import ResolveStyle from '../helpers/ResolveStyle.svelte'
|
||||
import PdfViewer from '$lib/components/display/PdfViewer.svelte'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
|
||||
interface Props {
|
||||
id: string
|
||||
@@ -46,17 +46,21 @@
|
||||
|
||||
{#if render}
|
||||
<div class="relative w-full h-full bg-gray-100 component-wrapper">
|
||||
<PdfViewer
|
||||
{source}
|
||||
{zoom}
|
||||
class={css?.container?.class}
|
||||
style={css?.container?.style}
|
||||
on:loading={() => {
|
||||
outputs.loading.set(true)
|
||||
}}
|
||||
on:loaded={() => {
|
||||
outputs.loading.set(false)
|
||||
}}
|
||||
/>
|
||||
{#await import('$lib/components/display/PdfViewer.svelte')}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:then Module}
|
||||
<Module.default
|
||||
{source}
|
||||
{zoom}
|
||||
class={css?.container?.class}
|
||||
style={css?.container?.style}
|
||||
on:loading={() => {
|
||||
outputs.loading.set(true)
|
||||
}}
|
||||
on:loaded={() => {
|
||||
outputs.loading.set(false)
|
||||
}}
|
||||
/>
|
||||
{/await}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
<script lang="ts">
|
||||
export let applyPageWidth = false
|
||||
export let stickToTop = false
|
||||
interface Props {
|
||||
applyPageWidth?: boolean
|
||||
stickToTop?: boolean
|
||||
class?: string | undefined
|
||||
left?: import('svelte').Snippet
|
||||
middle?: import('svelte').Snippet
|
||||
right?: import('svelte').Snippet
|
||||
}
|
||||
|
||||
$: wide = applyPageWidth ? 'max-w-7xl mx-auto px-4 sm:px-6 md:px-8' : ''
|
||||
let {
|
||||
applyPageWidth = false,
|
||||
stickToTop = false,
|
||||
class: clazz = '',
|
||||
left,
|
||||
middle,
|
||||
right
|
||||
}: Props = $props()
|
||||
let wide = $derived(applyPageWidth ? 'max-w-7xl mx-auto px-4 sm:px-6 md:px-8' : '')
|
||||
|
||||
let scrollY = 0
|
||||
let scrollY = $state(0)
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY />
|
||||
@@ -13,24 +27,24 @@
|
||||
class={'bg-surface py-3 ' +
|
||||
(stickToTop
|
||||
? 'lg:sticky lg:top-0 z-[500] border-b border-gray-200 border-opacity-0 duration-300 ' +
|
||||
(scrollY >= 30 ? 'border-opacity-100 ' : '')
|
||||
(scrollY >= 30 ? 'border-opacity-100 ' : '')
|
||||
: '') +
|
||||
($$props.class || '')}
|
||||
(clazz || '')}
|
||||
>
|
||||
<div class={'w-full flex flex-wrap justify-between items-center gap-4 ' + wide}>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
{#if $$slots.left}
|
||||
<slot name="left" />
|
||||
{#if left}
|
||||
{@render left?.()}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
{#if $$slots.middle}
|
||||
<slot name="middle" />
|
||||
{#if middle}
|
||||
{@render middle?.()}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2 lg:gap-4">
|
||||
{#if $$slots.right}
|
||||
<slot name="right" />
|
||||
{#if right}
|
||||
{@render right?.()}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import type { Placement } from '@floating-ui/core'
|
||||
import { conditionalMelt } from '$lib/utils'
|
||||
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
type MenuItem = {
|
||||
label: string
|
||||
|
||||
+8
-2
@@ -12,7 +12,7 @@
|
||||
} from '$lib/utils'
|
||||
import { page } from '$app/stores'
|
||||
import type { GetInitialAndModifiedValues } from './unsavedTypes'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
export let getInitialAndModifiedValues: GetInitialAndModifiedValues = undefined
|
||||
export let diffDrawer: DiffDrawer | undefined = undefined
|
||||
@@ -69,7 +69,13 @@
|
||||
</script>
|
||||
|
||||
{#if open}
|
||||
<div style="display: none" use:triggerableByAI={{id: "unsaved-changes-confirmation-modal", description: "Unsaved changes confirmation modal. Needs user confirmation to leave the page."}}></div>
|
||||
<div
|
||||
style="display: none"
|
||||
use:triggerableByAI={{
|
||||
id: 'unsaved-changes-confirmation-modal',
|
||||
description: 'Unsaved changes confirmation modal. Needs user confirmation to leave the page.'
|
||||
}}
|
||||
></div>
|
||||
{/if}
|
||||
|
||||
<ConfirmationModal
|
||||
|
||||
@@ -3,21 +3,41 @@
|
||||
import { BROWSER } from 'esm-env'
|
||||
import Disposable from './Disposable.svelte'
|
||||
import ConditionalPortal from './ConditionalPortal.svelte'
|
||||
import { aiChatManager } from '../../copilot/chat/AIChatManager.svelte'
|
||||
import { chatState } from '$lib/components/copilot/chat/sharedChatState.svelte'
|
||||
|
||||
export let open = false
|
||||
export let duration = 0.3
|
||||
export let placement = 'right'
|
||||
export let size = '600px'
|
||||
export let alwaysOpen = false
|
||||
export let shouldUsePortal: boolean = true
|
||||
export let offset: number = 0
|
||||
export let preventEscape = false
|
||||
export let disableChatOffset: boolean = false
|
||||
interface Props {
|
||||
open?: boolean
|
||||
duration?: number
|
||||
placement?: string
|
||||
size?: string
|
||||
alwaysOpen?: boolean
|
||||
shouldUsePortal?: boolean
|
||||
offset?: number
|
||||
preventEscape?: boolean
|
||||
disableChatOffset?: boolean
|
||||
class?: string | undefined
|
||||
positionClass?: string | undefined
|
||||
children?: import('svelte').Snippet<[any]>
|
||||
}
|
||||
|
||||
let disposable: Disposable | undefined = undefined
|
||||
let {
|
||||
open = $bindable(false),
|
||||
duration = 0.3,
|
||||
placement = 'right',
|
||||
size = '600px',
|
||||
alwaysOpen = false,
|
||||
shouldUsePortal = true,
|
||||
offset = 0,
|
||||
preventEscape = false,
|
||||
disableChatOffset = false,
|
||||
class: clazz = '',
|
||||
positionClass = undefined,
|
||||
children
|
||||
}: Props = $props()
|
||||
|
||||
$: durationMs = duration * 1000
|
||||
let disposable: Disposable | undefined = $state(undefined)
|
||||
|
||||
let durationMs = $derived(duration * 1000)
|
||||
|
||||
export function toggleDrawer() {
|
||||
disposable?.toggleDrawer()
|
||||
@@ -42,7 +62,7 @@
|
||||
let mounted = false
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: style = `--duration: ${duration}s; --size: ${size};`
|
||||
let style = $derived(`--duration: ${duration}s; --size: ${size};`)
|
||||
|
||||
function scrollLock(open: boolean) {
|
||||
if (BROWSER) {
|
||||
@@ -54,45 +74,55 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: scrollLock(open)
|
||||
$effect(() => {
|
||||
scrollLock(open)
|
||||
})
|
||||
|
||||
$: open ? openDrawer() : closeDrawer()
|
||||
$effect(() => {
|
||||
open ? openDrawer() : closeDrawer()
|
||||
})
|
||||
|
||||
let timeout = true
|
||||
$: !open ? setTimeout(() => (timeout = true), durationMs) : (timeout = false)
|
||||
let timeout = $state(true)
|
||||
$effect(() => {
|
||||
!open ? setTimeout(() => (timeout = true), durationMs) : (timeout = false)
|
||||
})
|
||||
onMount(() => {
|
||||
mounted = true
|
||||
})
|
||||
|
||||
const children_render = $derived(children)
|
||||
const aiChatOpen = $derived(chatState.size > 0)
|
||||
</script>
|
||||
|
||||
<ConditionalPortal condition={shouldUsePortal}>
|
||||
<Disposable
|
||||
initialOffset={offset}
|
||||
let:handleClickAway
|
||||
let:zIndex
|
||||
bind:open
|
||||
bind:this={disposable}
|
||||
on:open
|
||||
on:close
|
||||
{preventEscape}
|
||||
>
|
||||
<aside
|
||||
class="drawer windmill-app windmill-drawer {$$props.class ?? ''} {$$props.positionClass ??
|
||||
''} {aiChatManager.open ? 'respect-global-chat' : ''}"
|
||||
class:open
|
||||
class:close={!open && timeout}
|
||||
class:global-chat-open={aiChatManager.open}
|
||||
style={`${style}; --zIndex: ${zIndex}; --adjusted-offset: calc(${aiChatManager.open && placement === 'right' && !disableChatOffset ? aiChatManager.size : 0}% + 4px)`}
|
||||
>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="overlay {$$props.positionClass ?? ''}" on:click={handleClickAway}></div>
|
||||
<div class="panel {placement} {$$props.positionClass}" class:size>
|
||||
{#if open || !timeout || alwaysOpen}
|
||||
<slot {open} />
|
||||
{/if}
|
||||
</div>
|
||||
</aside>
|
||||
{#snippet children({ handleClickAway, zIndex })}
|
||||
<aside
|
||||
class="drawer windmill-app windmill-drawer {clazz ?? ''} {positionClass ?? ''} {aiChatOpen
|
||||
? 'respect-global-chat'
|
||||
: ''}"
|
||||
class:open
|
||||
class:close={!open && timeout}
|
||||
class:global-chat-open={aiChatOpen}
|
||||
style={`${style}; --zIndex: ${zIndex}; --adjusted-offset: calc(${aiChatOpen && placement === 'right' && !disableChatOffset ? chatState.size : 0}% + 4px)`}
|
||||
>
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="overlay {positionClass ?? ''}" onclick={handleClickAway}></div>
|
||||
<div class="panel {placement} {positionClass}" class:size>
|
||||
{#if open || !timeout || alwaysOpen}
|
||||
{@render children_render?.({ open })}
|
||||
{/if}
|
||||
</div>
|
||||
</aside>
|
||||
{/snippet}
|
||||
</Disposable>
|
||||
</ConditionalPortal>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { classNames } from '$lib/utils'
|
||||
import CloseButton from '../CloseButton.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { BellOff } from 'lucide-svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { TabsContext } from '$lib/components/apps/editor/settingsPanel/inputEditor/tabs.svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher<{ onpointerdown: any }>()
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import { yamlStringifyExceptKeys } from './utils'
|
||||
import type { ChatCompletionMessageParam } from 'openai/resources/index.mjs'
|
||||
import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
type PromptConfig = {
|
||||
system: string
|
||||
@@ -234,72 +234,70 @@ Generate a description for the flow below:
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="absolute left-[0.5rem] {elementType === 'textarea'
|
||||
? 'top-[1.3rem]'
|
||||
: 'top-[0.3rem]'} flex flex-row gap-2 items-start pointer-events-none"
|
||||
>
|
||||
{#if active}
|
||||
<span
|
||||
class={twMerge(
|
||||
'absolute text-xs bg-violet-100 text-violet-800 dark:bg-gray-700 dark:text-violet-400 px-1 py-0.5 rounded-md flex flex-row items-center justify-center gap-2 transition-all shrink-0',
|
||||
!loading && generatedContent.length > 0
|
||||
? 'bg-green-100 text-green-800 dark:text-green-400 dark:bg-green-700'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
<span
|
||||
class="px-0.5 py-0.5 rounded-md text-2xs text-bold flex flex-row items-center gap-1"
|
||||
>
|
||||
{#if loading}
|
||||
ESC
|
||||
{:else}
|
||||
TAB
|
||||
{/if}
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin" size={12} />
|
||||
{:else if generatedContent}
|
||||
<Check size={12} />
|
||||
{:else}
|
||||
<Wand2 size={12} />
|
||||
{/if}
|
||||
</span>
|
||||
<div
|
||||
class="absolute left-[0.5rem] {elementType === 'textarea'
|
||||
? 'top-[1.3rem]'
|
||||
: 'top-[0.3rem]'} flex flex-row gap-2 items-start pointer-events-none"
|
||||
>
|
||||
{#if active}
|
||||
<span
|
||||
class={twMerge(
|
||||
'absolute text-xs bg-violet-100 text-violet-800 dark:bg-gray-700 dark:text-violet-400 px-1 py-0.5 rounded-md flex flex-row items-center justify-center gap-2 transition-all shrink-0',
|
||||
!loading && generatedContent.length > 0
|
||||
? 'bg-green-100 text-green-800 dark:text-green-400 dark:bg-green-700'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
<span class="px-0.5 py-0.5 rounded-md text-2xs text-bold flex flex-row items-center gap-1">
|
||||
{#if loading}
|
||||
ESC
|
||||
{:else}
|
||||
TAB
|
||||
{/if}
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin" size={12} />
|
||||
{:else if generatedContent}
|
||||
<Check size={12} />
|
||||
{:else}
|
||||
<Wand2 size={12} />
|
||||
{/if}
|
||||
</span>
|
||||
<div
|
||||
bind:clientHeight={genHeight}
|
||||
class={twMerge(
|
||||
'text-sm leading-6 indent-[3.5rem] text-gray-500 dark:text-gray-400 pr-1',
|
||||
elementType === 'input' ? 'text-ellipsis overflow-hidden whitespace-nowrap' : ''
|
||||
)}
|
||||
style={elementType === 'input' ? `max-width: calc(${width}px - 0.5rem)` : ''}
|
||||
>
|
||||
{generatedContent}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if elementType === 'textarea'}
|
||||
<div>
|
||||
<div class="flex flex-row-reverse !text-3xs text-tertiary -mt-4">GH Markdown</div>
|
||||
<textarea
|
||||
bind:this={el}
|
||||
bind:value={content}
|
||||
use:autosize
|
||||
{...elementProps}
|
||||
placeholder={!active ? elementProps.placeholder : ''}
|
||||
class={active ? '!indent-[3.5rem]' : ''}
|
||||
on:focus={() => (focused = true)}
|
||||
on:blur={() => (focused = false)}
|
||||
></textarea>
|
||||
</span>
|
||||
<div
|
||||
bind:clientHeight={genHeight}
|
||||
class={twMerge(
|
||||
'text-sm leading-6 indent-[3.5rem] text-gray-500 dark:text-gray-400 pr-1',
|
||||
elementType === 'input' ? 'text-ellipsis overflow-hidden whitespace-nowrap' : ''
|
||||
)}
|
||||
style={elementType === 'input' ? `max-width: calc(${width}px - 0.5rem)` : ''}
|
||||
>
|
||||
{generatedContent}
|
||||
</div>
|
||||
{:else}
|
||||
<input
|
||||
{/if}
|
||||
</div>
|
||||
{#if elementType === 'textarea'}
|
||||
<div>
|
||||
<div class="flex flex-row-reverse !text-3xs text-tertiary -mt-4">GH Markdown</div>
|
||||
<textarea
|
||||
bind:this={el}
|
||||
bind:value={content}
|
||||
use:autosize
|
||||
{...elementProps}
|
||||
placeholder={!active ? elementProps.placeholder : ''}
|
||||
class={active ? '!indent-[3.5rem]' : ''}
|
||||
on:focus={() => (focused = true)}
|
||||
on:blur={() => (focused = false)}
|
||||
/>
|
||||
{/if}
|
||||
></textarea>
|
||||
</div>
|
||||
{:else}
|
||||
<input
|
||||
bind:this={el}
|
||||
bind:value={content}
|
||||
placeholder={!active ? elementProps.placeholder : ''}
|
||||
class={active ? '!indent-[3.5rem]' : ''}
|
||||
on:focus={() => (focused = true)}
|
||||
on:blur={() => (focused = false)}
|
||||
/>
|
||||
{/if}
|
||||
<!-- <slot {updateFocus} {active} {generatedContent} classNames={active ? '!indent-[8.8rem]' : ''} /> -->
|
||||
</div>
|
||||
|
||||
@@ -30,14 +30,8 @@ import type { CurrentEditor, ExtendedOpenFlow } from '$lib/components/flows/type
|
||||
import { untrack } from 'svelte'
|
||||
import type { DBSchemas } from '$lib/stores'
|
||||
import { askTools, prepareAskSystemMessage } from './ask/core'
|
||||
import { chatState, DEFAULT_SIZE, triggerablesByAi } from './sharedChatState.svelte'
|
||||
|
||||
type TriggerablesMap = Record<
|
||||
string,
|
||||
{
|
||||
description: string
|
||||
onTrigger: ((value?: string) => void) | undefined
|
||||
}
|
||||
>
|
||||
|
||||
export enum AIMode {
|
||||
SCRIPT = 'script',
|
||||
@@ -47,7 +41,6 @@ export enum AIMode {
|
||||
}
|
||||
|
||||
class AIChatManager {
|
||||
DEFAULT_SIZE = 22
|
||||
NAVIGATION_SYSTEM_PROMPT = `
|
||||
CONSIDERATIONS:
|
||||
- You are provided with a tool to switch to navigation mode, only use it when you are sure that the user is asking you to navigate the application, help them find something or fetch data from the API. Do not use it otherwise.
|
||||
@@ -57,8 +50,7 @@ class AIChatManager {
|
||||
abortController: AbortController | undefined = undefined
|
||||
|
||||
mode = $state<AIMode>(AIMode.NAVIGATOR)
|
||||
size = $state<number>(localStorage.getItem('ai-chat-open') === 'true' ? this.DEFAULT_SIZE : 0)
|
||||
readonly isOpen = $derived(this.size > 0)
|
||||
readonly isOpen = $derived(chatState.size > 0)
|
||||
savedSize = $state<number>(0)
|
||||
instructions = $state<string>('')
|
||||
pendingPrompt = $state<string>('')
|
||||
@@ -74,7 +66,6 @@ class AIChatManager {
|
||||
tools = $state<Tool<any>[]>([])
|
||||
helpers = $state<any | undefined>(undefined)
|
||||
|
||||
triggerablesByAI = $state<TriggerablesMap>({})
|
||||
scriptEditorOptions = $state<ScriptOptions | undefined>(undefined)
|
||||
scriptEditorApplyCode = $state<((code: string) => void) | undefined>(undefined)
|
||||
scriptEditorShowDiffMode = $state<(() => void) | undefined>(undefined)
|
||||
@@ -89,7 +80,7 @@ class AIChatManager {
|
||||
ask: true
|
||||
})
|
||||
|
||||
open = $derived(this.size > 0)
|
||||
open = $derived(chatState.size > 0)
|
||||
|
||||
async loadApiTools() {
|
||||
if (this.apiTools.length === 0) {
|
||||
@@ -129,7 +120,7 @@ class AIChatManager {
|
||||
getLang: () => lang
|
||||
}
|
||||
if (options?.closeScriptSettings) {
|
||||
const closeComponent = this.triggerablesByAI['close-script-builder-settings']
|
||||
const closeComponent = triggerablesByAi['close-script-builder-settings']
|
||||
if (closeComponent) {
|
||||
closeComponent.onTrigger?.()
|
||||
}
|
||||
@@ -188,22 +179,22 @@ class AIChatManager {
|
||||
}
|
||||
|
||||
openChat = () => {
|
||||
this.size = this.savedSize > 0 ? this.savedSize : this.DEFAULT_SIZE
|
||||
chatState.size = this.savedSize > 0 ? this.savedSize : DEFAULT_SIZE
|
||||
localStorage.setItem('ai-chat-open', 'true')
|
||||
}
|
||||
|
||||
closeChat = () => {
|
||||
this.savedSize = this.size
|
||||
this.size = 0
|
||||
this.savedSize = chatState.size
|
||||
chatState.size = 0
|
||||
localStorage.setItem('ai-chat-open', 'false')
|
||||
}
|
||||
|
||||
toggleOpen = () => {
|
||||
if (this.size > 0) {
|
||||
this.savedSize = this.size
|
||||
if (chatState.size > 0) {
|
||||
this.savedSize = chatState.size
|
||||
}
|
||||
this.size = this.size === 0 ? (this.savedSize > 0 ? this.savedSize : this.DEFAULT_SIZE) : 0
|
||||
localStorage.setItem('ai-chat-open', this.size === 0 ? 'false' : 'true')
|
||||
chatState.size = chatState.size === 0 ? (this.savedSize > 0 ? this.savedSize : DEFAULT_SIZE) : 0
|
||||
localStorage.setItem('ai-chat-open', chatState.size === 0 ? 'false' : 'true')
|
||||
}
|
||||
|
||||
askAi = (
|
||||
@@ -432,8 +423,8 @@ class AIChatManager {
|
||||
: this.mode === AIMode.NAVIGATOR
|
||||
? prepareNavigatorUserMessage(oldInstructions)
|
||||
: await prepareScriptUserMessage(oldInstructions, lang, oldSelectedContext, {
|
||||
isPreprocessor
|
||||
})
|
||||
isPreprocessor
|
||||
})
|
||||
|
||||
this.messages.push(userMessage)
|
||||
await this.historyManager.saveChat(this.displayMessages, this.messages)
|
||||
@@ -503,7 +494,7 @@ class AIChatManager {
|
||||
|
||||
restartLastGeneration = (displayMessageIndex: number) => {
|
||||
const userMessage = this.displayMessages[displayMessageIndex]
|
||||
|
||||
|
||||
if (!userMessage || userMessage.role !== 'user') {
|
||||
throw new Error('No user message found at the specified index')
|
||||
}
|
||||
@@ -657,15 +648,15 @@ class AIChatManager {
|
||||
const editorRelated =
|
||||
currentEditor && currentEditor.type === 'script' && currentEditor.stepId === module.id
|
||||
? {
|
||||
diffMode: currentEditor.diffMode,
|
||||
lastDeployedCode: currentEditor.lastDeployedCode,
|
||||
lastSavedCode: undefined
|
||||
}
|
||||
diffMode: currentEditor.diffMode,
|
||||
lastDeployedCode: currentEditor.lastDeployedCode,
|
||||
lastSavedCode: undefined
|
||||
}
|
||||
: {
|
||||
diffMode: false,
|
||||
lastDeployedCode: undefined,
|
||||
lastSavedCode: undefined
|
||||
}
|
||||
diffMode: false,
|
||||
lastDeployedCode: undefined,
|
||||
lastSavedCode: undefined
|
||||
}
|
||||
|
||||
return {
|
||||
args: moduleState?.previewArgs ?? {},
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { langToExt } from '$lib/editorUtils'
|
||||
import { ResourceService, type ListResourceResponse, type ScriptLang } from '$lib/gen'
|
||||
import { scriptLangToEditorLang } from '$lib/scripts'
|
||||
import { SQLSchemaLanguages, type DBSchemas } from '$lib/stores'
|
||||
@@ -6,6 +5,7 @@ import { diffLines } from 'diff'
|
||||
import type { ContextElement } from './context'
|
||||
|
||||
import type { DisplayMessage } from './shared'
|
||||
import { langToExt } from '$lib/editorLangUtils'
|
||||
|
||||
export interface ScriptOptions {
|
||||
lang: ScriptLang | 'bunnative'
|
||||
@@ -160,15 +160,15 @@ export default class ContextManager {
|
||||
.map((c) =>
|
||||
c.type === 'code'
|
||||
? {
|
||||
...c,
|
||||
content: scriptOptions.code,
|
||||
title: this.getContextCodePath(scriptOptions)
|
||||
}
|
||||
...c,
|
||||
content: scriptOptions.code,
|
||||
title: this.getContextCodePath(scriptOptions)
|
||||
}
|
||||
: c.type === 'db' && dbSchemas[c.title]
|
||||
? {
|
||||
...c,
|
||||
schema: dbSchemas[c.title]
|
||||
}
|
||||
...c,
|
||||
schema: dbSchemas[c.title]
|
||||
}
|
||||
: c
|
||||
)
|
||||
|
||||
@@ -234,14 +234,14 @@ export default class ContextManager {
|
||||
...(options.withCode === false ? [] : [codeContext]),
|
||||
...(options.withDiff
|
||||
? [
|
||||
{
|
||||
type: 'diff' as const,
|
||||
title: 'diff_with_last_deployed_version',
|
||||
content: this.scriptOptions.lastDeployedCode ?? '',
|
||||
diff: diffLines(this.scriptOptions.lastDeployedCode ?? '', this.scriptOptions.code),
|
||||
lang: this.scriptOptions.lang
|
||||
}
|
||||
]
|
||||
{
|
||||
type: 'diff' as const,
|
||||
title: 'diff_with_last_deployed_version',
|
||||
content: this.scriptOptions.lastDeployedCode ?? '',
|
||||
diff: diffLines(this.scriptOptions.lastDeployedCode ?? '', this.scriptOptions.code),
|
||||
lang: this.scriptOptions.lang
|
||||
}
|
||||
]
|
||||
: [])
|
||||
]
|
||||
}
|
||||
@@ -268,14 +268,14 @@ export default class ContextManager {
|
||||
contextElements:
|
||||
m.role !== 'tool' && m.contextElements
|
||||
? m.contextElements.map((c) =>
|
||||
c.type === 'db'
|
||||
? {
|
||||
type: 'db',
|
||||
title: c.title,
|
||||
schema: dbSchemas[c.title]
|
||||
}
|
||||
: c
|
||||
)
|
||||
c.type === 'db'
|
||||
? {
|
||||
type: 'db',
|
||||
title: c.title,
|
||||
schema: dbSchemas[c.title]
|
||||
}
|
||||
: c
|
||||
)
|
||||
: undefined
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { openDB, type DBSchema as IDBSchema, type IDBPDatabase } from 'idb'
|
||||
import type { DisplayMessage } from './shared'
|
||||
import { createLongHash } from '$lib/editorUtils'
|
||||
import { createLongHash } from '$lib/editorLangUtils'
|
||||
import type { ChatCompletionMessageParam } from 'openai/resources/index.mjs'
|
||||
interface ChatSchema extends IDBSchema {
|
||||
chats: {
|
||||
|
||||
@@ -3,19 +3,6 @@
|
||||
if (!id) return undefined
|
||||
return aiChatManager.flowAiChatHelpers?.getModuleAction(id)
|
||||
}
|
||||
|
||||
export function aiModuleActionToBgColor(action: AIModuleAction | undefined) {
|
||||
switch (action) {
|
||||
case 'modified':
|
||||
return '!bg-orange-200 dark:!bg-orange-800'
|
||||
case 'added':
|
||||
return '!bg-green-200 dark:!bg-green-800'
|
||||
case 'removed':
|
||||
return '!bg-red-200/50 dark:!bg-red-800/50'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { dfs } from '$lib/components/flows/previousResults'
|
||||
import type { OpenFlow } from '$lib/gen'
|
||||
import type { AIModuleAction } from './core'
|
||||
|
||||
export function getIndexInNestedModules(flow: OpenFlow, id: string) {
|
||||
const accessingModules = dfs(id, flow, true).reverse()
|
||||
@@ -80,3 +81,18 @@ export function getNestedModules(flow: OpenFlow, id: string, branchIndex?: numbe
|
||||
throw new Error('Module is not a loop or branch')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function aiModuleActionToBgColor(action: AIModuleAction | undefined) {
|
||||
switch (action) {
|
||||
case 'modified':
|
||||
return '!bg-orange-200 dark:!bg-orange-800'
|
||||
case 'added':
|
||||
return '!bg-green-200 dark:!bg-green-800'
|
||||
case 'removed':
|
||||
return '!bg-red-200/50 dark:!bg-red-800/50'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,10 @@ import type {
|
||||
ChatCompletionUserMessageParam
|
||||
} from 'openai/resources/index.mjs'
|
||||
import type { Tool } from '../shared'
|
||||
import { aiChatManager } from '../AIChatManager.svelte'
|
||||
import { ResourceService } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { get } from 'svelte/store'
|
||||
import { triggerablesByAi } from '../sharedChatState.svelte'
|
||||
|
||||
export const CHAT_SYSTEM_PROMPT = `
|
||||
You are Windmill's intelligent assistant, designed to help users navigate the application and answer questions about its functionality. It is your only purpose to help the user in the context of the windmill application.
|
||||
@@ -160,8 +160,8 @@ const GET_AVAILABLE_RESOURCES_TOOL: ChatCompletionTool = {
|
||||
|
||||
function getTriggerableComponents(): string {
|
||||
try {
|
||||
// Get components registered in the triggerablesByAI store
|
||||
const registeredComponents = aiChatManager.triggerablesByAI
|
||||
// Get components registered in the triggerablesByAi store
|
||||
const registeredComponents = triggerablesByAi
|
||||
let result = 'TRIGGERABLE_COMPONENTS:\n'
|
||||
|
||||
// If there are no components registered, return a message
|
||||
@@ -218,7 +218,7 @@ function triggerComponent(args: { id: string; value: string }): string {
|
||||
return 'Trigger command requires an id parameter'
|
||||
}
|
||||
|
||||
const component = aiChatManager.triggerablesByAI[id]
|
||||
const component = triggerablesByAi[id]
|
||||
|
||||
if (!component) {
|
||||
return `No triggerable component found with id: ${id}`
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export const triggerablesByAi = $state<TriggerablesMap>({})
|
||||
|
||||
export type TriggerablesMap = Record<
|
||||
string,
|
||||
{
|
||||
description: string
|
||||
onTrigger: ((value?: string) => void) | undefined
|
||||
}
|
||||
>
|
||||
export const DEFAULT_SIZE = 22
|
||||
|
||||
type ChatState = {
|
||||
size: number
|
||||
}
|
||||
export const chatState = $state<ChatState>({
|
||||
size: localStorage.getItem('ai-chat-open') === 'true' ? DEFAULT_SIZE : 0,
|
||||
})
|
||||
@@ -1,49 +1,49 @@
|
||||
import { createLongHash } from '$lib/editorUtils'
|
||||
import { createLongHash } from '$lib/editorLangUtils'
|
||||
import { type editor as meditor } from 'monaco-editor'
|
||||
|
||||
export type VisualChange =
|
||||
| {
|
||||
type: 'added_inline'
|
||||
position: {
|
||||
line: number
|
||||
column: number
|
||||
}
|
||||
value: string
|
||||
options?: {
|
||||
greenHighlight?: boolean
|
||||
}
|
||||
}
|
||||
type: 'added_inline'
|
||||
position: {
|
||||
line: number
|
||||
column: number
|
||||
}
|
||||
value: string
|
||||
options?: {
|
||||
greenHighlight?: boolean
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: 'added_block'
|
||||
position: {
|
||||
afterLineNumber: number
|
||||
type: 'added_block'
|
||||
position: {
|
||||
afterLineNumber: number
|
||||
}
|
||||
value: string
|
||||
options?: {
|
||||
greenHighlight?: boolean
|
||||
review?: {
|
||||
acceptFn: () => void
|
||||
rejectFn: () => void
|
||||
}
|
||||
value: string
|
||||
options?: {
|
||||
greenHighlight?: boolean
|
||||
review?: {
|
||||
acceptFn: () => void
|
||||
rejectFn: () => void
|
||||
}
|
||||
extraChanges?: VisualChange[]
|
||||
}
|
||||
}
|
||||
extraChanges?: VisualChange[]
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: 'deleted'
|
||||
range: {
|
||||
startLine: number
|
||||
startColumn: number
|
||||
endLine: number
|
||||
endColumn: number
|
||||
type: 'deleted'
|
||||
range: {
|
||||
startLine: number
|
||||
startColumn: number
|
||||
endLine: number
|
||||
endColumn: number
|
||||
}
|
||||
options?: {
|
||||
isWholeLine?: boolean
|
||||
review?: {
|
||||
acceptFn: () => void
|
||||
rejectFn: () => void
|
||||
}
|
||||
options?: {
|
||||
isWholeLine?: boolean
|
||||
review?: {
|
||||
acceptFn: () => void
|
||||
rejectFn: () => void
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyMonacoStyles(targetEl: HTMLElement, greenHighlight?: boolean) {
|
||||
const computedStyles = window.getComputedStyle(
|
||||
@@ -81,9 +81,8 @@ function addInlineGhostText(change: Extract<VisualChange, { type: 'added_inline'
|
||||
endColumn: change.position.column + change.value.length
|
||||
},
|
||||
options: {
|
||||
beforeContentClassName: `editor-ghost-text editor-ghost-text-content-${cssId} ${
|
||||
change.options?.greenHighlight ? 'editor-ghost-text-green' : ''
|
||||
}`
|
||||
beforeContentClassName: `editor-ghost-text editor-ghost-text-content-${cssId} ${change.options?.greenHighlight ? 'editor-ghost-text-green' : ''
|
||||
}`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import type { Trigger } from '$lib/components/triggers/utils'
|
||||
import FlowAIChat from '../copilot/chat/flow/FlowAIChat.svelte'
|
||||
import { aiChatManager, AIMode } from '../copilot/chat/AIChatManager.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
const { flowStore } = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { refreshStateStore } from '$lib/svelte5Utils.svelte'
|
||||
import ModuleAcceptReject, {
|
||||
aiModuleActionToBgColor,
|
||||
getAiModuleAction
|
||||
} from '$lib/components/copilot/chat/flow/ModuleAcceptReject.svelte'
|
||||
import { aiModuleActionToBgColor } from '$lib/components/copilot/chat/flow/utils'
|
||||
let {
|
||||
small,
|
||||
clazz
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
import OutputPickerInner from '$lib/components/flows/propPicker/OutputPickerInner.svelte'
|
||||
import type { FlowState } from '$lib/components/flows/flowState'
|
||||
import ModuleAcceptReject, {
|
||||
aiModuleActionToBgColor,
|
||||
getAiModuleAction
|
||||
} from '$lib/components/copilot/chat/flow/ModuleAcceptReject.svelte'
|
||||
import { Button } from '$lib/components/common'
|
||||
import ModuleTest from '$lib/components/ModuleTest.svelte'
|
||||
import { getStepHistoryLoaderContext } from '$lib/components/stepHistoryLoader.svelte'
|
||||
import { aiModuleActionToBgColor } from '$lib/components/copilot/chat/flow/utils'
|
||||
|
||||
interface Props {
|
||||
selected?: boolean
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
import { fade } from 'svelte/transition'
|
||||
import { Database, Square } from 'lucide-svelte'
|
||||
import ModuleAcceptReject, {
|
||||
aiModuleActionToBgColor,
|
||||
getAiModuleAction
|
||||
} from '$lib/components/copilot/chat/flow/ModuleAcceptReject.svelte'
|
||||
import { aiModuleActionToBgColor } from '$lib/components/copilot/chat/flow/utils'
|
||||
|
||||
interface Props {
|
||||
label?: string | undefined
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
import TreeViewRoot from './TreeViewRoot.svelte'
|
||||
import Popover from '$lib/components/meltComponents/Popover.svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
interface Props {
|
||||
filter?: string
|
||||
subtab?: 'flow' | 'script' | 'app'
|
||||
@@ -351,217 +351,223 @@
|
||||
</Drawer>
|
||||
|
||||
<CenteredPage>
|
||||
<div class="flex flex-wrap gap-2 items-center justify-between w-full mt-2" use:triggerableByAI={{id: "home-items-list", description: "Lists of scripts, flows, and apps"}}>
|
||||
<div class="flex justify-start">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={itemKind}
|
||||
on:selected={() => {
|
||||
if (itemKind != 'all') {
|
||||
subtab = itemKind
|
||||
}
|
||||
setQuery($page.url, 'kind', itemKind)
|
||||
}}
|
||||
class="h-10"
|
||||
>
|
||||
{#snippet children({ item })}
|
||||
<ToggleButton value="all" label="All" class="text-sm px-4 py-2" {item} />
|
||||
<div
|
||||
class="flex flex-wrap gap-2 items-center justify-between w-full mt-2"
|
||||
use:triggerableByAI={{
|
||||
id: 'home-items-list',
|
||||
description: 'Lists of scripts, flows, and apps'
|
||||
}}
|
||||
>
|
||||
<div class="flex justify-start">
|
||||
<ToggleButtonGroup
|
||||
bind:selected={itemKind}
|
||||
on:selected={() => {
|
||||
if (itemKind != 'all') {
|
||||
subtab = itemKind
|
||||
}
|
||||
setQuery($page.url, 'kind', itemKind)
|
||||
}}
|
||||
class="h-10"
|
||||
>
|
||||
{#snippet children({ item })}
|
||||
<ToggleButton value="all" label="All" class="text-sm px-4 py-2" {item} />
|
||||
<ToggleButton
|
||||
value="script"
|
||||
icon={Code2}
|
||||
label="Scripts"
|
||||
class="text-sm px-4 py-2"
|
||||
{item}
|
||||
/>
|
||||
{#if HOME_SEARCH_SHOW_FLOW}
|
||||
<ToggleButton
|
||||
value="script"
|
||||
icon={Code2}
|
||||
label="Scripts"
|
||||
value="flow"
|
||||
label="Flows"
|
||||
icon={FlowIcon}
|
||||
class="text-sm px-4 py-2"
|
||||
selectedColor="#14b8a6"
|
||||
{item}
|
||||
/>
|
||||
{#if HOME_SEARCH_SHOW_FLOW}
|
||||
<ToggleButton
|
||||
value="flow"
|
||||
label="Flows"
|
||||
icon={FlowIcon}
|
||||
class="text-sm px-4 py-2"
|
||||
selectedColor="#14b8a6"
|
||||
{item}
|
||||
/>
|
||||
{/if}
|
||||
<ToggleButton
|
||||
value="app"
|
||||
label="Apps"
|
||||
icon={LayoutDashboard}
|
||||
class="text-sm px-4 py-2"
|
||||
selectedColor="#fb923c"
|
||||
{item}
|
||||
{/if}
|
||||
<ToggleButton
|
||||
value="app"
|
||||
label="Apps"
|
||||
icon={LayoutDashboard}
|
||||
class="text-sm px-4 py-2"
|
||||
selectedColor="#fb923c"
|
||||
{item}
|
||||
/>
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
<div class="relative text-tertiary grow min-w-[100px]">
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
autofocus
|
||||
placeholder={HOME_SEARCH_PLACEHOLDER}
|
||||
bind:value={filter}
|
||||
class="bg-surface !h-10 !px-4 !pr-10 !rounded-lg text-sm focus:outline-none"
|
||||
/>
|
||||
<button aria-label="Search" type="submit" class="absolute right-0 top-0 mt-3 mr-4">
|
||||
<svg
|
||||
class="h-4 w-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 56.966 56.966"
|
||||
style="enable-background:new 0 0 56.966 56.966;"
|
||||
xml:space="preserve"
|
||||
width="512px"
|
||||
height="512px"
|
||||
>
|
||||
<path
|
||||
d="M55.146,51.887L41.588,37.786c3.486-4.144,5.396-9.358,5.396-14.786c0-12.682-10.318-23-23-23s-23,10.318-23,23 s10.318,23,23,23c4.761,0,9.298-1.436,13.177-4.162l13.661,14.208c0.571,0.593,1.339,0.92,2.162,0.92 c0.779,0,1.518-0.297,2.079-0.837C56.255,54.982,56.293,53.08,55.146,51.887z M23.984,6c9.374,0,17,7.626,17,17s-7.626,17-17,17 s-17-7.626-17-17S14.61,6,23.984,6z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<Button
|
||||
on:click={() => openSearchWithPrefilledText('#')}
|
||||
variant="border"
|
||||
size="sm"
|
||||
spacingSize="lg"
|
||||
wrapperClasses="h-10"
|
||||
color="light"
|
||||
endIcon={{
|
||||
icon: SearchCode
|
||||
}}
|
||||
>
|
||||
Content
|
||||
</Button>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<ListFilters
|
||||
syncQuery
|
||||
bind:selectedFilter={ownerFilter}
|
||||
filters={owners}
|
||||
bottomMargin={false}
|
||||
/>
|
||||
{#if filteredItems?.length == 0}
|
||||
<div class="mt-10"></div>
|
||||
{/if}
|
||||
{#if !loading}
|
||||
<div class="flex w-full flex-row-reverse gap-2 mt-4 mb-1 items-center h-6">
|
||||
<Popover floatingConfig={{ placement: 'bottom-end' }}>
|
||||
{#snippet trigger()}
|
||||
<Button
|
||||
startIcon={{
|
||||
icon: SlidersHorizontal
|
||||
}}
|
||||
nonCaptureEvent
|
||||
iconOnly
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
spacingSize="xs2"
|
||||
/>
|
||||
{/snippet}
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
|
||||
<div class="relative text-tertiary grow min-w-[100px]">
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
autofocus
|
||||
placeholder={HOME_SEARCH_PLACEHOLDER}
|
||||
bind:value={filter}
|
||||
class="bg-surface !h-10 !px-4 !pr-10 !rounded-lg text-sm focus:outline-none"
|
||||
/>
|
||||
<button aria-label="Search" type="submit" class="absolute right-0 top-0 mt-3 mr-4">
|
||||
<svg
|
||||
class="h-4 w-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 56.966 56.966"
|
||||
style="enable-background:new 0 0 56.966 56.966;"
|
||||
xml:space="preserve"
|
||||
width="512px"
|
||||
height="512px"
|
||||
>
|
||||
<path
|
||||
d="M55.146,51.887L41.588,37.786c3.486-4.144,5.396-9.358,5.396-14.786c0-12.682-10.318-23-23-23s-23,10.318-23,23 s10.318,23,23,23c4.761,0,9.298-1.436,13.177-4.162l13.661,14.208c0.571,0.593,1.339,0.92,2.162,0.92 c0.779,0,1.518-0.297,2.079-0.837C56.255,54.982,56.293,53.08,55.146,51.887z M23.984,6c9.374,0,17,7.626,17,17s-7.626,17-17,17 s-17-7.626-17-17S14.61,6,23.984,6z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<Button
|
||||
on:click={() => openSearchWithPrefilledText('#')}
|
||||
variant="border"
|
||||
size="sm"
|
||||
spacingSize="lg"
|
||||
wrapperClasses="h-10"
|
||||
color="light"
|
||||
endIcon={{
|
||||
icon: SearchCode
|
||||
}}
|
||||
>
|
||||
Content
|
||||
</Button>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<ListFilters
|
||||
syncQuery
|
||||
bind:selectedFilter={ownerFilter}
|
||||
filters={owners}
|
||||
bottomMargin={false}
|
||||
/>
|
||||
{#if filteredItems?.length == 0}
|
||||
<div class="mt-10"></div>
|
||||
{/if}
|
||||
{#if !loading}
|
||||
<div class="flex w-full flex-row-reverse gap-2 mt-4 mb-1 items-center h-6">
|
||||
<Popover floatingConfig={{ placement: 'bottom-end' }}>
|
||||
{#snippet trigger()}
|
||||
<Button
|
||||
startIcon={{
|
||||
icon: SlidersHorizontal
|
||||
}}
|
||||
nonCaptureEvent
|
||||
iconOnly
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
spacingSize="xs2"
|
||||
/>
|
||||
{/snippet}
|
||||
{#snippet content()}
|
||||
<div class="p-4">
|
||||
<span class="text-sm font-semibold">Filters</span>
|
||||
<div class="flex flex-col gap-2 mt-2">
|
||||
<Toggle size="xs" bind:checked={archived} options={{ right: 'Only archived' }} />
|
||||
{#if $userStore && !$userStore.operator}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={includeWithoutMain}
|
||||
options={{ right: 'Include without main function' }}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#snippet content()}
|
||||
<div class="p-4">
|
||||
<span class="text-sm font-semibold">Filters</span>
|
||||
<div class="flex flex-col gap-2 mt-2">
|
||||
<Toggle size="xs" bind:checked={archived} options={{ right: 'Only archived' }} />
|
||||
{#if $userStore && !$userStore.operator}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={includeWithoutMain}
|
||||
options={{ right: 'Include without main function' }}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
{#if $userStore?.is_super_admin && $userStore.username.includes('@')}
|
||||
<Toggle size="xs" bind:checked={filterUserFolders} options={{ right: 'Only f/*' }} />
|
||||
{:else if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={filterUserFolders}
|
||||
options={{ right: `Only u/${$userStore.username} and f/*` }}
|
||||
/>
|
||||
{/if}
|
||||
<Toggle size="xs" bind:checked={treeView} options={{ right: 'Tree view' }} />
|
||||
{#if treeView}
|
||||
<Button
|
||||
btnClasses="py-0 h-6"
|
||||
size="xs"
|
||||
variant="border"
|
||||
color="light"
|
||||
on:click={() => (collapseAll = !collapseAll)}
|
||||
startIcon={{
|
||||
icon: collapseAll ? UnfoldVertical : FoldVertical
|
||||
}}
|
||||
>
|
||||
{#if collapseAll}
|
||||
Expand all
|
||||
{:else}
|
||||
Collapse all
|
||||
{/if}
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
{#if filteredItems == undefined}
|
||||
<div class="mt-4"></div>
|
||||
<Skeleton layout={[[2], 1]} />
|
||||
{#each new Array(6) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{:else if filteredItems.length === 0}
|
||||
<NoItemFound />
|
||||
{:else if treeView}
|
||||
<TreeViewRoot
|
||||
{items}
|
||||
{nbDisplayed}
|
||||
{collapseAll}
|
||||
isSearching={filter !== ''}
|
||||
on:scriptChanged={() => loadScripts(includeWithoutMain)}
|
||||
on:flowChanged={loadFlows}
|
||||
on:appChanged={loadApps}
|
||||
on:rawAppChanged={loadRawApps}
|
||||
on:reload={() => {
|
||||
loadScripts(includeWithoutMain)
|
||||
loadFlows()
|
||||
loadApps()
|
||||
loadRawApps()
|
||||
}}
|
||||
{showCode}
|
||||
/>
|
||||
{:else}
|
||||
<div class="border rounded-md">
|
||||
{#each (items ?? []).slice(0, nbDisplayed) as item (item.type + '/' + item.path)}
|
||||
<Item
|
||||
{item}
|
||||
on:scriptChanged={() => loadScripts(includeWithoutMain)}
|
||||
on:flowChanged={loadFlows}
|
||||
on:appChanged={loadApps}
|
||||
on:rawAppChanged={loadRawApps}
|
||||
on:reload={() => {
|
||||
loadScripts(includeWithoutMain)
|
||||
loadFlows()
|
||||
loadApps()
|
||||
loadRawApps()
|
||||
}}
|
||||
{showCode}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{#if items && items?.length > 15 && nbDisplayed < items.length}
|
||||
<span class="text-xs"
|
||||
>{nbDisplayed} items out of {items.length}
|
||||
<button class="ml-4" onclick={() => (nbDisplayed += 30)}>load 30 more</button></span
|
||||
>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Popover>
|
||||
{#if $userStore?.is_super_admin && $userStore.username.includes('@')}
|
||||
<Toggle size="xs" bind:checked={filterUserFolders} options={{ right: 'Only f/*' }} />
|
||||
{:else if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={filterUserFolders}
|
||||
options={{ right: `Only u/${$userStore.username} and f/*` }}
|
||||
/>
|
||||
{/if}
|
||||
<Toggle size="xs" bind:checked={treeView} options={{ right: 'Tree view' }} />
|
||||
{#if treeView}
|
||||
<Button
|
||||
btnClasses="py-0 h-6"
|
||||
size="xs"
|
||||
variant="border"
|
||||
color="light"
|
||||
on:click={() => (collapseAll = !collapseAll)}
|
||||
startIcon={{
|
||||
icon: collapseAll ? UnfoldVertical : FoldVertical
|
||||
}}
|
||||
>
|
||||
{#if collapseAll}
|
||||
Expand all
|
||||
{:else}
|
||||
Collapse all
|
||||
{/if}
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
{#if filteredItems == undefined}
|
||||
<div class="mt-4"></div>
|
||||
<Skeleton layout={[[2], 1]} />
|
||||
{#each new Array(6) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{:else if filteredItems.length === 0}
|
||||
<NoItemFound />
|
||||
{:else if treeView}
|
||||
<TreeViewRoot
|
||||
{items}
|
||||
{nbDisplayed}
|
||||
{collapseAll}
|
||||
isSearching={filter !== ''}
|
||||
on:scriptChanged={() => loadScripts(includeWithoutMain)}
|
||||
on:flowChanged={loadFlows}
|
||||
on:appChanged={loadApps}
|
||||
on:rawAppChanged={loadRawApps}
|
||||
on:reload={() => {
|
||||
loadScripts(includeWithoutMain)
|
||||
loadFlows()
|
||||
loadApps()
|
||||
loadRawApps()
|
||||
}}
|
||||
{showCode}
|
||||
/>
|
||||
{:else}
|
||||
<div class="border rounded-md">
|
||||
{#each (items ?? []).slice(0, nbDisplayed) as item (item.type + '/' + item.path)}
|
||||
<Item
|
||||
{item}
|
||||
on:scriptChanged={() => loadScripts(includeWithoutMain)}
|
||||
on:flowChanged={loadFlows}
|
||||
on:appChanged={loadApps}
|
||||
on:rawAppChanged={loadRawApps}
|
||||
on:reload={() => {
|
||||
loadScripts(includeWithoutMain)
|
||||
loadFlows()
|
||||
loadApps()
|
||||
loadRawApps()
|
||||
}}
|
||||
{showCode}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{#if items && items?.length > 15 && nbDisplayed < items.length}
|
||||
<span class="text-xs"
|
||||
>{nbDisplayed} items out of {items.length}
|
||||
<button class="ml-4" onclick={() => (nbDisplayed += 30)}>load 30 more</button></span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</CenteredPage>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { type AnyMeltElement } from '@melt-ui/svelte'
|
||||
import { conditionalMelt } from '$lib/utils'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
export let aiId: string | undefined = undefined
|
||||
export let aiDescription: string | undefined = undefined
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { melt } from '@melt-ui/svelte'
|
||||
import type { MenubarMenuElements } from '@melt-ui/svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
interface Props {
|
||||
aiId?: string | undefined
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { Button } from '../common'
|
||||
import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte'
|
||||
import ToggleButtonGroup from '../common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import Toggle from '../Toggle.svelte'
|
||||
import { UserService, type NewToken } from '$lib/gen'
|
||||
import { copyToClipboard } from '$lib/utils'
|
||||
@@ -135,10 +135,13 @@
|
||||
<h3 class="pb-3 font-semibold">Add a new token</h3>
|
||||
|
||||
{#if showMcpMode}
|
||||
<div class="mb-4 flex flex-row flex-shrink-0" use:triggerableByAI={{
|
||||
id: 'account-settings-create-mcp-token',
|
||||
description: 'Create a new MCP token to authenticate to the Windmill API'
|
||||
}}>
|
||||
<div
|
||||
class="mb-4 flex flex-row flex-shrink-0"
|
||||
use:triggerableByAI={{
|
||||
id: 'account-settings-create-mcp-token',
|
||||
description: 'Create a new MCP token to authenticate to the Windmill API'
|
||||
}}
|
||||
>
|
||||
<Toggle
|
||||
on:change={(e) => {
|
||||
mcpCreationMode = e.detail
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { goto } from '$app/navigation'
|
||||
import { conditionalMelt } from '$lib/utils'
|
||||
import type { MenubarMenuElements } from '@melt-ui/svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
interface Props {
|
||||
aiId?: string | undefined
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { navigating, page } from '$app/stores'
|
||||
import Popover from '../Popover.svelte'
|
||||
import { base } from '$app/paths'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import AddTriggersButton from './AddTriggersButton.svelte'
|
||||
import TriggerLabel from './TriggerLabel.svelte'
|
||||
import DeleteTriggerButton from './DeleteTriggerButton.svelte'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI'
|
||||
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
||||
|
||||
interface Props {
|
||||
// Props
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
export function langToExt(lang: string): string {
|
||||
switch (lang) {
|
||||
case 'tsx':
|
||||
return 'tsx'
|
||||
case 'javascript':
|
||||
return 'js'
|
||||
case 'jsx':
|
||||
return 'js'
|
||||
case 'bunnative':
|
||||
return 'ts'
|
||||
case 'json':
|
||||
return 'json'
|
||||
case 'sql':
|
||||
return 'sql'
|
||||
case 'yaml':
|
||||
return 'yaml'
|
||||
case 'typescript':
|
||||
return 'ts'
|
||||
case 'python':
|
||||
return 'py'
|
||||
case 'go':
|
||||
return 'go'
|
||||
case 'bash':
|
||||
return 'sh'
|
||||
case 'powershell':
|
||||
return 'ps1'
|
||||
case 'php':
|
||||
return 'php'
|
||||
case 'rust':
|
||||
return 'rs'
|
||||
case 'deno':
|
||||
return 'ts'
|
||||
case 'nativets':
|
||||
return 'ts'
|
||||
case 'graphql':
|
||||
return 'gql'
|
||||
case 'css':
|
||||
return 'css'
|
||||
case 'ansible':
|
||||
return 'yml'
|
||||
case 'csharp':
|
||||
return 'cs'
|
||||
case 'nu':
|
||||
return 'nu'
|
||||
case 'java':
|
||||
return 'java'
|
||||
case 'svelte':
|
||||
return 'svelte'
|
||||
case 'vue':
|
||||
return 'vue'
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
export function extToLang(ext: string) {
|
||||
switch (ext) {
|
||||
case 'tsx':
|
||||
return 'typescript'
|
||||
case 'ts':
|
||||
return 'typescript'
|
||||
case 'js':
|
||||
return 'javascript'
|
||||
case 'jsx':
|
||||
return 'javascript'
|
||||
case 'json':
|
||||
return 'json'
|
||||
case 'sql':
|
||||
return 'sql'
|
||||
case 'yaml':
|
||||
return 'yaml'
|
||||
case 'py':
|
||||
return 'python'
|
||||
case 'go':
|
||||
return 'go'
|
||||
case 'sh':
|
||||
return 'bash'
|
||||
case 'ps1':
|
||||
return 'powershell'
|
||||
case 'php':
|
||||
return 'php'
|
||||
case 'rs':
|
||||
return 'rust'
|
||||
case 'gql':
|
||||
return 'graphql'
|
||||
case 'css':
|
||||
return 'css'
|
||||
case 'yml':
|
||||
return 'ansible'
|
||||
case 'cs':
|
||||
return 'csharp'
|
||||
case 'svelte':
|
||||
return 'svelte'
|
||||
case 'vue':
|
||||
return 'vue'
|
||||
case 'nu':
|
||||
return 'nu'
|
||||
case 'java':
|
||||
return 'java'
|
||||
// for related places search: ADD_NEW_LANG
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
export function createHash() {
|
||||
return (Math.random() + 1).toString(36).substring(2)
|
||||
}
|
||||
|
||||
export function createLongHash() {
|
||||
return 'h' + Math.random().toString(36).substring(2) + Math.random().toString(36).substring(2)
|
||||
}
|
||||
@@ -41,118 +41,7 @@ export function editorConfig(
|
||||
}
|
||||
}
|
||||
|
||||
export function createHash() {
|
||||
return (Math.random() + 1).toString(36).substring(2)
|
||||
}
|
||||
|
||||
export function createLongHash() {
|
||||
return 'h' + Math.random().toString(36).substring(2) + Math.random().toString(36).substring(2)
|
||||
}
|
||||
|
||||
export function langToExt(lang: string): string {
|
||||
switch (lang) {
|
||||
case 'tsx':
|
||||
return 'tsx'
|
||||
case 'javascript':
|
||||
return 'js'
|
||||
case 'jsx':
|
||||
return 'js'
|
||||
case 'bunnative':
|
||||
return 'ts'
|
||||
case 'json':
|
||||
return 'json'
|
||||
case 'sql':
|
||||
return 'sql'
|
||||
case 'yaml':
|
||||
return 'yaml'
|
||||
case 'typescript':
|
||||
return 'ts'
|
||||
case 'python':
|
||||
return 'py'
|
||||
case 'go':
|
||||
return 'go'
|
||||
case 'bash':
|
||||
return 'sh'
|
||||
case 'powershell':
|
||||
return 'ps1'
|
||||
case 'php':
|
||||
return 'php'
|
||||
case 'rust':
|
||||
return 'rs'
|
||||
case 'deno':
|
||||
return 'ts'
|
||||
case 'nativets':
|
||||
return 'ts'
|
||||
case 'graphql':
|
||||
return 'gql'
|
||||
case 'css':
|
||||
return 'css'
|
||||
case 'ansible':
|
||||
return 'yml'
|
||||
case 'csharp':
|
||||
return 'cs'
|
||||
case 'nu':
|
||||
return 'nu'
|
||||
case 'java':
|
||||
return 'java'
|
||||
case 'svelte':
|
||||
return 'svelte'
|
||||
case 'vue':
|
||||
return 'vue'
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
export function extToLang(ext: string) {
|
||||
switch (ext) {
|
||||
case 'tsx':
|
||||
return 'typescript'
|
||||
case 'ts':
|
||||
return 'typescript'
|
||||
case 'js':
|
||||
return 'javascript'
|
||||
case 'jsx':
|
||||
return 'javascript'
|
||||
case 'json':
|
||||
return 'json'
|
||||
case 'sql':
|
||||
return 'sql'
|
||||
case 'yaml':
|
||||
return 'yaml'
|
||||
case 'py':
|
||||
return 'python'
|
||||
case 'go':
|
||||
return 'go'
|
||||
case 'sh':
|
||||
return 'bash'
|
||||
case 'ps1':
|
||||
return 'powershell'
|
||||
case 'php':
|
||||
return 'php'
|
||||
case 'rs':
|
||||
return 'rust'
|
||||
case 'gql':
|
||||
return 'graphql'
|
||||
case 'css':
|
||||
return 'css'
|
||||
case 'yml':
|
||||
return 'ansible'
|
||||
case 'cs':
|
||||
return 'csharp'
|
||||
case 'svelte':
|
||||
return 'svelte'
|
||||
case 'vue':
|
||||
return 'vue'
|
||||
case 'nu':
|
||||
return 'nu'
|
||||
case 'java':
|
||||
return 'java'
|
||||
// for related places search: ADD_NEW_LANG
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
export const updateOptions = { tabSize: 2, insertSpaces: true }
|
||||
|
||||
|
||||
@@ -1,46 +1,253 @@
|
||||
<script lang="ts">
|
||||
// import { BROWSER } from 'esm-env'
|
||||
// import { page } from '$app/stores'
|
||||
// import { base } from '$lib/base'
|
||||
// import { IS_APP_PUBLIC_CONTEXT_KEY, type EditorBreakpoint } from '$lib/components/apps/types'
|
||||
// import { aiChatManager } from '$lib/components/copilot/chat/AIChatManager.svelte'
|
||||
// aiChatManager
|
||||
|
||||
// import { WindmillIcon } from '$lib/components/icons'
|
||||
// import { AppService, OpenAPI, type AppWithLastVersion } from '$lib/gen'
|
||||
// import { enterpriseLicense, userStore } from '$lib/stores'
|
||||
// import { twMerge } from 'tailwind-merge'
|
||||
// import type { AIProviderModel, ScriptLang } from '$lib/gen/types.gen'
|
||||
// import type { ScriptOptions } from './ContextManager.svelte'
|
||||
// import {
|
||||
// flowTools,
|
||||
// prepareFlowSystemMessage,
|
||||
// prepareFlowUserMessage,
|
||||
// type FlowAIChatHelpers
|
||||
// } from './flow/core'
|
||||
// import ContextManager from './ContextManager.svelte'
|
||||
// import HistoryManager from './HistoryManager.svelte'
|
||||
// import { processToolCall, type DisplayMessage, type Tool, type ToolCallbacks } from './shared'
|
||||
|
||||
// HistoryManager
|
||||
// ContextManager
|
||||
// import type {
|
||||
// ChatCompletionChunk,
|
||||
// ChatCompletionMessageParam,
|
||||
// ChatCompletionMessageToolCall,
|
||||
// ChatCompletionSystemMessageParam,
|
||||
// ChatCompletionUserMessageParam
|
||||
// } from 'openai/resources/chat/completions.mjs'
|
||||
|
||||
// import { setContext } from 'svelte'
|
||||
// import { writable } from 'svelte/store'
|
||||
// import { setLicense } from '$lib/enterpriseUtils'
|
||||
// import { isCloudHosted } from '$lib/cloud'
|
||||
// import { getUserExt } from '$lib/user'
|
||||
// import { User, UserRoundX } from 'lucide-svelte'
|
||||
// import { goto } from '$app/navigation'
|
||||
// import { sendUserToast } from '$lib/toast'
|
||||
// import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
// import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte'
|
||||
// import Login from '$lib/components/Login.svelte'
|
||||
// import { dfs } from '$lib/components/flows/previousResults'
|
||||
// import type { FlowModuleState, FlowState } from '$lib/components/flows/flowState'
|
||||
// import type { CurrentEditor, ExtendedOpenFlow } from '$lib/components/flows/types'
|
||||
// import { untrack } from 'svelte'
|
||||
// import type { DBSchemas } from '$lib/stores'
|
||||
// import { getCompletion } from '$lib/components/copilot/lib'
|
||||
// import { getStringError } from '$lib/components/copilot/chat/utils'
|
||||
// import {
|
||||
// navigatorTools,
|
||||
// prepareNavigatorSystemMessage,
|
||||
// prepareNavigatorUserMessage
|
||||
// } from '$lib/components/copilot/chat/navigator/core'
|
||||
// import {
|
||||
// prepareScriptSystemMessage,
|
||||
// prepareScriptTools,
|
||||
// prepareScriptUserMessage
|
||||
// } from '$lib/components/copilot/chat/script/core'
|
||||
// import { loadApiTools } from '$lib/components/copilot/chat/navigator/apiTools'
|
||||
// import { langToExt } from '$lib/editorUtils'
|
||||
// import { langToExt } from '$lib/editorLangUtils'
|
||||
|
||||
// import { ResourceService, type ListResourceResponse, type ScriptLang } from '$lib/gen'
|
||||
// import { scriptLangToEditorLang } from '$lib/scripts'
|
||||
|
||||
// import HistoryManager from '$lib/components/copilot/chat/HistoryManager.svelte'
|
||||
// import ContextManager from '$lib/components/copilot/chat/ContextManager.svelte'
|
||||
// loadApiTools
|
||||
// import { askTools, prepareAskSystemMessage } from './ask/core'
|
||||
// import { chatState, DEFAULT_SIZE, triggerablesByAi } from './sharedChatState.svelte'
|
||||
|
||||
// import FlowStatusViewerInner from '$lib/components/FlowStatusViewerInner.svelte'
|
||||
|
||||
// import ArgTest from '$lib/components/ArgTest.svelte'
|
||||
// import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
|
||||
// import { goto } from '$lib/navigation'
|
||||
// import Github from '$lib/components/icons/brands/Github.svelte'
|
||||
// import Gitlab from '$lib/components/icons/brands/Gitlab.svelte'
|
||||
// import Google from '$lib/components/icons/brands/Google.svelte'
|
||||
// import Microsoft from '$lib/components/icons/brands/Microsoft.svelte'
|
||||
// import Okta from '$lib/components/icons/brands/Okta.svelte'
|
||||
// import Auth0 from '$lib/components/icons/brands/Auth0.svelte'
|
||||
// AppPrevi
|
||||
// import ArgInput from '$lib/components/ArgInput.svelte'
|
||||
|
||||
// import { OauthService, UserService, WorkspaceService } from '$lib/gen'
|
||||
// import { usersWorkspaceStore, workspaceStore, userStore } from '$lib/stores'
|
||||
// import { classNames, emptyString, parseQueryParams } from '$lib/utils'
|
||||
// import { base } from '$lib/base'
|
||||
// import { getUserExt } from '$lib/user'
|
||||
// import { sendUserToast } from '$lib/toast'
|
||||
// import { isCloudHosted } from '$lib/cloud'
|
||||
// import { refreshSuperadmin } from '$lib/refreshUser'
|
||||
// import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
||||
// import SchemaForm from '$lib/components/SchemaForm.svelte'
|
||||
|
||||
// import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte'
|
||||
// import Button from '$lib/components/common/button/Button.svelte'
|
||||
// import RunnableComponent from '$lib/components/apps/components/helpers/RunnableComponent.svelte'
|
||||
|
||||
// import ComponentInner from '$lib/components/apps/editor/component/ComponentInner.svelte'
|
||||
|
||||
// import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
// import { getContext, onDestroy, setContext, untrack } from 'svelte'
|
||||
// import { get, writable, type Writable } from 'svelte/store'
|
||||
// import { buildWorld } from '../rx'
|
||||
// import type {
|
||||
// App,
|
||||
// AppViewerContext,
|
||||
// ConnectingInput,
|
||||
// EditorBreakpoint,
|
||||
// EditorMode
|
||||
// } from '../types'
|
||||
// import type { Policy } from '$lib/gen'
|
||||
// import { Unlock } from 'lucide-svelte'
|
||||
// import GridViewer from '$lib/components/apps/editor/GridViewer.svelte'
|
||||
// import { twMerge } from 'tailwind-merge'
|
||||
// import { ButtonType } from '$lib/components/common'
|
||||
|
||||
// import { dfs, maxHeight } from './appUtils'
|
||||
// import { BG_PREFIX, migrateApp } from '../utils'
|
||||
// import { workspaceStore, enterpriseLicense } from '$lib/stores'
|
||||
// import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
|
||||
// import { getTheme } from './componentsPanel/themeUtils'
|
||||
// import HiddenComponent from '../components/helpers/HiddenComponent.svelte'
|
||||
// import RecomputeAllComponents from './RecomputeAllComponents.svelte'
|
||||
|
||||
// HiddenComponent,
|
||||
// RecomputeAllComponents
|
||||
// import HiddenComponent from '$lib/components/apps/components/helpers/HiddenComponent.svelte'
|
||||
// RunnableComponent
|
||||
// import { buildWorld } from '../rx'
|
||||
// import type {
|
||||
// App,
|
||||
// AppViewerContext,
|
||||
// ConnectingInput,
|
||||
// EditorBreakpoint,
|
||||
// EditorMode
|
||||
// } from '../types'
|
||||
// import type { Policy } from '$lib/gen'
|
||||
// import Button from '../../common/button/Button.svelte'
|
||||
// import { Unlock } from 'lucide-svelte'
|
||||
// import GridViewer from './GridViewer.svelte'
|
||||
// import Component from './component/Component.svelte'
|
||||
// import { twMerge } from 'tailwind-merge'
|
||||
// import { deepEqual } from 'fast-equals'
|
||||
// import { dfs, maxHeight } from './appUtils'
|
||||
// import { BG_PREFIX, migrateApp } from '../utils'
|
||||
// import { workspaceStore, enterpriseLicense } from '$lib/stores'
|
||||
// import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
|
||||
// import { getTheme } from './componentsPanel/themeUtils'
|
||||
// import HiddenComponent from '../components/helpers/HiddenComponent.svelte'
|
||||
// import RecomputeAllComponents from './RecomputeAllComponents.svelte'
|
||||
// ComponentInner
|
||||
// import { Button } from '$lib/components/common'
|
||||
|
||||
// SchemaForm
|
||||
|
||||
// ArgInput
|
||||
|
||||
// import {
|
||||
// setInputCat as computeInputCat,
|
||||
// debounce,
|
||||
// emptyString,
|
||||
// getSchemaFromProperties
|
||||
// } from '$lib/utils'
|
||||
// import { DollarSign, Pipette, Plus, X, Check, Loader2 } from 'lucide-svelte'
|
||||
// import { createEventDispatcher, onDestroy, onMount, tick, untrack } from 'svelte'
|
||||
// import { fade } from 'svelte/transition'
|
||||
// import { Button, SecondsInput } from './common'
|
||||
// import FieldHeader from './FieldHeader.svelte'
|
||||
// import type ItemPicker from './ItemPicker.svelte'
|
||||
// import ObjectResourceInput from './ObjectResourceInput.svelte'
|
||||
// import Range from './Range.svelte'
|
||||
// import ResourcePicker from './ResourcePicker.svelte'
|
||||
// import type SimpleEditor from './SimpleEditor.svelte'
|
||||
// import Toggle from './Toggle.svelte'
|
||||
// import type VariableEditor from './VariableEditor.svelte'
|
||||
// import { twMerge } from 'tailwind-merge'
|
||||
// import ArgEnum from './ArgEnum.svelte'
|
||||
// import DateTimeInput from './DateTimeInput.svelte'
|
||||
// import DateInput from './DateInput.svelte'
|
||||
// import S3FilePicker from './S3FilePicker.svelte'
|
||||
// import CurrencyInput from './apps/components/inputs/currency/CurrencyInput.svelte'
|
||||
// import FileUpload from './common/fileUpload/FileUpload.svelte'
|
||||
// import autosize from '$lib/autosize'
|
||||
// import PasswordArgInput from './PasswordArgInput.svelte'
|
||||
// import Password from './Password.svelte'
|
||||
// import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
// import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
|
||||
// import SchemaFormDnd from '$lib/components/schema/SchemaFormDND.svelte'
|
||||
// import SchemaForm from './SchemaForm.svelte'
|
||||
// import { deepEqual } from 'fast-equals'
|
||||
// import DynSelect from './DynSelect.svelte'
|
||||
// import type { Script } from '$lib/gen'
|
||||
// import type { SchemaDiff } from '$lib/components/schema/schemaUtils.svelte'
|
||||
// import type { ComponentCustomCSS } from './apps/types'
|
||||
// import MultiSelect from './select/MultiSelect.svelte'
|
||||
// import { safeSelectItems } from './select/utils.svelte'
|
||||
// SchemaFormDnd
|
||||
|
||||
// import FlowJobResult from './FlowJobResult.svelte'
|
||||
// import FlowPreviewStatus from './preview/FlowPreviewStatus.svelte'
|
||||
// import DisplayResult from './DisplayResult.svelte'
|
||||
|
||||
// FlowJobResult
|
||||
// import FlowJobResult from '$lib/components/FlowJobResult.svelte'
|
||||
// import FlowPreviewStatus from '$lib/components/preview/FlowPreviewStatus.svelte'
|
||||
// import DisplayResult from '$lib/components/DisplayResult.svelte'
|
||||
|
||||
// FlowJobResult
|
||||
// FlowPreviewStatus
|
||||
// DisplayResult
|
||||
|
||||
// FlowStatusViewerInner
|
||||
|
||||
// import JobArgs from './JobArgs.svelte'
|
||||
// import { ChevronDown, Hourglass, Loader2 } from 'lucide-svelte'
|
||||
// import FlowStatusWaitingForEvents from './FlowStatusWaitingForEvents.svelte'
|
||||
// import { deepEqual } from 'fast-equals'
|
||||
// import FlowTimeline from './FlowTimeline.svelte'
|
||||
// import { dfs } from './flows/dfs'
|
||||
// import { get, writable, type Unsubscriber, type Writable } from 'svelte/store'
|
||||
// import Alert from './common/alert/Alert.svelte'
|
||||
// import FlowGraphViewerStep from './FlowGraphViewerStep.svelte'
|
||||
// import FlowGraphV2 from './graph/FlowGraphV2.svelte'
|
||||
// import { buildPrefix } from './graph/graphBuilder.svelte'
|
||||
|
||||
// import JobArgs from '$lib/components/JobArgs.svelte'
|
||||
// import FlowStatusWaitingForEvents from '$lib/components/FlowStatusWaitingForEvents.svelte'
|
||||
|
||||
// import DisplayResult from '$lib/components/DisplayResult.svelte'
|
||||
// import FlowTimeline from '$lib/components/FlowTimeline.svelte'
|
||||
// import { dfs } from '$lib/components/flows/dfs'
|
||||
// import { get, writable, type Unsubscriber, type Writable } from 'svelte/store'
|
||||
|
||||
// TimelineBar
|
||||
|
||||
// import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
// import FlowGraphViewerStep from '$lib/components/FlowGraphViewerStep.svelte'
|
||||
// import FlowGraphV2 from '$lib/components/graph/FlowGraphV2.svelte'
|
||||
// import { buildPrefix } from '$lib/components/graph/graphBuilder.svelte'
|
||||
// import Popover from '$lib/components/Popover.svelte'
|
||||
// import TimelineBar from '$lib/components/TimelineBar.svelte'
|
||||
// Popover
|
||||
|
||||
// import ModuleNode from './renderers/nodes/ModuleNode.svelte'
|
||||
// import InputNode from './renderers/nodes/InputNode.svelte'
|
||||
// import BranchAllStart from './renderers/nodes/BranchAllStart.svelte'
|
||||
// import BranchAllEndNode from './renderers/nodes/BranchAllEndNode.svelte'
|
||||
// import ForLoopEndNode from './renderers/nodes/ForLoopEndNode.svelte'
|
||||
// import ForLoopStartNode from './renderers/nodes/ForLoopStartNode.svelte'
|
||||
// import ResultNode from './renderers/nodes/ResultNode.svelte'
|
||||
// import BaseEdge from './renderers/edges/BaseEdge.svelte'
|
||||
// import EmptyEdge from './renderers/edges/EmptyEdge.svelte'
|
||||
// import { sugiyama, dagStratify, coordCenter, decrossTwoLayer, decrossOpt } from 'd3-dag'
|
||||
// import { Expand } from 'lucide-svelte'
|
||||
// import Toggle from '../Toggle.svelte'
|
||||
// import DataflowEdge from './renderers/edges/DataflowEdge.svelte'
|
||||
// import { encodeState } from '$lib/utils'
|
||||
// import BranchOneStart from './renderers/nodes/BranchOneStart.svelte'
|
||||
// import NoBranchNode from './renderers/nodes/NoBranchNode.svelte'
|
||||
// import HiddenBaseEdge from './renderers/edges/HiddenBaseEdge.svelte'
|
||||
// import TriggersNode from './renderers/nodes/TriggersNode.svelte'
|
||||
// import { Alert, Drawer } from '../common'
|
||||
// import Button from '../common/button/Button.svelte'
|
||||
// import FlowYamlEditor from '../flows/header/FlowYamlEditor.svelte'
|
||||
// import BranchOneEndNode from './renderers/nodes/branchOneEndNode.svelte'
|
||||
// import type { TriggerContext } from '../triggers'
|
||||
// import { workspaceStore } from '$lib/stores'
|
||||
// import SubflowBound from './renderers/nodes/SubflowBound.svelte'
|
||||
// import { deepEqual } from 'fast-equals'
|
||||
// import ViewportResizer from './ViewportResizer.svelte'
|
||||
|
||||
// import ModuleNode from '$lib/components/graph/renderers/nodes/ModuleNode.svelte'
|
||||
// import InputNode from '$lib/components/graph/renderers/nodes/InputNode.svelte'
|
||||
// import BranchAllStart from '$lib/components/graph/renderers/nodes/BranchAllStart.svelte'
|
||||
// import BranchAllEndNode from '$lib/components/graph/renderers/nodes/BranchAllEndNode.svelte'
|
||||
// import ForLoopEndNode from '$lib/components/graph/renderers/nodes/ForLoopEndNode.svelte'
|
||||
// import ForLoopStartNode from '$lib/components/graph/renderers/nodes/ForLoopStartNode.svelte'
|
||||
// import ResultNode from '$lib/components/graph/renderers/nodes/ResultNode.svelte'
|
||||
// import BaseEdge from '$lib/components/graph/renderers/edges/BaseEdge.svelte'
|
||||
// import VirtualItem from '$lib/components/flows/map/VirtualItem.svelte'
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user