mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 08:02:47 +00:00
fix: the agent's settings report path errors, and hold nothing a reader can edit
The path field reads its error back, so it shows it and keeps deploy blocked on it. Labels are shown rather than editable without write access. Evals wait for the load to know they can be opened, and the page layout builds no levels it never shows. 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
995fd1b1e5
commit
96d0a6e62b
@@ -447,14 +447,17 @@
|
||||
|
||||
/** The path field's own verdict (a taken path, an invalid name), which the server would otherwise
|
||||
* only report after the request. The field lives with whoever shows it, which reports here. */
|
||||
let pathError = $state('')
|
||||
let pathErrorValue = $state('')
|
||||
export function pathError() {
|
||||
return pathErrorValue
|
||||
}
|
||||
export function setPathError(error: string | undefined) {
|
||||
pathError = error ?? ''
|
||||
pathErrorValue = error ?? ''
|
||||
}
|
||||
|
||||
export function deploy(): Promise<boolean> {
|
||||
if (pathError) {
|
||||
sendUserToast(`Cannot deploy the agent: ${pathError}`, true)
|
||||
if (pathErrorValue) {
|
||||
sendUserToast(`Cannot deploy the agent: ${pathErrorValue}`, true)
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
return draft.deploy().then(async (written) => {
|
||||
|
||||
@@ -130,6 +130,12 @@
|
||||
let inSettings = $derived(target?.view === 'settings' && !refused)
|
||||
let readOnly = $derived(draft ? !draft.canWrite : false)
|
||||
let draftOnly = $derived(draft?.noDeployed ?? false)
|
||||
// Evals run against the deployed agent, and a draft-only one has none: the backend's
|
||||
// `require_agent` would reject every run. Evaluating is authoring, so it is for those who can
|
||||
// edit the agent. Unknown until the load answers, and warming the pane loads it.
|
||||
let canEvaluate = $derived(
|
||||
draft != undefined && !draft.loading && !draftOnly && !readOnly && !refused
|
||||
)
|
||||
// A never-deployed agent is stored at a minted `draft_<uuid>` path, so it is named by the path
|
||||
// its first deploy will create, as the home list names it.
|
||||
let shownPath = $derived((draftOnly && draft?.state?.path) || target?.path)
|
||||
@@ -410,10 +416,7 @@
|
||||
on:click={openSettings}
|
||||
/>
|
||||
{/if}
|
||||
<!-- Evals run against the deployed agent, and a draft-only one has none: the
|
||||
backend's `require_agent` would reject every run. Evaluating is authoring, so it
|
||||
is for those who can edit the agent. -->
|
||||
{#if !draftOnly && !readOnly}
|
||||
{#if canEvaluate}
|
||||
<Button
|
||||
unifiedSize="sm"
|
||||
variant="default"
|
||||
@@ -463,16 +466,16 @@
|
||||
<!-- One strip of pages, so a level slides in from the right the way evals' own levels do.
|
||||
No `onNavigate`: the arrow keys belong to whichever pane is on screen, and evals answers
|
||||
them for its own levels. Warmed, as those levels are: a page built on its first visit
|
||||
lands inside the transition and arrives empty. Evals only where they can be opened,
|
||||
since warming them loads them. -->
|
||||
lands inside the transition and arrives empty. The page layout has no levels: it opens
|
||||
settings in a drawer and evals in a dialog, so warming them there would build them twice. -->
|
||||
<PagedContent
|
||||
warm
|
||||
class="flex-1 min-h-0"
|
||||
current={inEvals ? 'evals' : inSettings ? 'settings' : 'agent'}
|
||||
pages={[
|
||||
{ key: 'agent', content: agentPage },
|
||||
{ key: 'settings', content: settingsPage },
|
||||
...(draftOnly || readOnly ? [] : [{ key: 'evals', content: evalsPage }])
|
||||
...(layout === 'modal' ? [{ key: 'settings', content: settingsPage }] : []),
|
||||
...(layout === 'modal' && canEvaluate ? [{ key: 'evals', content: evalsPage }] : [])
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
@@ -500,7 +503,7 @@
|
||||
{draft}
|
||||
path={target?.path ?? ''}
|
||||
workspace={ws}
|
||||
bind:error={() => undefined, (error) => host?.setPathError(error)}
|
||||
bind:error={() => host?.pathError(), (error) => host?.setPathError(error)}
|
||||
/>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { resource } from 'runed'
|
||||
import { Badge } from '$lib/components/common'
|
||||
import Label from '$lib/components/Label.svelte'
|
||||
import LabelsInput from '$lib/components/LabelsInput.svelte'
|
||||
import Path from '$lib/components/Path.svelte'
|
||||
@@ -52,7 +53,17 @@
|
||||
disabled={readOnly}
|
||||
/>
|
||||
</Label>
|
||||
<LabelsInput bind:labels={draft.state.labels} {workspace} class="-mt-4" />
|
||||
{#if readOnly}
|
||||
{#if draft.state.labels?.length}
|
||||
<div class="-mt-4 inline-flex items-center gap-1">
|
||||
{#each draft.state.labels as label (label)}
|
||||
<Badge color="blue" small>{label}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<LabelsInput bind:labels={draft.state.labels} {workspace} class="-mt-4" />
|
||||
{/if}
|
||||
{#if deployTo.current}
|
||||
<Label label="Workspace specific" tooltip="Keeps this agent out of deploys to prod/staging.">
|
||||
<Toggle bind:checked={draft.state.wsSpecific} disabled={readOnly} />
|
||||
|
||||
Reference in New Issue
Block a user