feat: agent node
This commit is contained in:
@@ -71,6 +71,7 @@ export const DEFAULT_NODE_STYLE: Record<string, { width: number; height: number
|
||||
variable: { width: 224, height: 180 },
|
||||
function: { width: 288, height: 260 },
|
||||
data: { width: 360, height: 280 },
|
||||
agent: { width: 360, height: 320 },
|
||||
}
|
||||
|
||||
/** Default data for a new node. Uses nodeRegistry when type is registered. */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type React from 'react'
|
||||
|
||||
export type NodeType = 'config' | 'render' | 'variable' | 'function' | 'data'
|
||||
export type NodeType = 'config' | 'render' | 'variable' | 'function' | 'data' | 'agent'
|
||||
|
||||
export type NodeHelpEntry = {
|
||||
title: string
|
||||
@@ -90,6 +90,19 @@ export const NODE_HELP: Record<NodeType, NodeHelpEntry> = {
|
||||
</>
|
||||
),
|
||||
},
|
||||
agent: {
|
||||
title: 'Agent node',
|
||||
content: (
|
||||
<>
|
||||
<Section title="How to use">
|
||||
<p>Agent nodes use AI to produce structured markdown. Connect Config nodes as the <strong>prompt</strong> (their content is sent as the main prompt). Optionally connect Variable or Data nodes; they are passed as context. Define additional context in the text area. Click Run to execute the agent; output is markdown. Connect this node to a Renderer to display the result.</p>
|
||||
</Section>
|
||||
<Section title="Output">
|
||||
<p>When connected to a Renderer node, the agent’s markdown output is rendered there. Ensure the backend <Code>/api/agent</Code> is running and (if using OpenAI) <Code>OPENAI_API_KEY</Code> is set.</p>
|
||||
</Section>
|
||||
</>
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
export function getNodeHelp(nodeType: NodeType): NodeHelpEntry {
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
import type React from 'react'
|
||||
import type { Node } from '@xyflow/react'
|
||||
|
||||
/** Node classification for UI: Psyche (Form/Config, Variable, Behavior/Function), Pneuma (Rendering), Physis (TBD). */
|
||||
export type NodeClassification = 'psyche' | 'pneuma' | 'physis'
|
||||
/** Node classification for UI: Psyche, Pneuma, Physis, Archon (AI Agent). */
|
||||
export type NodeClassification = 'psyche' | 'pneuma' | 'physis' | 'archon'
|
||||
|
||||
export const NODE_CLASSIFICATION_LABELS: Record<NodeClassification, string> = {
|
||||
psyche: 'Psyche',
|
||||
pneuma: 'Pneuma',
|
||||
physis: 'Physis',
|
||||
archon: 'Archon',
|
||||
}
|
||||
|
||||
export type NodeHelpEntry = {
|
||||
@@ -59,7 +60,7 @@ export function getNodeType(id: string): NodeTypeDescriptor | undefined {
|
||||
return registry.get(id)
|
||||
}
|
||||
|
||||
const CLASSIFICATION_ORDER: NodeClassification[] = ['psyche', 'pneuma', 'physis']
|
||||
const CLASSIFICATION_ORDER: NodeClassification[] = ['psyche', 'pneuma', 'physis', 'archon']
|
||||
|
||||
export function getRegisteredNodeTypes(): NodeTypeDescriptor[] {
|
||||
return Array.from(registry.values())
|
||||
|
||||
@@ -8,7 +8,8 @@ import type { RenderingNodeData } from '@/components/nodes/RenderingNode'
|
||||
import type { VariableNodeData } from '@/components/nodes/VariableNode'
|
||||
import type { FunctionNodeData } from '@/components/nodes/FunctionNode'
|
||||
import type { DataNodeData } from '@/components/nodes/DataNode'
|
||||
import type { AgentNodeData } from '@/components/nodes/AgentNode'
|
||||
|
||||
export type AppNodeData = ConfigNodeData | RenderingNodeData | VariableNodeData | FunctionNodeData | DataNodeData
|
||||
export type AppNodeData = ConfigNodeData | RenderingNodeData | VariableNodeData | FunctionNodeData | DataNodeData | AgentNodeData
|
||||
export type AppNode = Node<AppNodeData>
|
||||
export type AppEdge = Edge
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { ScrollText, Sparkles, Variable, Code2, Database } from 'lucide-react'
|
||||
import { ScrollText, Sparkles, Variable, Code2, Database, Bot } from 'lucide-react'
|
||||
import { registerNodeType } from './nodeRegistry'
|
||||
import { NODE_HELP } from './nodeHelp'
|
||||
import ConfigNode from '../components/nodes/ConfigNode'
|
||||
@@ -12,6 +12,7 @@ import RenderingNode from '../components/nodes/RenderingNode'
|
||||
import VariableNode from '../components/nodes/VariableNode'
|
||||
import FunctionNode from '../components/nodes/FunctionNode'
|
||||
import DataNode from '../components/nodes/DataNode'
|
||||
import AgentNode from '../components/nodes/AgentNode'
|
||||
|
||||
const ICON_CLASS = 'mr-2 h-4 w-4'
|
||||
|
||||
@@ -26,7 +27,7 @@ export function registerBuiltinNodes(): void {
|
||||
hasOutput: true,
|
||||
classification: 'psyche',
|
||||
allowedSourceTypes: ['config', 'variable', 'function', 'data'],
|
||||
allowedTargetTypes: ['config', 'render'],
|
||||
allowedTargetTypes: ['config', 'render', 'agent'],
|
||||
help: NODE_HELP.config,
|
||||
menuLabel: 'Config',
|
||||
menuIcon: <ScrollText className={ICON_CLASS} />,
|
||||
@@ -52,13 +53,30 @@ export function registerBuiltinNodes(): void {
|
||||
hasInput: true,
|
||||
hasOutput: false,
|
||||
classification: 'pneuma',
|
||||
allowedSourceTypes: ['config'],
|
||||
allowedSourceTypes: ['config', 'agent'],
|
||||
help: NODE_HELP.render,
|
||||
menuLabel: 'Renderer',
|
||||
menuIcon: <Sparkles className={ICON_CLASS} />,
|
||||
connectionLabel: 'rendering',
|
||||
})
|
||||
|
||||
registerNodeType({
|
||||
id: 'agent',
|
||||
component: AgentNode,
|
||||
defaultStyle: { width: 360, height: 320 },
|
||||
defaultData: { context: '' },
|
||||
idPrefix: 'agt_',
|
||||
hasInput: true,
|
||||
hasOutput: true,
|
||||
classification: 'archon',
|
||||
allowedSourceTypes: ['config', 'variable', 'data'],
|
||||
allowedTargetTypes: ['render'],
|
||||
help: NODE_HELP.agent,
|
||||
menuLabel: 'Agent',
|
||||
menuIcon: <Bot className={ICON_CLASS} />,
|
||||
connectionLabel: 'prompt/context',
|
||||
})
|
||||
|
||||
registerNodeType({
|
||||
id: 'variable',
|
||||
component: VariableNode,
|
||||
@@ -68,7 +86,7 @@ export function registerBuiltinNodes(): void {
|
||||
hasInput: false,
|
||||
hasOutput: true,
|
||||
classification: 'psyche',
|
||||
allowedTargetTypes: ['config', 'function'],
|
||||
allowedTargetTypes: ['config', 'function', 'agent'],
|
||||
help: NODE_HELP.variable,
|
||||
menuLabel: 'Variable',
|
||||
menuIcon: <Variable className={ICON_CLASS} />,
|
||||
@@ -83,7 +101,7 @@ export function registerBuiltinNodes(): void {
|
||||
hasInput: false,
|
||||
hasOutput: true,
|
||||
classification: 'physis',
|
||||
allowedTargetTypes: ['config'],
|
||||
allowedTargetTypes: ['config', 'agent'],
|
||||
help: NODE_HELP.data,
|
||||
menuLabel: 'Data',
|
||||
menuIcon: <Database className={ICON_CLASS} />,
|
||||
|
||||
Reference in New Issue
Block a user