feat: add icon property to workflow node specifications and update related components

This commit is contained in:
mlogclub
2026-06-28 15:24:00 +08:00
parent 389291143a
commit 530cf145b2
12 changed files with 42 additions and 57 deletions
+14
View File
@@ -25,6 +25,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeStart,
Title: "Start",
Description: "Conversation workflow entry.",
Icon: "PlayCircleIcon",
RiskLevel: NodeRiskLevelLow,
OutputSchema: []VariableSpec{
output("conversationId", VariableTypeInteger, "Conversation ID."),
@@ -38,6 +39,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeConversationUnderstanding,
Title: "Conversation Understanding",
Description: "Classify customer message intent and answer scope before retrieval.",
Icon: "MessageCircleIcon",
RiskLevel: NodeRiskLevelLow,
InputSchema: []VariableSpec{
requiredInput("userMessage", VariableTypeString, "Current user message content."),
@@ -75,6 +77,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeReplyPolicy,
Title: "Reply Policy",
Description: "Decide the next customer-service action from understanding output and agent policy.",
Icon: "ShieldCheckIcon",
RiskLevel: NodeRiskLevelLow,
InputSchema: []VariableSpec{
requiredInput("messageIntent", VariableTypeString, "Detected customer message intent."),
@@ -115,6 +118,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeKnowledgeRetrieve,
Title: "Knowledge Retrieve",
Description: "Retrieve knowledge for the current user message.",
Icon: "BookOpenIcon",
RiskLevel: NodeRiskLevelLow,
InputSchema: []VariableSpec{
requiredInput("query", VariableTypeString, "Search query."),
@@ -131,6 +135,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeAnswerabilityGate,
Title: "Answerability Gate",
Description: "Decide whether retrieved knowledge is enough to answer.",
Icon: "HelpCircleIcon",
RiskLevel: NodeRiskLevelLow,
InputSchema: []VariableSpec{
requiredInput("userMessage", VariableTypeString, "Current user message content."),
@@ -148,6 +153,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeLLMReply,
Title: "LLM Reply",
Description: "Generate a reply or structured analysis with the configured model.",
Icon: "BotIcon",
RiskLevel: NodeRiskLevelMedium,
InputSchema: []VariableSpec{
requiredInput("userMessage", VariableTypeString, "Current user message content."),
@@ -161,6 +167,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeCondition,
Title: "Condition",
Description: "Route by controlled workflow variables.",
Icon: "GitBranchIcon",
RiskLevel: NodeRiskLevelLow,
OutputSchema: []VariableSpec{
output("matched", VariableTypeBoolean, "Whether the condition matched."),
@@ -170,6 +177,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeAnalyzeConversation,
Title: "Analyze Conversation",
Description: "Analyze intent, risk, and recommended next action.",
Icon: "SearchIcon",
RiskLevel: NodeRiskLevelLow,
InputSchema: []VariableSpec{
requiredInput("userMessage", VariableTypeString, "Current user message content."),
@@ -185,6 +193,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypePrepareTicketDraft,
Title: "Prepare Ticket Draft",
Description: "Build a ticket draft from conversation context.",
Icon: "ClipboardListIcon",
RiskLevel: NodeRiskLevelMedium,
InputSchema: []VariableSpec{
requiredInput("issue", VariableTypeString, "Issue summary."),
@@ -197,6 +206,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeHumanConfirm,
Title: "Human Confirm",
Description: "Interrupt and wait for explicit user confirmation.",
Icon: "UserCheckIcon",
RiskLevel: NodeRiskLevelMedium,
Interruptible: true,
InputSchema: []VariableSpec{
@@ -211,6 +221,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeCreateTicket,
Title: "Create Ticket",
Description: "Create a ticket from a confirmed draft.",
Icon: "TicketIcon",
RiskLevel: NodeRiskLevelHigh,
RequiresConfirmationPredecessor: true,
InputSchema: []VariableSpec{
@@ -228,6 +239,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeHandoffToHuman,
Title: "Handoff To Human",
Description: "Transfer the conversation to human support.",
Icon: "HeadphonesIcon",
RiskLevel: NodeRiskLevelHigh,
InputSchema: []VariableSpec{
requiredInput("reason", VariableTypeString, "Handoff reason."),
@@ -252,6 +264,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeSendReply,
Title: "Send Reply",
Description: "Return or commit customer-visible reply text.",
Icon: "SendIcon",
RiskLevel: NodeRiskLevelLow,
InputSchema: []VariableSpec{
requiredInput("replyText", VariableTypeString, "Customer-visible reply text."),
@@ -265,6 +278,7 @@ func DefaultRegistry() *Registry {
Type: NodeTypeEnd,
Title: "End",
Description: "End workflow execution.",
Icon: "FlagIcon",
RiskLevel: NodeRiskLevelLow,
OutputSchema: []VariableSpec{
output("status", VariableTypeString, "Workflow terminal status."),
+1
View File
@@ -44,6 +44,7 @@ type NodeSpec struct {
Type string `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Icon string `json:"icon"`
RiskLevel NodeRiskLevel `json:"riskLevel"`
Interruptible bool `json:"interruptible"`
RequiresConfirmationPredecessor bool `json:"requiresConfirmationPredecessor"`
+1
View File
@@ -76,6 +76,7 @@ func BuildAIWorkflowNodeSpecs(list []workflowregistry.NodeSpec) []response.AIWor
Type: item.Type,
Title: item.Title,
Description: item.Description,
Icon: item.Icon,
RiskLevel: item.RiskLevel,
Interruptible: item.Interruptible,
RequiresConfirmationPredecessor: item.RequiresConfirmationPredecessor,
@@ -19,6 +19,9 @@ func TestBuildAIWorkflowNodeSpecsIncludesVariableContracts(t *testing.T) {
switch spec.Type {
case workflowregistry.NodeTypeStart:
startFound = true
if spec.Icon != "PlayCircleIcon" {
t.Fatalf("expected start icon PlayCircleIcon, got %q", spec.Icon)
}
if !hasResponseVariable(spec.OutputSchema, "userMessage") {
t.Fatalf("expected start output userMessage, got %#v", spec.OutputSchema)
}
@@ -45,6 +45,7 @@ type AIWorkflowNodeSpecResponse struct {
Type string `json:"type"`
Title string `json:"title"`
Description string `json:"description"`
Icon string `json:"icon"`
RiskLevel workflowregistry.NodeRiskLevel `json:"riskLevel"`
Interruptible bool `json:"interruptible"`
RequiresConfirmationPredecessor bool `json:"requiresConfirmationPredecessor"`