diff --git a/frontend/src/components/comm/blocks/AgentResultBlock.tsx b/frontend/src/components/comm/blocks/AgentResultBlock.tsx new file mode 100644 index 0000000..995adc3 --- /dev/null +++ b/frontend/src/components/comm/blocks/AgentResultBlock.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import type { MessageBlock } from '@/store/commStore'; +import { Bot, CheckCircle, XCircle, Loader2 } from 'lucide-react'; + +interface AgentResultBlockProps { + block: MessageBlock; +} + +const AgentResultBlock: React.FC = ({ block }) => { + const { agent_name, status, result, run_id } = block.block_data; + const statusIcon = status === 'completed' ? : status === 'failed' ? : ; + return ( +
+
+ + {agent_name || 'Agent'} + {statusIcon} + {status} +
+ {result &&

{result}

} + {run_id &&

Run: {run_id.slice(0, 8)}

} +
+ ); +}; +export default AgentResultBlock; diff --git a/frontend/src/components/comm/blocks/ApprovalRequestBlock.tsx b/frontend/src/components/comm/blocks/ApprovalRequestBlock.tsx new file mode 100644 index 0000000..e9de1ff --- /dev/null +++ b/frontend/src/components/comm/blocks/ApprovalRequestBlock.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import type { MessageBlock } from '@/store/commStore'; +import { ShieldCheck, Check, X } from 'lucide-react'; + +interface ApprovalRequestBlockProps { + block: MessageBlock; +} + +const ApprovalRequestBlock: React.FC = ({ block }) => { + const { title, description, approval_id, status } = block.block_data; + return ( +
+
+ + {title || 'Approval Required'} + {status && {status}} +
+ {description &&

{description}

} + {status === 'pending' && ( +
+ + +
+ )} + {approval_id &&

ID: {approval_id.slice(0, 8)}

} +
+ ); +}; +export default ApprovalRequestBlock; diff --git a/frontend/src/components/comm/blocks/BlockRenderer.tsx b/frontend/src/components/comm/blocks/BlockRenderer.tsx index e93fd70..dc1f43c 100644 --- a/frontend/src/components/comm/blocks/BlockRenderer.tsx +++ b/frontend/src/components/comm/blocks/BlockRenderer.tsx @@ -9,6 +9,11 @@ import FileBlock from './FileBlock'; import ActionCardBlock from './ActionCardBlock'; import ContactCardBlock from './ContactCardBlock'; import MiniAppBlock from './MiniAppBlock'; +import AgentResultBlock from './AgentResultBlock'; +import ApprovalRequestBlock from './ApprovalRequestBlock'; +import TaskCardBlock from './TaskCardBlock'; +import WorkflowCardBlock from './WorkflowCardBlock'; +import KnowledgeCardBlock from './KnowledgeCardBlock'; interface BlockRendererProps { blocks: MessageBlock[]; @@ -52,6 +57,16 @@ const BlockRenderer: React.FC = ({ blocks }) => { return ; case 'miniapp': return ; + case 'agent_result': + return ; + case 'approval_request': + return ; + case 'task_card': + return ; + case 'workflow_card': + return ; + case 'knowledge_card': + return ; default: // Fallback for unknown block types return ( diff --git a/frontend/src/components/comm/blocks/KnowledgeCardBlock.tsx b/frontend/src/components/comm/blocks/KnowledgeCardBlock.tsx new file mode 100644 index 0000000..cb6350a --- /dev/null +++ b/frontend/src/components/comm/blocks/KnowledgeCardBlock.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import type { MessageBlock } from '@/store/commStore'; +import { BookOpen, ExternalLink } from 'lucide-react'; + +interface KnowledgeCardBlockProps { + block: MessageBlock; +} + +const KnowledgeCardBlock: React.FC = ({ block }) => { + const { title, summary, source_type, url, confidence } = block.block_data; + return ( +
+
+ + {title || 'Knowledge'} + {source_type && {source_type}} +
+ {summary &&

{summary}

} +
+ {confidence !== undefined && Confidence: {Math.round(confidence * 100)}%} + {url && Open} +
+
+ ); +}; +export default KnowledgeCardBlock; diff --git a/frontend/src/components/comm/blocks/TaskCardBlock.tsx b/frontend/src/components/comm/blocks/TaskCardBlock.tsx new file mode 100644 index 0000000..607a175 --- /dev/null +++ b/frontend/src/components/comm/blocks/TaskCardBlock.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import type { MessageBlock } from '@/store/commStore'; +import { CheckSquare, Clock, User } from 'lucide-react'; + +interface TaskCardBlockProps { + block: MessageBlock; +} + +const TaskCardBlock: React.FC = ({ block }) => { + const { title, assignee, due_date, priority, status, task_id } = block.block_data; + const priorityColor = priority === 'high' ? 'text-danger-600' : priority === 'medium' ? 'text-warning-600' : 'text-secondary-500'; + return ( +
+
+ + {title || 'Task'} + {status && {status}} +
+
+ {assignee && {assignee}} + {due_date && {due_date}} + {priority && ● {priority}} +
+ {task_id &&

Task: {task_id.slice(0, 8)}

} +
+ ); +}; +export default TaskCardBlock; diff --git a/frontend/src/components/comm/blocks/WorkflowCardBlock.tsx b/frontend/src/components/comm/blocks/WorkflowCardBlock.tsx new file mode 100644 index 0000000..5500f3e --- /dev/null +++ b/frontend/src/components/comm/blocks/WorkflowCardBlock.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import type { MessageBlock } from '@/store/commStore'; +import { Workflow as WorkflowIcon, CheckCircle, XCircle, Loader2 } from 'lucide-react'; + +interface WorkflowCardBlockProps { + block: MessageBlock; +} + +const WorkflowCardBlock: React.FC = ({ block }) => { + const { workflow_name, status, current_step, total_steps, instance_id } = block.block_data; + const statusIcon = status === 'completed' ? : status === 'failed' ? : ; + return ( +
+
+ + {workflow_name || 'Workflow'} + {statusIcon} + {status} +
+ {current_step !== undefined && total_steps !== undefined && ( +
+
+
+ )} +

Step {current_step || 0} / {total_steps || 0}

+ {instance_id &&

Instance: {instance_id.slice(0, 8)}

} +
+ ); +}; +export default WorkflowCardBlock; diff --git a/frontend/src/components/comm/blocks/index.ts b/frontend/src/components/comm/blocks/index.ts index 540aeb2..fe71a02 100644 --- a/frontend/src/components/comm/blocks/index.ts +++ b/frontend/src/components/comm/blocks/index.ts @@ -8,3 +8,8 @@ export { default as FileBlock } from './FileBlock'; export { default as ActionCardBlock } from './ActionCardBlock'; export { default as ContactCardBlock } from './ContactCardBlock'; export { default as MiniAppBlock } from './MiniAppBlock'; +export { default as AgentResultBlock } from './AgentResultBlock'; +export { default as ApprovalRequestBlock } from './ApprovalRequestBlock'; +export { default as TaskCardBlock } from './TaskCardBlock'; +export { default as WorkflowCardBlock } from './WorkflowCardBlock'; +export { default as KnowledgeCardBlock } from './KnowledgeCardBlock';