PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Agent / components / messages / AgentMessage.jsx

AgentMessage.jsx in Extendify 3.2.1, at src/Agent/components/messages/AgentMessage.jsx

117 lines 3.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { recordAgentActivity } from '@agent/api';
2 import { AnimateChunks } from '@agent/components/messages/AnimateChunks';
3 import { ReplyOptions } from '@agent/components/ReplyOptions';
4 import { magic } from '@agent/icons';
5 import pageTours from '@agent/lib/page-tours';
6 import tours from '@agent/tours/tours';
7 import { SingleTour } from '@agent/workflows/misc/components/ToursList';
8 import { decodeEntities } from '@wordpress/html-entities';
9 import { __ } from '@wordpress/i18n';
10 import { cog, Icon, lifesaver, pencil, styles } from '@wordpress/icons';
11 import ReactMarkdown from 'react-markdown';
12
13 const availableTours = Object.values(tours);
14 const adminPages = window.extAgentData.agentContext?.availableAdminPages || [];
15 const agentSuggestions =
16 Object.fromEntries(
17 adminPages.map((page) => [
18 page,
19 {
20 label: __('Take me there', 'extendify-local'),
21 tour:
22 availableTours.find((tour) => tour.id === pageTours[page]) ?? null,
23 },
24 ]),
25 ) || {};
26
27 const agentIcons = {
28 agent1: lifesaver,
29 agent2: styles,
30 agent3: pencil,
31 agent4: cog,
32 };
33
34 export const AgentMessage = ({ message, animate, active }) => {
35 const {
36 content,
37 role,
38 pageSuggestion,
39 qaSuggestions,
40 agent,
41 sessionId = 'not-set',
42 } = message.details;
43 const containsCodeBlock = /```[\s\S]*?```/.test(content);
44 const blocks = containsCodeBlock
45 ? [decodeEntities(content ?? '')]
46 : decodeEntities(content ?? '').split(/\n{2,}/);
47
48 // Check if the pageSuggestion matches any key in agentSuggestions
49 const agentSuggestionKey = Object.keys(agentSuggestions).find((k) =>
50 pageSuggestion?.startsWith(k),
51 );
52 const agentSuggestion = agentSuggestions[agentSuggestionKey] || {};
53
54 return (
55 <div
56 data-agent-message-role={role}
57 className="flex w-full items-start gap-2.5 px-2.5 py-2"
58 >
59 <div className="w-7 shrink-0">
60 {agent?.avatar ? (
61 <img className="mt-px" src={agent.avatar} alt={agent.name} />
62 ) : (
63 <Icon
64 className="-mt-0.5 fill-gray-900"
65 icon={agentIcons[agent?.id] ?? magic}
66 size={28}
67 />
68 )}
69 </div>
70 <div className="flex min-w-0 flex-1 flex-col gap-4">
71 <div className="extendify-agent-markdown w-full">
72 {animate ? (
73 <AnimateChunks words={blocks} delay={0.1} duration={0.35} />
74 ) : (
75 <ReactMarkdown>{decodeEntities(content)}</ReactMarkdown>
76 )}
77 </div>
78 {agentSuggestion?.label ? (
79 <div>
80 <a
81 onClick={() => {
82 recordAgentActivity({
83 sessionId,
84 action: 'take_me_there_click',
85 value: { pageSuggestion },
86 });
87 }}
88 href={`${window.extSharedData.adminUrl}${pageSuggestion}`}
89 className="rounded-sm border border-design-main bg-design-main p-2 text-sm text-white no-underline hover:opacity-90"
90 >
91 {agentSuggestion.label}
92 </a>
93 </div>
94 ) : null}
95 {agentSuggestion?.tour && (
96 <div>
97 <SingleTour tour={agentSuggestion.tour} />
98 </div>
99 )}
100 {/* An empty array still renders — it's the agent asking with no drafts. */}
101 {active && Array.isArray(qaSuggestions) ? (
102 <ReplyOptions
103 options={qaSuggestions}
104 onSubmit={(message) =>
105 window.dispatchEvent(
106 new CustomEvent('extendify-agent:chat-submit', {
107 detail: { message },
108 }),
109 )
110 }
111 />
112 ) : null}
113 </div>
114 </div>
115 );
116 };
117