PluginProbe
Extendify / 3.0.6
Extendify v3.0.6
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 / state / workflows.js

workflows.js in Extendify 3.0.6, at src/Agent/state/workflows.js

153 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { isChangeSiteDesignWorkflowAvailable } from '@agent/lib/util';
2 import changeSiteDesignWorkflow from '@agent/workflows/theme/change-site-design';
3 import variationsWorkflow from '@agent/workflows/theme/change-theme-variation';
4 import { workflows } from '@agent/workflows/workflows';
5 import { deepMerge } from '@shared/lib/utils';
6 import apiFetch from '@wordpress/api-fetch';
7 import { create } from 'zustand';
8 import { devtools, persist } from 'zustand/middleware';
9
10 const onboarding = window.extAgentData.chatHistory?.length === 0;
11 const agentResponse = isChangeSiteDesignWorkflowAvailable()
12 ? changeSiteDesignWorkflow.example?.agentResponse
13 : variationsWorkflow.example?.agentResponse;
14 const onboardingToolProps = {
15 ...agentResponse.whenFinishedTool,
16 agentResponse,
17 };
18
19 // Used to check case-insensitive matches for workflow examples
20 const collator = new Intl.Collator(undefined, {
21 sensitivity: 'base',
22 usage: 'search',
23 });
24
25 const state = (set, get) => ({
26 workflow: null,
27 // Data for the tool component that shows up at the end of a workflow
28 whenFinishedToolProps: null,
29 block: null, // data-extendify-agent-block-id + details about the block
30 setBlock: (block) => set({ block, blockCode: null }),
31 // Used as "previousContent" in workflows that need it
32 blockCode: null,
33 setBlockCode: (blockCode) => set({ blockCode }),
34 domToolEnabled: false,
35 setDomToolEnabled: (enabled) => {
36 if (get().block) return; // can't disable if a block is set
37 set({ domToolEnabled: enabled });
38 },
39 getWorkflow: () => {
40 const curr = get().workflow;
41 // Workflows may define a "parent" workflow via templateId
42 const currId = curr?.templateId || curr?.id;
43 const wf = workflows.find(({ id }) => id === currId);
44 if (!wf?.id) return curr || null;
45 return { ...deepMerge(curr, wf || {}), id: curr?.id };
46 },
47 getWorkflowByExample: (example) => {
48 const wf = workflows.find(
49 ({ example: ex }) => collator.compare(ex?.text, example) === 0,
50 );
51 if (!wf?.id) return null;
52 return wf;
53 },
54 // Gets the workflows available to the user
55 // TODO: maybe we need to have a way to include a
56 // workflow regardless of the block being active?
57 getAvailableWorkflows: () => {
58 const wfs = workflows.filter(({ available }) => available());
59 // If a block is set, only include those with 'block'
60 const blockWorkflows = wfs.filter(({ requires }) =>
61 requires?.includes('block'),
62 );
63 if (get().block) return blockWorkflows;
64 // otherwise remove all of the above
65 return wfs.filter(({ id }) => !blockWorkflows.some((w) => w.id === id));
66 },
67 getWorkflowsByFeature: ({ requires } = {}) => {
68 if (!requires) return workflows.filter(({ available }) => available());
69 // e.g. requires: ['block']
70 return workflows.filter(
71 ({ available, requires: workflowRequires }) =>
72 available() &&
73 (!requires || workflowRequires?.some((s) => requires.includes(s))),
74 );
75 },
76 workflowData: null,
77 // This is the history of the results
78 // { answerId: '', canceled: false, reason: '', error: false, completed: false, whenFinishedTool: null }[]
79 workflowHistory: window.extAgentData?.workflowHistory || [],
80 addWorkflowResult: (data) => {
81 const workflowId = get().workflow?.id;
82
83 if (data.status === 'completed') {
84 set((state) => {
85 const max = Math.max(0, state.workflowHistory.length - 10);
86
87 return {
88 workflowHistory: [
89 { workflowId, ...data },
90 ...state.workflowHistory.toSpliced(0, max),
91 ],
92 };
93 });
94 }
95
96 if (!workflowId) return;
97 // Persist it to the server
98 const path = '/extendify/v1/agent/workflows';
99 apiFetch({
100 method: 'POST',
101 keepalive: true,
102 path,
103 data: { workflowId, ...data },
104 });
105 },
106 mergeWorkflowData: (data) => {
107 set((state) => {
108 if (!state.workflowData) return { workflowData: data };
109 return {
110 workflowData: { ...state.workflowData, ...data },
111 };
112 });
113 },
114 setWorkflow: (workflow) =>
115 set({
116 workflow: workflow
117 ? { ...workflow, startingPage: window.location.href }
118 : null,
119 // If a block is selected, add it to the workflow data
120 // previousContent is named this way for legacy reasons
121 workflowData: get().blockCode
122 ? { previousContent: get().blockCode }
123 : null,
124 whenFinishedToolProps: null,
125 }),
126 setWhenFinishedToolProps: (whenFinishedToolProps) =>
127 set({ whenFinishedToolProps }),
128 });
129
130 export const useWorkflowStore = create()(
131 persist(devtools(state, { name: 'Extendify Agent Workflows' }), {
132 name: `extendify-agent-workflows-${window.extSharedData.siteId}`,
133 merge: (persistedState, currentState) => {
134 // if we are in onboarding mode, add the starting workflow
135 if (onboarding) {
136 return {
137 ...currentState,
138 ...persistedState,
139 workflow: isChangeSiteDesignWorkflowAvailable()
140 ? changeSiteDesignWorkflow
141 : variationsWorkflow,
142 whenFinishedToolProps: onboardingToolProps,
143 };
144 }
145 return { ...currentState, ...persistedState };
146 },
147 partialize: (state) => {
148 const { block, workflowHistory, ...rest } = state;
149 return { ...rest };
150 },
151 }),
152 );
153