{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "generate-text-node",
	"type": "registry:ui",
	"title": "Generate Text Node",
	"description": "A React Flow node component that represents Vercel AI SDK's text generation capabilities, featuring system instructions, prompts, and optional tool outputs.",
	"dependencies": ["@xyflow/react"],
	"registryDependencies": [
		"button",
		"separator",
		"@simple-ai/model-selector",
		"@simple-ai/node-header-status",
		"@simple-ai/editable-handle",
		"@simple-ai/labeled-handle",
		"@simple-ai/base-node",
		"@simple-ai/node-header"
	],
	"files": [
		{
			"path": "./src/registry/ui/flow/generate-text-node.tsx",
			"content": "import {\n\ttype Node,\n\ttype NodeProps,\n\tPosition,\n\tuseUpdateNodeInternals,\n} from \"@xyflow/react\";\nimport { Bot, Plus, Trash } from \"lucide-react\";\nimport { useCallback } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\nimport { BaseNode } from \"@/registry/ui/flow/base-node\";\nimport {\n\tEditableHandle,\n\tEditableHandleDialog,\n} from \"@/registry/ui/flow/editable-handle\";\nimport { LabeledHandle } from \"@/registry/ui/flow/labeled-handle\";\nimport {\n\tNodeHeader,\n\tNodeHeaderAction,\n\tNodeHeaderActions,\n\tNodeHeaderIcon,\n\tNodeHeaderTitle,\n} from \"@/registry/ui/flow/node-header\";\nimport { NodeHeaderStatus } from \"@/registry/ui/flow/node-header-status\";\nimport { type Model, ModelSelector } from \"@/registry/ui/model-selector\";\n\nexport type GenerateTextData = {\n\tstatus: \"processing\" | \"error\" | \"success\" | \"idle\" | undefined;\n\tconfig: {\n\t\tmodel: Model;\n\t};\n\tdynamicHandles: {\n\t\ttools: {\n\t\t\tid: string;\n\t\t\tname: string;\n\t\t\tdescription?: string;\n\t\t}[];\n\t};\n};\n\nexport type GenerateTextNode = Node<GenerateTextData, \"generate-text\">;\n\ninterface GenerateTextNodeProps extends NodeProps<GenerateTextNode> {\n\tdisableModelSelector?: boolean;\n\tonModelChange: (model: Model) => void;\n\tonCreateTool: (name: string, description?: string) => boolean;\n\tonRemoveTool: (handleId: string) => void;\n\tonUpdateTool: (\n\t\ttoolId: string,\n\t\tnewName: string,\n\t\tnewDescription?: string,\n\t) => boolean;\n\tonDeleteNode: () => void;\n}\n\nexport function GenerateTextNode({\n\tid,\n\tselected,\n\tdeletable,\n\tdisableModelSelector,\n\tdata,\n\tonModelChange,\n\tonCreateTool,\n\tonRemoveTool,\n\tonUpdateTool,\n\tonDeleteNode,\n}: GenerateTextNodeProps) {\n\tconst updateNodeInternals = useUpdateNodeInternals();\n\n\tconst handleModelChange = useCallback(\n\t\t(value: string) => {\n\t\t\tonModelChange?.(value as Model);\n\t\t},\n\t\t[onModelChange],\n\t);\n\n\tconst handleCreateTool = useCallback(\n\t\t(name: string, description?: string) => {\n\t\t\tif (!onCreateTool) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst result = onCreateTool(name, description);\n\t\t\tif (result) {\n\t\t\t\tupdateNodeInternals(id);\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\t[onCreateTool, id, updateNodeInternals],\n\t);\n\n\tconst removeHandle = useCallback(\n\t\t(handleId: string) => {\n\t\t\tonRemoveTool?.(handleId);\n\t\t\tupdateNodeInternals(id);\n\t\t},\n\t\t[onRemoveTool, id, updateNodeInternals],\n\t);\n\n\treturn (\n\t\t<BaseNode\n\t\t\tselected={selected}\n\t\t\tclassName={cn(\"w-[350px] p-0 hover:ring-orange-500\", {\n\t\t\t\t\"border-orange-500\": data.status === \"processing\",\n\t\t\t\t\"border-red-500\": data.status === \"error\",\n\t\t\t})}\n\t\t>\n\t\t\t<NodeHeader className=\"m-0\">\n\t\t\t\t<NodeHeaderIcon>\n\t\t\t\t\t<Bot />\n\t\t\t\t</NodeHeaderIcon>\n\t\t\t\t<NodeHeaderTitle>Generate Text</NodeHeaderTitle>\n\t\t\t\t<NodeHeaderActions>\n\t\t\t\t\t<NodeHeaderStatus status={data.status} />\n\t\t\t\t\t{deletable && (\n\t\t\t\t\t\t<NodeHeaderAction\n\t\t\t\t\t\t\tonClick={onDeleteNode}\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tlabel=\"Delete node\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Trash />\n\t\t\t\t\t\t</NodeHeaderAction>\n\t\t\t\t\t)}\n\t\t\t\t</NodeHeaderActions>\n\t\t\t</NodeHeader>\n\t\t\t<Separator />\n\t\t\t<div className=\"p-4 flex flex-col gap-4\">\n\t\t\t\t<ModelSelector\n\t\t\t\t\tvalue={data.config.model}\n\t\t\t\t\tonChange={handleModelChange}\n\t\t\t\t\tdisabled={disableModelSelector}\n\t\t\t\t\tdisabledModels={[\n\t\t\t\t\t\t\"gpt-4o\",\n\t\t\t\t\t\t\"gpt-4o-mini\",\n\t\t\t\t\t\t\"deepseek-r1-distill-llama-70b\",\n\t\t\t\t\t]}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className=\"grid grid-cols-[2fr,1fr] gap-2 pt-2 text-sm\">\n\t\t\t\t<div className=\"flex flex-col gap-2 min-w-0\">\n\t\t\t\t\t<LabeledHandle\n\t\t\t\t\t\tid=\"system\"\n\t\t\t\t\t\ttitle=\"System\"\n\t\t\t\t\t\ttype=\"target\"\n\t\t\t\t\t\tposition={Position.Left}\n\t\t\t\t\t/>\n\t\t\t\t\t<LabeledHandle\n\t\t\t\t\t\tid=\"prompt\"\n\t\t\t\t\t\ttitle=\"Prompt\"\n\t\t\t\t\t\ttype=\"target\"\n\t\t\t\t\t\tposition={Position.Left}\n\t\t\t\t\t\tclassName=\"col-span-2\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"justify-self-end\">\n\t\t\t\t\t<LabeledHandle\n\t\t\t\t\t\tid=\"result\"\n\t\t\t\t\t\ttitle=\"Result\"\n\t\t\t\t\t\ttype=\"source\"\n\t\t\t\t\t\tposition={Position.Right}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"border-t border-border mt-2\">\n\t\t\t\t<div>\n\t\t\t\t\t<div className=\"flex items-center justify-between py-2 px-4 bg-muted\">\n\t\t\t\t\t\t<span className=\"text-sm font-medium\">\n\t\t\t\t\t\t\tTool outputs\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<EditableHandleDialog\n\t\t\t\t\t\t\tvariant=\"create\"\n\t\t\t\t\t\t\tonSave={handleCreateTool}\n\t\t\t\t\t\t\talign=\"end\"\n\t\t\t\t\t\t\tshowDescription\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tclassName=\"h-7 px-2\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Plus className=\"h-4 w-4 mr-1\" />\n\t\t\t\t\t\t\t\tNew tool output\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</EditableHandleDialog>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t{data.dynamicHandles.tools.map((tool) => (\n\t\t\t\t\t\t\t<EditableHandle\n\t\t\t\t\t\t\t\tkey={tool.id}\n\t\t\t\t\t\t\t\tnodeId={id}\n\t\t\t\t\t\t\t\thandleId={tool.id}\n\t\t\t\t\t\t\t\tname={tool.name}\n\t\t\t\t\t\t\t\tdescription={tool.description}\n\t\t\t\t\t\t\t\ttype=\"source\"\n\t\t\t\t\t\t\t\tposition={Position.Right}\n\t\t\t\t\t\t\t\twrapperClassName=\"w-full\"\n\t\t\t\t\t\t\t\tonUpdateTool={onUpdateTool}\n\t\t\t\t\t\t\t\tonDelete={removeHandle}\n\t\t\t\t\t\t\t\tshowDescription\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</BaseNode>\n\t);\n}\n",
			"type": "registry:ui",
			"target": "components/flow/generate-text-node.tsx"
		}
	]
}
