Files
windmill/frontend/src/lib/components/graph/model.ts
T
Ruben FiszelandClaude Opus 5 4c4387d52a feat(flow-editor): show an agent's tool-call status without moving the graph (#10557)
* feat(flow-editor): surface an agent's tool-call status without moving the graph

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: count only an agent's tool calls and key them in one place

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat: report an agent's replies alongside its tool calls

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat: break the agent summary down by action kind

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: key agent tool nodes by kind and keep the summary clear of the tool row

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* refactor: read agent action status from the run's success array

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: pin the tool joins a local run cannot reach

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: place the agent summary beside the step and match MCP paths bare

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: feed a single-step agent test's calls into the graph status

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 02:17:34 +00:00

89 lines
2.3 KiB
TypeScript

import type { FlowStatusModule, Job, WorkflowStatus } from '$lib/gen'
import type { StateStore } from '$lib/utils'
import type { FlowState } from '../flows/flowState'
export type ModuleHost = 'workspace' | 'inline' | 'hub'
export type Loop = {
type: 'loop'
items: NestedNodes
}
export type Branch = {
node: Node
nodeEnd: Node
type: 'branch'
items: NestedNodes[]
}
export type GraphItem = Node | Loop | Branch
export type GraphModuleStates = {
job_id: string
states: Record<string, GraphModuleState>
}
export type DurationStatus = {
byJob: Record<string, { created_at?: number; started_at?: number; duration_ms?: number }>
}
export type FlowStatusViewerContext = {
flowState?: FlowState
retryStatus: StateStore<Record<string, number | undefined>>
suspendStatus: StateStore<Record<string, { nb: number; job: Job }>>
hideDownloadInGraph?: boolean
hideTimeline?: boolean
hideNodeDefinition?: boolean
hideJobId?: boolean
hideDownloadLogs?: boolean
}
export type GraphModuleState = {
type: FlowStatusModule['type']
args: any
logs?: string
flow_jobs_results?: any
branchChosen?: number
result?: any
tag?: string
scheduled_for?: Date
job_id?: string
parent_module?: string
selectedForloop?: string
selectedForloopIndex?: number
selectedForLoopSetManually?: boolean
flow_jobs_success?: (boolean | undefined)[]
flow_jobs_duration?: {
started_at?: (string | undefined)[]
duration_ms?: (number | undefined)[]
}
flow_jobs?: string[]
iteration_total?: number
retries?: number
duration_ms?: number
started_at?: number
suspend_count?: number
isListJob?: boolean
skipped?: boolean
agent_actions?: FlowStatusModule['agent_actions']
/** Positionally aligned with `agent_actions`: every push of an action appends one entry, so a
* missing entry means that action has not finished yet. */
agent_actions_success?: FlowStatusModule['agent_actions_success']
script_hash?: string
workflow_as_code_status?: WorkflowStatus
}
export type NestedNodes = GraphItem[]
export function isNode(item: GraphItem | NestedNodes | undefined): item is Node {
return item?.['type'] === 'node'
}
export function isLoop(item: GraphItem | NestedNodes | undefined): item is Loop {
return item?.['type'] === 'loop'
}
export function isBranch(item: GraphItem | NestedNodes | undefined): item is Branch {
return item?.['type'] === 'branch'
}