mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-21 08:03:33 +00:00
* feat(frontend): group the AI agent step form and edit saved agents in a modal Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat: edit a saved AI agent through its own resource draft Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor: drop the agent fork-for-edit session now that edits live in a draft Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat: edit ai_agent resources from the resources page with the agent editor Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: send a standalone agent's brain from the module when testing a step Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep the agent draft faithful to the resource it deploys to Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: add the sqlx cache entry for the eval subject rename Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor: share the module insert between the graph and the agent editor Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): open evals inside the agent editor, actions in its header Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): add tools from the agent editor and lighten its test pane Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): open an ai_agent deep link in the agent editor Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): drop the failed result badge on a step that never ran Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): head the agent editor's levels with a back control Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): drop connect and fill inputs from the agent editor Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): lighten the agent editor's run panel Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): stop a nested agent tool's config reading as AI-filled Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): offer only AI or static on an agent tool's inputs Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): give a saved agent's tool editor a static-only surface Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): open an agent tool in a drawer beside the agent Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat(frontend): hide unset agent config in the run form Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor(frontend): share the input forms' pickers and s3 lookup Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore(frontend): drop a dead agent-editor export and fix two stale comments Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): reach an ai_agent's resource-level settings and copilot Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): open an ai_agent's resource view as JSON, not the generic form Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): address review findings on the agent editor's draft and streaming Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): close the agent editor on a version restore, as the resource editor does Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): stop the provider picker auto-writing a kind, and clear review nits Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor(frontend): drop the fork-for-edit leftovers from the agent card Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): mount the agent editor in the dev flow editor and guard the deep-link race Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): deploy the agent config that was submitted, and refuse one no run could use Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * refactor(frontend): build the agent editor's rows from the design-system button Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): keep a draft-only agent's draft, and let a blank MCP summary deploy Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): guard read-only agents, incomplete MCP tools and duplicate editor mounts Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: read-only agent editor, linked-card refresh, atomic eval rename * fix: eval rename needs the privileged pool, per-workspace write access * fix(frontend): drop the agent editor target when its mount goes away * refactor: drop the agent rename work from this PR, unban the bindable defaults * fix(frontend): refuse a renaming deploy and drop the copilot from static-only fields * fix(frontend): mirror the worker's streaming rule and scope agent writes to their target * fix(frontend): read runtime streaming as off and reset the drawer's json view * fix(frontend): read an unsettled output_type as non-streaming too * fix(frontend): let the showing modal claim an agent opened from inside it * fix(frontend): keep in-flight edits, tool replacements and every linked step in sync * fix(frontend): keep attachments in the run form and bind the agent ref to its tools * fix(frontend): preview the agent as authored and re-evaluate step args on run * fix(frontend): scope agent-editor ownership to the flow's workspace * fix(frontend): drop the tool drill-in where there is no graph to select on * fix(frontend): require a provider kind and keep one resource editor open at a time * fix(frontend): keep legacy nulls, static-only text literal, and the handover anchor * test(worker): pin the agent streaming default * fix(frontend): let an AI-fillable input be switched to static * fix(frontend): report agent editor background failures instead of floating them * fix(frontend): keep the version pane's path alive while the editor closes * fix(frontend): clear the anchor-keep flag at the start of each drawer session * fix(frontend): preview the agent without its synthetic path, refresh the baseline on external writes * refactor(frontend): drop the unverifiable baseline refresh, state the synthetic-path rule * fix(frontend): keep the synthetic path out of agent tool test runs too * refactor(frontend): host the agent editor under the agent's own path * fix(frontend): mark an agent editor's host explicitly instead of inferring it from the path * fix(frontend): discard linked-agent responses from before a deploy * fix(frontend): keep a flow mount from claiming an agent editor's nested target * feat(frontend): keep an agent used as a tool inside the agent being edited * fix(frontend): reserve the agent editor's root module id * docs(frontend): record why the agent editor previews under the agent's path * fix(frontend): refuse to open or deploy a resource that is not an agent * docs(frontend): put the scope-migration comment on the function it describes * fix(frontend): refuse an agent path whose resource type is not proven * fix(frontend): recheck the resource type before deploying, and keep expressions off static-only inputs * fix(frontend): lazy-load the agent editor and slide its levels like the evals pane * refactor: drop unreachable non-list tools check from agent deploy Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): clear text-only agent fields on image output, reserve the root id Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): keep the agent editor usable for a non-list tools value Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): stop the parked eval run list from taking arrow keys Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): report a non-list tools value on deploy instead of throwing Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): keep temperature editable for image output Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): skip non-object tool entries when rendering an agent Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): guard tool entry reads instead of copying the tool array Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(frontend): key tool rows by position so duplicate ids render Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
105 lines
3.1 KiB
TypeScript
105 lines
3.1 KiB
TypeScript
import type { GroupDisplayState } from '$lib/components/graph/groupEditor.svelte'
|
|
import { refreshStateStore } from '$lib/svelte5Utils.svelte'
|
|
import type { GroupedModulesProxy } from '$lib/components/graph/groupedModulesProxy.svelte'
|
|
import type { SelectionManager } from '$lib/components/graph/selectionUtils.svelte'
|
|
import type { FlowStructureNode } from '$lib/components/graph/flowStructure'
|
|
import type { OpenFlow } from '$lib/gen'
|
|
import { push, type History } from '$lib/history.svelte'
|
|
import type { StateStore } from '$lib/utils'
|
|
import { createDeletePlan, removeDeletePlanTools, type DeletePlan } from './flowDeleteUtils'
|
|
import type { FlowState } from './flowState'
|
|
import { deleteFlowStateById } from './flowStateUtils.svelte'
|
|
|
|
export type PreparedDeleteRequest = {
|
|
plan: DeletePlan
|
|
needsDependencyConfirmation: boolean
|
|
}
|
|
|
|
export type DeletePlanExecutionContext = {
|
|
history?: History<OpenFlow>
|
|
flowStore: StateStore<OpenFlow>
|
|
flowStateStore: StateStore<FlowState>
|
|
selectionManager: Pick<SelectionManager, 'clearSelection' | 'selectId'>
|
|
onDelete?: (id: string) => void
|
|
}
|
|
|
|
export type DeletePlanExecutionResult = {
|
|
removedStateIds: string[]
|
|
removedToolStateIds: string[]
|
|
}
|
|
|
|
export function prepareDeleteRequest(args: {
|
|
ids: string[]
|
|
flow: OpenFlow
|
|
tree: FlowStructureNode[]
|
|
proxy: GroupedModulesProxy
|
|
displayState: GroupDisplayState
|
|
}): PreparedDeleteRequest | undefined {
|
|
const plan = createDeletePlan(args)
|
|
if (!plan) {
|
|
return undefined
|
|
}
|
|
|
|
return {
|
|
plan,
|
|
needsDependencyConfirmation: Object.keys(plan.dependents).length > 0
|
|
}
|
|
}
|
|
|
|
export function executeDeletePlan(
|
|
plan: DeletePlan,
|
|
args: DeletePlanExecutionContext
|
|
): DeletePlanExecutionResult {
|
|
push(args.history, args.flowStore.val)
|
|
const removedStructureStateIds = resolvePlannedStructureStateIds(plan.targets)
|
|
|
|
if (plan.selection.kind === 'clear') {
|
|
args.selectionManager.clearSelection()
|
|
} else {
|
|
// Whatever remains selected after a delete was not asked for, so it must not
|
|
// pop the modal panel open.
|
|
args.selectionManager.selectId(plan.selection.id, { openPanel: false })
|
|
}
|
|
|
|
if (plan.targets.some((target) => target.kind === 'preprocessor')) {
|
|
args.flowStore.val.value.preprocessor_module = undefined
|
|
}
|
|
|
|
plan.structureDelete?.commit({ removeDuplicates: plan.removeDuplicates })
|
|
|
|
const removedToolStateIds = removeDeletePlanTools(plan.targets, args.flowStore.val.value.modules)
|
|
const removedStateIds = uniqueIds([...removedStructureStateIds, ...removedToolStateIds])
|
|
|
|
for (const id of removedStateIds) {
|
|
deleteFlowStateById(id, args.flowStateStore)
|
|
}
|
|
|
|
refreshStateStore(args.flowStore)
|
|
|
|
if (plan.inputIds.length === 1) {
|
|
args.onDelete?.(plan.targets[0].id)
|
|
}
|
|
|
|
return {
|
|
removedStateIds,
|
|
removedToolStateIds
|
|
}
|
|
}
|
|
|
|
function resolvePlannedStructureStateIds(targets: DeletePlan['targets']): string[] {
|
|
const removedIds: string[] = []
|
|
|
|
for (const target of targets) {
|
|
if (target.kind !== 'preprocessor' && target.kind !== 'structure_node') {
|
|
continue
|
|
}
|
|
removedIds.push(...target.stateIds)
|
|
}
|
|
|
|
return uniqueIds(removedIds)
|
|
}
|
|
|
|
function uniqueIds(ids: string[]): string[] {
|
|
return [...new Set(ids)]
|
|
}
|