mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 00:02:19 +00:00
fix(script-editor,raw-app-editor): preserve AI chat across editor nav
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
import JobLoader from './JobLoader.svelte'
|
||||
import JobProgressBar from '$lib/components/jobs/JobProgressBar.svelte'
|
||||
import { createEventDispatcher, getContext, onDestroy, onMount, untrack } from 'svelte'
|
||||
import { beforeNavigate } from '$app/navigation'
|
||||
import { Button } from './common'
|
||||
import SplitPanesWrapper from './splitPanes/SplitPanesWrapper.svelte'
|
||||
import WindmillIcon from './icons/WindmillIcon.svelte'
|
||||
@@ -1203,6 +1204,24 @@
|
||||
}
|
||||
})
|
||||
|
||||
// Preserve the chat across the /scripts/add → /scripts/edit/{path} promotion
|
||||
// (and same-script reloads): ScriptEditor unmounts + remounts on those
|
||||
// transitions, and without this its onDestroy would saveAndClear the
|
||||
// SCRIPT-mode conversation the user is still actively having about this same
|
||||
// script.
|
||||
let preserveChatOnDestroy = $state(false)
|
||||
beforeNavigate(({ to }) => {
|
||||
const dest = to?.url.pathname ?? ''
|
||||
if (!dest.startsWith('/scripts/edit/')) return
|
||||
const destPath = dest.slice('/scripts/edit/'.length)
|
||||
const currentPath = aiChatManager.scriptEditorOptions?.path
|
||||
// !currentPath: on /scripts/add, dest is /scripts/edit/{path} (initial save).
|
||||
// destPath === currentPath: same script (e.g. query change / reload).
|
||||
if (!currentPath || destPath === currentPath) {
|
||||
preserveChatOnDestroy = true
|
||||
}
|
||||
})
|
||||
|
||||
onMount(async () => {
|
||||
await inferSchema(code, { applyInitialArgs: true })
|
||||
// Retry once if the initial inference failed silently (e.g. transient WASM
|
||||
@@ -1211,7 +1230,12 @@
|
||||
if (!validCode && code && lang) {
|
||||
await inferSchema(code, { applyInitialArgs: true })
|
||||
}
|
||||
aiChatManager.saveAndClear()
|
||||
// The previous instance's onDestroy may have preserved the chat for
|
||||
// intra-script-editor nav; in that case mode is still SCRIPT and the
|
||||
// conversation is intact. Skip saveAndClear so we don't blow it away.
|
||||
if (aiChatManager.mode !== AIMode.SCRIPT) {
|
||||
aiChatManager.saveAndClear()
|
||||
}
|
||||
aiChatManager.changeMode(AIMode.SCRIPT)
|
||||
})
|
||||
|
||||
@@ -1298,8 +1322,10 @@
|
||||
aiChatManager.scriptEditorShowDiffMode = undefined
|
||||
aiChatManager.scriptEditorGetLintErrors = undefined
|
||||
aiChatManager.scriptEditorOptions = undefined
|
||||
aiChatManager.saveAndClear()
|
||||
aiChatManager.changeMode(AIMode.NAVIGATOR)
|
||||
if (!preserveChatOnDestroy) {
|
||||
aiChatManager.saveAndClear()
|
||||
aiChatManager.changeMode(AIMode.NAVIGATOR)
|
||||
}
|
||||
// Clean up debug mode
|
||||
if (debugMode) {
|
||||
stopDebugging()
|
||||
@@ -1357,9 +1383,7 @@
|
||||
// width (Svelte wires a ResizeObserver for bind:clientWidth).
|
||||
let splitContainerWidth = $state(0)
|
||||
const TEST_PANE_MIN_PX = 400
|
||||
const testPaneMinPercent = $derived(
|
||||
paneMinPercent(splitContainerWidth, TEST_PANE_MIN_PX)
|
||||
)
|
||||
const testPaneMinPercent = $derived(paneMinPercent(splitContainerWidth, TEST_PANE_MIN_PX))
|
||||
|
||||
// Raw user-controlled test size (what the splitter wrote, or what the
|
||||
// toggle set). The size we actually pass to <Pane> is clamped to the
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
import type { Modules } from './RawAppModules.svelte'
|
||||
import { isRunnableByName, isRunnableByPath } from '../apps/inputType'
|
||||
import { aiChatManager, AIMode } from '../copilot/chat/AIChatManager.svelte'
|
||||
import { onMount, untrack } from 'svelte'
|
||||
import { onDestroy, onMount, untrack } from 'svelte'
|
||||
import { beforeNavigate } from '$app/navigation'
|
||||
import type {
|
||||
AppDatatableMetadata,
|
||||
LintResult,
|
||||
@@ -618,8 +619,30 @@
|
||||
)
|
||||
}
|
||||
|
||||
// Preserve the chat across the /apps_raw/add → /apps_raw/edit/{path} promotion
|
||||
// (and same-app reloads): RawAppEditor unmounts + remounts on those
|
||||
// transitions, and without this the fresh onMount's saveAndClear would blow
|
||||
// away the APP-mode conversation the user is still actively having about this
|
||||
// same app.
|
||||
let preserveChatOnDestroy = $state(false)
|
||||
beforeNavigate(({ to }) => {
|
||||
const dest = to?.url.pathname ?? ''
|
||||
if (!dest.startsWith('/apps_raw/edit/')) return
|
||||
const destPath = dest.slice('/apps_raw/edit/'.length)
|
||||
// !path: on /apps_raw/add, dest is /apps_raw/edit/{path} (initial deploy).
|
||||
// destPath === path: same app.
|
||||
if (!path || destPath === path) {
|
||||
preserveChatOnDestroy = true
|
||||
}
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
aiChatManager.saveAndClear()
|
||||
// The previous instance may have preserved the chat for intra-app-editor
|
||||
// nav; in that case mode is still APP and the conversation is intact. Skip
|
||||
// saveAndClear so we don't blow it away.
|
||||
if (aiChatManager.mode !== AIMode.APP) {
|
||||
aiChatManager.saveAndClear()
|
||||
}
|
||||
aiChatManager.changeMode(AIMode.APP)
|
||||
rawAppLintStore.enable()
|
||||
loadSharedUi()
|
||||
@@ -645,6 +668,16 @@
|
||||
}
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
// Cross-app / leave-editor navigation resets to NAVIGATOR; same-app /
|
||||
// add→edit navigation keeps the chat (the fresh onMount detects mode is
|
||||
// still APP and skips its clearing saveAndClear).
|
||||
if (!preserveChatOnDestroy) {
|
||||
aiChatManager.saveAndClear()
|
||||
aiChatManager.changeMode(AIMode.NAVIGATOR)
|
||||
}
|
||||
})
|
||||
|
||||
// Sync data with aiChatManager.datatableCreationPolicy (bidirectional)
|
||||
$effect(() => {
|
||||
// Read the current policy from aiChatManager
|
||||
@@ -1637,8 +1670,9 @@
|
||||
title="Build failed"
|
||||
class="relative before:absolute before:inset-0 before:-z-10 before:rounded-md before:bg-surface before:content-['']"
|
||||
>
|
||||
<pre
|
||||
class="overflow-auto whitespace-pre-wrap text-xs max-h-60">{buildError}</pre>
|
||||
<pre class="overflow-auto whitespace-pre-wrap text-xs max-h-60"
|
||||
>{buildError}</pre
|
||||
>
|
||||
</Alert>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user