PluginProbe
Extendify / 2.2.0
Extendify v2.2.0
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 0.7.0 All 126 releases
extendify / src / Agent / api.js

api.js in Extendify 2.2.0, at src/Agent/api.js

190 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { AI_HOST } from '@constants';
2 import { useChatStore } from '@agent/state/chat';
3 import { useGlobalStore } from '@agent/state/global';
4 import { useWorkflowStore } from '@agent/state/workflows';
5 import { tools } from '@agent/workflows/workflows';
6
7 const extraBody = {
8 ...Object.fromEntries(
9 Object.entries(window.extSharedData).filter(([key]) =>
10 // Optionally add items to request body
11 [
12 'partnerId',
13 'devbuild',
14 'version',
15 'siteId',
16 'wpLanguage',
17 'wpVersion',
18 'siteProfile',
19 ].includes(key),
20 ),
21 ),
22 };
23
24 const extra = () => {
25 const { x, y, width, height } = useGlobalStore.getState();
26 return {
27 userAgent: window?.navigator?.userAgent,
28 vendor: window?.navigator?.vendor || 'unknown',
29 platform:
30 window?.navigator?.userAgentData?.platform ||
31 window?.navigator?.platform ||
32 'unknown',
33 mobile: window?.navigator?.userAgentData?.mobile,
34 width: window.innerWidth,
35 height: window.innerHeight,
36 screenHeight: window.screen.height,
37 screenWidth: window.screen.width,
38 orientation: window.screen.orientation?.type,
39 touchSupport: 'ontouchstart' in window || navigator.maxTouchPoints > 0,
40 agentUI: { x, y, width, height },
41 };
42 };
43
44 export const pickWorkflow = async ({ workflows, options }) => {
45 const { failedWorkflows, context } = window.extAgentData;
46 const failed = failedWorkflows ?? new Set();
47 const filteredWorkflows = workflows.filter((wf) => !failed.has(wf.id));
48
49 const { workflowHistory: pastWorkflows, block } = useWorkflowStore.getState();
50 const messages = useChatStore.getState().getMessagesForAI();
51 const response = await fetch(`${AI_HOST}/api/agent/find-agent`, {
52 method: 'POST',
53 headers: { 'Content-Type': 'application/json' },
54 signal: options?.signal,
55 body: JSON.stringify({
56 ...extraBody,
57 workflows: filteredWorkflows,
58 workflowHistory: pastWorkflows
59 .filter(Boolean)
60 .slice(0, 5)
61 .filter((h) => h.summary)
62 .map((h) => h.summary),
63 previousAgentName: pastWorkflows.at(0)?.agentName,
64 context,
65 agentContext: window.extAgentData.agentContext,
66 messages: messages.slice(-5),
67 hasBlock: Boolean(block), // todo: remove this
68 blockDetails: block,
69 ...options,
70 extra: extra(),
71 }),
72 });
73
74 if (!response.ok) {
75 digest({
76 caller: 'pick-workflow',
77 error: {
78 name: response.statusText,
79 messages: response.statusMessage,
80 },
81 });
82 const error = new Error('Bad response from server');
83 error.response = response;
84 throw error;
85 }
86 return await response.json();
87 };
88
89 export const handleWorkflow = async ({ workflow, workflowData, options }) => {
90 const messages = useChatStore.getState().getMessagesForAI();
91 const response = await fetch(`${AI_HOST}/api/agent/handle-workflow`, {
92 method: 'POST',
93 headers: { 'Content-Type': 'application/json' },
94 signal: options?.signal,
95 body: JSON.stringify({
96 ...extraBody,
97 workflow,
98 workflowData,
99 messages: messages,
100 context: window.extAgentData.context,
101 agentContext: window.extAgentData.agentContext,
102 extra: extra(),
103 }),
104 }).catch((error) => {
105 throw error;
106 });
107
108 if (!response.ok) throw new Error('Bad response from server');
109 return await response.json();
110 };
111
112 export const rateAnswer = ({ answerId, rating }) =>
113 fetch(`${AI_HOST}/api/agent/rate-workflow`, {
114 method: 'POST',
115 headers: { 'Content-Type': 'application/json' },
116 body: JSON.stringify({ answerId, rating }),
117 }).catch((error) =>
118 digest({
119 caller: 'rateAnswer',
120 error,
121 extra: { answerId, rating },
122 }),
123 );
124
125 export const callTool = async ({ tool, inputs }) => {
126 if (!tools[tool]) throw new Error(`Tool ${tool} not found`);
127 return await tools[tool](inputs);
128 };
129
130 export const digest = ({ error, sessionId, caller, additional = {} }) => {
131 if (Boolean(extraBody?.devbuild) === true) return;
132
133 const errorMessage = () => {
134 if (error.response && error.response.statusText) {
135 return (
136 error.response?.statusText || error.response.message || 'Unknown error'
137 );
138 }
139 return typeof error === 'string'
140 ? error
141 : error?.message || 'Unknown error';
142 };
143
144 const errorData = {
145 message: errorMessage(),
146 name: error?.name,
147 };
148
149 return fetch(`${AI_HOST}/api/agent/digest`, {
150 method: 'POST',
151 keepalive: true,
152 headers: { 'Content-Type': 'application/json' },
153 body: JSON.stringify({
154 ...extraBody,
155 phpVersion: window.extSharedData?.phpVersion,
156 sessionId,
157 error: errorData,
158 browser: {
159 userAgent: window.navigator?.userAgent,
160 vendor: window.navigator?.vendor,
161 platform: window.navigator?.platform,
162 width: window.innerWidth,
163 height: window.innerHeight,
164 touchSupport: 'ontouchstart' in window || navigator.maxTouchPoints > 0,
165 },
166 caller,
167 ...additional,
168 extra: extra(),
169 }),
170 }).catch(() => {});
171 };
172
173 export const recordAgentActivity = ({ action, sessionId, value = {} }) => {
174 if (!sessionId) {
175 return Promise.resolve(null);
176 }
177
178 return fetch(`${AI_HOST}/api/agent/activities`, {
179 keepalive: true,
180 method: 'POST',
181 headers: { 'Content-Type': 'application/json' },
182 body: JSON.stringify({
183 ...extraBody,
184 action,
185 sessionId,
186 value,
187 }),
188 });
189 };
190