feat: agent node

This commit is contained in:
2026-03-11 14:39:38 +01:00
parent 94da42f9fc
commit f201fe92f4
15 changed files with 772 additions and 24 deletions

View File

@@ -64,10 +64,12 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
const incomingIds = sourceIds
const srcId = incomingIds.length > 0 ? incomingIds[0] : null
const srcNode = nodes.find((n: any) => n.id === srcId)
const configTypeId = srcNode?.type === 'config' ? getConfigTypeId((srcNode.data ?? undefined) as Record<string, unknown> | undefined) : 'plantuml'
const isAgentSource = srcNode?.type === 'agent'
const agentOutputMarkdown = isAgentSource ? ((srcNode.data as { outputMarkdown?: string })?.outputMarkdown ?? '') : ''
const configTypeId = srcNode?.type === 'config' ? getConfigTypeId((srcNode.data ?? undefined) as Record<string, unknown> | undefined) : isAgentSource ? 'markdown' : 'plantuml'
const configType = getConfigType(configTypeId)
const outputType = configType.outputType
const sourceContent = srcNode?.type === 'config' ? getConfigContent((srcNode.data ?? undefined) as Record<string, unknown> | undefined) : ''
const sourceContent = srcNode?.type === 'config' ? getConfigContent((srcNode.data ?? undefined) as Record<string, unknown> | undefined) : isAgentSource ? agentOutputMarkdown : ''
const srcData = srcNode?.data ?? {}
/** Set of node IDs that can affect this render node (configs in the chain + variables/functions feeding them) */
@@ -184,7 +186,10 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
if (!sourceContent && incomingIds.length > 0) {
setRenderedContent(null)
setResolvedContent(null)
setError({ kind: 'no-content', message: 'No content on connected configuration node' })
setError({
kind: 'no-content',
message: isAgentSource ? 'Run the Agent node to generate output.' : 'No content on connected configuration node',
})
setLoading(false)
return
}
@@ -205,6 +210,17 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
setLoading(true)
setError(null)
try {
if (srcNode?.type === 'agent') {
const md = (srcNode.data as { outputMarkdown?: string })?.outputMarkdown ?? ''
setResolvedContent(md)
const markdownType = getConfigType('markdown')
const html = await markdownType.render(md)
if (cancelled || thisRunId !== runIdRef.current) return
setRenderedContent(html)
setError(null)
setLoading(false)
return
}
const configIdsUsed = new Set<string>()
const isReachable = (startId: string, targetId: string) => {
@@ -531,7 +547,7 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
}
}
// Only re-run when inputs that affect the resolved output change (signatures + source). Debounced to avoid excessive re-renders while typing. retryCount triggers re-run on Retry.
}, [id, sourceContent, configTypeId, configSignature, edgesSignature, variablesSignature, functionsSignature, dataSignature, viewportWidth, viewportHeight, retryCount])
}, [id, sourceContent, configTypeId, configSignature, edgesSignature, variablesSignature, functionsSignature, dataSignature, viewportWidth, viewportHeight, retryCount, isAgentSource])
const dimensions =
width != null && height != null && width > 0 && height > 0