mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-16 08:03:02 +00:00
feat: evals open as a dialog over the agent editor page
The editor page opens an agent's evals over itself, as the agent page does, with the unsaved edits offered to a run; the editor dialog keeps evals as a level of its own. The two pages share the dialog. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
954d8b0212
commit
0fd5973b12
@@ -37,6 +37,7 @@
|
||||
import { linkedModulesForAgent, linkedToolsScope } from '../linkedAgentToolsStore.svelte'
|
||||
import AgentEditorHost from './AgentEditorHost.svelte'
|
||||
import AgentSettings from './AgentSettings.svelte'
|
||||
import AgentEvalsModal from './AgentEvalsModal.svelte'
|
||||
import { useOperatingWorkspace } from '$lib/components/operatingWorkspace.svelte'
|
||||
|
||||
const operatingWorkspace = useOperatingWorkspace()
|
||||
@@ -92,6 +93,7 @@
|
||||
let host = $state<ReturnType<typeof AgentEditorHost> | undefined>(undefined)
|
||||
let versionDrawer: Drawer | undefined = $state(undefined)
|
||||
let settingsDrawer: Drawer | undefined = $state(undefined)
|
||||
let evalsModal: AgentEvalsModal | undefined = $state(undefined)
|
||||
let saving = $state(false)
|
||||
|
||||
// Counted per agent, so a deploy that leaves the editor on the same agent still refetches the
|
||||
@@ -163,6 +165,12 @@
|
||||
// belongs to that level rather than to the dialog's own name.
|
||||
let description = $derived(inEvals || inSettings || refused ? undefined : AGENT_DESCRIPTION)
|
||||
|
||||
// The dialog's levels are its pages; a page has none, so evals open over it as a dialog.
|
||||
function openEvals() {
|
||||
if (layout === 'modal') showAgentEditorView('evals')
|
||||
else evalsModal?.openModal()
|
||||
}
|
||||
|
||||
function openSettings() {
|
||||
if (layout === 'modal') showAgentEditorView('settings')
|
||||
else settingsDrawer?.openDrawer()
|
||||
@@ -410,7 +418,7 @@
|
||||
variant="default"
|
||||
startIcon={{ icon: FlaskConical }}
|
||||
title="Run this agent against a dataset of cases"
|
||||
on:click={() => showAgentEditorView('evals')}
|
||||
on:click={openEvals}
|
||||
>
|
||||
Evals
|
||||
</Button>
|
||||
@@ -507,6 +515,15 @@
|
||||
/>
|
||||
{/snippet}
|
||||
|
||||
{#if layout === 'page' && ws}
|
||||
<AgentEvalsModal
|
||||
bind:this={evalsModal}
|
||||
agentPath={target?.path ?? ''}
|
||||
workspace={ws}
|
||||
editedConfig={draft?.sync.hasDraft ? editedConfig : undefined}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<Drawer bind:this={settingsDrawer} size="600px">
|
||||
<DrawerContent title="Settings" on:close={() => settingsDrawer?.closeDrawer()}>
|
||||
{@render settingsFields()}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<script lang="ts">
|
||||
import { Badge } from '$lib/components/common'
|
||||
import Modal from '$lib/components/common/modal/Modal.svelte'
|
||||
import EvalsPane from '$lib/components/aiEvals/EvalsPane.svelte'
|
||||
import type { EvalsLocation } from '$lib/components/aiEvals/evalUtils'
|
||||
import type { AgentDraft } from '$lib/gen'
|
||||
|
||||
/** An agent's evals in a dialog of their own, over the page that opened them. */
|
||||
interface Props {
|
||||
agentPath: string
|
||||
workspace: string
|
||||
/** The unsaved edits, offered to a run as an alternative to the deployed version. */
|
||||
editedConfig?: () => AgentDraft
|
||||
}
|
||||
|
||||
let { agentPath, workspace, editedConfig = undefined }: Props = $props()
|
||||
|
||||
let open = $state(false)
|
||||
// Where the evals pane is within itself, so its levels extend the dialog's trail. Cleared on the
|
||||
// way in: the pane reports a level once it is on one, and never that it is back at its root.
|
||||
let location = $state<EvalsLocation | undefined>(undefined)
|
||||
|
||||
export function openModal() {
|
||||
location = undefined
|
||||
open = true
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if open}
|
||||
<Modal
|
||||
bind:open
|
||||
kind="X"
|
||||
fillHeight
|
||||
enterConfirms={false}
|
||||
title="Evals"
|
||||
trail={[
|
||||
{ label: 'Evals', onclick: location ? location.back : undefined },
|
||||
...(location ? [{ label: location.label }] : [])
|
||||
]}
|
||||
class="w-[92vw] sm:w-[92vw] max-w-[1500px] sm:max-w-[1500px] h-[88vh]"
|
||||
>
|
||||
{#snippet titleBadge()}
|
||||
{#if !location}
|
||||
<Badge color="blue" small class="shrink-0 !py-0 leading-4">Beta</Badge>
|
||||
{/if}
|
||||
{/snippet}
|
||||
<EvalsPane {agentPath} opWorkspace={workspace} {editedConfig} bind:location active={open} />
|
||||
</Modal>
|
||||
{/if}
|
||||
@@ -5,10 +5,8 @@
|
||||
import { base } from '$lib/base'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { copilotInfo } from '$lib/aiStore'
|
||||
import { Badge, Button } from '$lib/components/common'
|
||||
import Modal from '$lib/components/common/modal/Modal.svelte'
|
||||
import EvalsPane from '$lib/components/aiEvals/EvalsPane.svelte'
|
||||
import type { EvalsLocation } from '$lib/components/aiEvals/evalUtils'
|
||||
import { Button } from '$lib/components/common'
|
||||
import AgentEvalsModal from '$lib/components/flows/content/AgentEvalsModal.svelte'
|
||||
import DropdownV2 from '$lib/components/DropdownV2.svelte'
|
||||
import SummaryPathDisplay from '$lib/components/SummaryPathDisplay.svelte'
|
||||
import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
@@ -44,14 +42,7 @@
|
||||
let shareModal: ShareModal | undefined = $state(undefined)
|
||||
let deploymentDrawer: DeployWorkspaceDrawer | undefined = $state(undefined)
|
||||
let deleteOpen = $state(false)
|
||||
let evalsOpen = $state(false)
|
||||
// Where the evals pane is within itself, so its levels extend the dialog's trail. Cleared on the
|
||||
// way in: the pane reports a level once it is on one, and never that it is back at its root.
|
||||
let evalsLocation = $state<EvalsLocation | undefined>(undefined)
|
||||
function openEvals() {
|
||||
evalsLocation = undefined
|
||||
evalsOpen = true
|
||||
}
|
||||
let evalsModal: AgentEvalsModal | undefined = $state(undefined)
|
||||
|
||||
async function deleteAgent() {
|
||||
if (!ws) return
|
||||
@@ -131,7 +122,7 @@
|
||||
unifiedSize="md"
|
||||
startIcon={{ icon: FlaskConical }}
|
||||
title="Run this agent against a dataset of cases"
|
||||
onClick={openEvals}
|
||||
onClick={() => evalsModal?.openModal()}
|
||||
>
|
||||
Evals
|
||||
</Button>
|
||||
@@ -204,26 +195,8 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{#if evalsOpen && ws}
|
||||
<Modal
|
||||
bind:open={evalsOpen}
|
||||
kind="X"
|
||||
fillHeight
|
||||
enterConfirms={false}
|
||||
title="Evals"
|
||||
trail={[
|
||||
{ label: 'Evals', onclick: evalsLocation ? evalsLocation.back : undefined },
|
||||
...(evalsLocation ? [{ label: evalsLocation.label }] : [])
|
||||
]}
|
||||
class="w-[92vw] sm:w-[92vw] max-w-[1500px] sm:max-w-[1500px] h-[88vh]"
|
||||
>
|
||||
{#snippet titleBadge()}
|
||||
{#if !evalsLocation}
|
||||
<Badge color="blue" small class="shrink-0 !py-0 leading-4">Beta</Badge>
|
||||
{/if}
|
||||
{/snippet}
|
||||
<EvalsPane agentPath={path} opWorkspace={ws} bind:location={evalsLocation} active={evalsOpen} />
|
||||
</Modal>
|
||||
{#if ws}
|
||||
<AgentEvalsModal bind:this={evalsModal} agentPath={path} workspace={ws} />
|
||||
{/if}
|
||||
|
||||
{#if config}
|
||||
|
||||
Reference in New Issue
Block a user