Major refactoring cleanup: - Add new controller architecture (class-controller-*.php) - Add new settings-v2 UI (views/settings-v2/) - Add new CSS architecture (agentic-sidebar.css, tokens) - Add esbuild build pipeline (scripts/build.js, package.json) - Add composer dependencies (vendor/) - Add frontend src directory (assets/js/src/index.jsx) - Add documentation files - Remove old/obsolete files (class-settings.php, old CSS) This commits all pending changes from previous refactoring efforts.
346 lines
8.3 KiB
Markdown
346 lines
8.3 KiB
Markdown
# WP Agentic Writer - Migration Guide
|
|
|
|
**Source:** `assets/js/sidebar.js` (12,363 lines)
|
|
**Goal:** 1:1 mechanical translation
|
|
|
|
---
|
|
|
|
## The Migration is Mechanical
|
|
|
|
1. Copy lines X-Y from `sidebar.js`
|
|
2. Convert `wp.element.createElement()` to JSX
|
|
3. Done
|
|
|
|
---
|
|
|
|
## JSX Conversion Rules
|
|
|
|
```jsx
|
|
// sidebar.js (verbatim copy)
|
|
wp.element.createElement('div', {
|
|
className: 'wpaw-status-icon-btn',
|
|
onClick: handleClick,
|
|
style: { display: 'flex', alignItems: 'center' }
|
|
}, 'text');
|
|
|
|
// Convert to JSX
|
|
<div
|
|
className="wpaw-status-icon-btn"
|
|
onClick={handleClick}
|
|
style={{ display: 'flex', alignItems: 'center' }}
|
|
>
|
|
text
|
|
</div>
|
|
```
|
|
|
|
| sidebar.js | JSX |
|
|
|-----------|-----|
|
|
| `{ key: value }` | `{ value }` |
|
|
| `{ className: 'foo' }` | `className="foo"` |
|
|
| `{ style: { x: y } }` | `style={{ x: y }}` |
|
|
| `null` children | `null` |
|
|
|
|
---
|
|
|
|
## Phase 1: ENTRY POINT
|
|
|
|
### `src/index.jsx` (NEW)
|
|
```jsx
|
|
import { createElement } from "@wordpress/element";
|
|
import { registerPlugin } from "@wordpress/plugins";
|
|
import { PluginSidebar, PluginSidebarMoreMenuItem } from "@wordpress/edit-post";
|
|
import { useSelect } from "@wordpress/data";
|
|
import { AgenticWriterSidebar } from "./components/Sidebar";
|
|
|
|
const pluginIcon = createElement("img", {
|
|
src: (window.wpAgenticWriter?.pluginUrl || "") + "/assets/img/icon.svg",
|
|
alt: "WP Agentic Writer",
|
|
style: { width: "20px", height: "20px" },
|
|
});
|
|
|
|
function WPAWPlugin() {
|
|
const postId = useSelect(
|
|
(select) => select("core/editor")?.getCurrentPostId() || 0,
|
|
[]
|
|
);
|
|
|
|
return createElement(
|
|
createElement.Fragment,
|
|
null,
|
|
createElement(PluginSidebarMoreMenuItem, {
|
|
target: "wp-agentic-writer",
|
|
icon: pluginIcon,
|
|
}, "WP Agentic Writer"),
|
|
createElement(PluginSidebar, {
|
|
name: "wp-agentic-writer",
|
|
title: "WP Agentic Writer",
|
|
icon: pluginIcon,
|
|
}, createElement(AgenticWriterSidebar, { postId }))
|
|
);
|
|
}
|
|
|
|
registerPlugin("wp-agentic-writer", {
|
|
icon: pluginIcon,
|
|
render: WPAWPlugin,
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 2: MAIN COMPONENT (Keep as Monolith First)
|
|
|
|
### `src/components/Sidebar.jsx`
|
|
**Lines from sidebar.js: L38 - L12363**
|
|
|
|
Copy the entire `AgenticWriterSidebar` component verbatim, then convert createElement to JSX.
|
|
|
|
---
|
|
|
|
## Phase 3: Extract Helpers (Pure Functions)
|
|
|
|
After main component works, extract these as standalone modules:
|
|
|
|
### `src/helpers/logging.js`
|
|
**Lines: L17-136**
|
|
- `formatAiErrorMessage()`
|
|
|
|
### `src/helpers/api.js`
|
|
**Lines: L380-490, L511-538, L540-549, L1195-1562, L1782-1837, L1890-2024, L2074-2207, L2301-2397, L2398-2514, L3633-3696**
|
|
|
|
Functions:
|
|
- `savePostConfig()` L402-447
|
|
- `saveWritingState()` L511-538
|
|
- `persistWritingStatePatch()` L540-549
|
|
- `runSeoAudit()` L1195-1268
|
|
- `generateMetaDescription()` L1460-1562
|
|
- `persistSessionMessages()` L1782-1837
|
|
- `acquireSessionLock()` L1890-1925
|
|
- `releaseSessionLock()` L1927-1946
|
|
- `loadChatHistory()` L2074-2207
|
|
- `loadPostSessions()` L2301-2397
|
|
- `openSessionById()` L2398-2514
|
|
- `loadSectionBlocks()` L3633-3673
|
|
- `saveSectionBlocks()` L3674-3696
|
|
|
|
### `src/helpers/session.js`
|
|
**Lines: L1640-1753, L1755-1883, L2043-2207, L2301-2514, L8830-9002**
|
|
|
|
Functions:
|
|
- `updateSnapshot()` L1640-1648
|
|
- `sanitizeMessagesForStorage()` L1717-1753
|
|
- `hydrateSessionStateFromMessages()` L1755-1780
|
|
- `flushOnUnload()` L1847-1883
|
|
- `loadChatHistory()` L2074-2207
|
|
- `loadPostSessions()` L2301-2397
|
|
- `openSessionById()` L2398-2514
|
|
- `startNewConversation()` L8830-8915
|
|
- `deleteConversationSession()` L8917-8958
|
|
- `getSessionDisplayTitle()` L8960-8983
|
|
|
|
### `src/helpers/editor.js`
|
|
**Lines: L753-811, L843-968, L1020-1028**
|
|
|
|
Functions:
|
|
- `captureEditorSnapshot()` L753-763
|
|
- `pushUndoSnapshot()` L765-774
|
|
- `undoLastAiOperation()` L776-811
|
|
- `blockEditorDispatch()` L843
|
|
- `shouldBlockEditorInput()` L927-943
|
|
- `keydownHandler()` L945-960
|
|
- `blockMutationEvent()` L962-968
|
|
- `toTextValue()` L1020-1028
|
|
|
|
### `src/helpers/timeline.js`
|
|
**Lines: L586-673**
|
|
|
|
Functions:
|
|
- `updateOrCreateTimelineEntry()` L637-659
|
|
- `addActivityTimeline()` L660-673
|
|
|
|
### `src/helpers/operations.js`
|
|
**Lines: L674-750**
|
|
|
|
Functions:
|
|
- `setActiveOperationState()` L674-682
|
|
- `beginAgentOperation()` L683-691
|
|
- `finishAgentOperation()` L692-700
|
|
- `markActiveOperationStopping()` L701-721
|
|
- `requestRefineAllConfirmation()` L729-742
|
|
- `resolveRefineAllConfirmation()` L743-750
|
|
|
|
### `src/helpers/keywords.js`
|
|
**Lines: L1072-1157, L4097-4155**
|
|
|
|
Functions:
|
|
- `handleFocusKeywordChange()` L1072-1078
|
|
- `handleKeywordSelect()` L1080-1087
|
|
- `extractFocusKeywordSuggestions()` L1090-1135
|
|
- `addFocusKeywordSuggestions()` L1154-1157
|
|
- `suggestKeywordsFromPlan()` L4097-4155
|
|
|
|
### `src/helpers/seo.js`
|
|
**Lines: L1195-1347**
|
|
|
|
Functions:
|
|
- `runSeoAudit()` L1195-1268
|
|
- `buildSeoAuditFixInstruction()` L1270-1308
|
|
- `getSeoFixKey()` L1309-1310
|
|
- `buildAuditRefinementContext()` L1329-1347
|
|
|
|
### `src/helpers/refinement.js`
|
|
**Lines: L1349-1458, L2570-2689, L4954-5279**
|
|
|
|
Functions:
|
|
- `handleSeoAuditFix()` L1349-1458
|
|
- `handleTitleRefinement()` L2570-2689
|
|
- `reformatBlocks()` L4954-5056
|
|
- `applyEditPlan()` L5143-5240
|
|
- `cancelEditPlan()` L5241-5279
|
|
|
|
### `src/helpers/blocks.js`
|
|
**Lines: L4871-5050, L5363-5420**
|
|
|
|
Functions:
|
|
- `createBlocksFromSerialized()` L4871-4953
|
|
- `getRefineableBlocks()` L5363-5390
|
|
- `getListItemBlocks()` L5391-5420
|
|
|
|
### `src/helpers/blocks-context.js`
|
|
**Lines: L5443-5622**
|
|
|
|
Functions:
|
|
- `getBlockContentForContext()` L5443-5453
|
|
- `getHeadingContextForBlock()` L5454-5470
|
|
- `getNearbyParagraphContext()` L5471-5494
|
|
- `getContextFromMentions()` L5495-5503
|
|
- `selectLikelySlangBlocks()` L5521-5533
|
|
- `getAiSlopFindingsForBlock()` L5538-5589
|
|
- `buildContextBlocksForRefinement()` L5607-5622
|
|
- `buildRefinementDiagnosis()` L5623-5703
|
|
|
|
### `src/helpers/plan.js`
|
|
**Lines: L3474-3891, L4321-4767**
|
|
|
|
Functions:
|
|
- `createBlockFromPlan()` L3474-3534
|
|
- `normalizePlanActions()` L3535-3543
|
|
- `buildPlanPreviewItem()` L3544-3604
|
|
- `upsertSectionBlock()` L3612-3622
|
|
- `removeSectionBlock()` L3623-3632
|
|
- `findBestPlanSectionMatch()` L3744-3828
|
|
- `updatePlanSectionStatus()` L3829-3851
|
|
- `findSectionInsertIndex()` L3852-3891
|
|
- `executePlanFromCard()` L4321-4767
|
|
|
|
### `src/helpers/agent.js`
|
|
**Lines: L3907-4320**
|
|
|
|
Functions:
|
|
- `summarizeChatHistory()` L3907-3954
|
|
- `detectUserIntent()` L3957-4005
|
|
- `buildOptimizedContext()` L4008-4025
|
|
- `classifyAgentIntent()` L4222-4260
|
|
- `decideAgentAction()` L4261-4320
|
|
- `getPlanRuntimeSummary()` L4199-4218
|
|
|
|
### `src/helpers/mentions.js`
|
|
**Lines: L2516-2569, L5705-5797, L6454-6605, L6613-6757**
|
|
|
|
Functions:
|
|
- `resolveStreamTarget()` L2516-2526
|
|
- `normalizeMentionToken()` L2527-2536
|
|
- `extractMentionsFromText()` L2537-2550
|
|
- `resolveBlockMentions()` L5705-5797
|
|
- `getMentionOptions()` L6456-6578
|
|
- `handleInsertMention()` L6581-6605
|
|
- `insertMention()` L6702-6726
|
|
|
|
### `src/helpers/commands.js`
|
|
**Lines: L2688-2758**
|
|
|
|
Functions:
|
|
- `parseInsertCommand()` L2690-2712
|
|
- `getSlashOptions()` L2713-2747
|
|
- `getBlockIndex()` L2748-2758
|
|
|
|
### `src/helpers/chat.js`
|
|
**Lines: L6759-8054, L8057-8474**
|
|
|
|
Functions:
|
|
- `sendMessage()` L6759-8054 (the main chat function)
|
|
- `submitAnswers()` L8057-8474
|
|
|
|
### `src/helpers/markdown.js`
|
|
**Lines: L10007-10270**
|
|
|
|
Functions:
|
|
- `escapeHtml()` L10007-10014
|
|
- `inlineMarkdownToHtml()` L10015-10031
|
|
- `markdownToHtml()` L10032-10270
|
|
|
|
### `src/helpers/welcome.js`
|
|
**Lines: L1176-1192**
|
|
|
|
Functions:
|
|
- `handleWelcomeStart()` L1176-1192
|
|
|
|
### `src/helpers/retry.js`
|
|
**Lines: L3189-3257**
|
|
|
|
Functions:
|
|
- `retryLastGeneration()` L3189-3213
|
|
- `retryLastExecute()` L3214-3228
|
|
- `retryLastRefinement()` L3229-3257
|
|
|
|
---
|
|
|
|
## Phase 4: State Objects (Plain Objects, Not React State)
|
|
|
|
### `src/state/config.js`
|
|
**Lines: L163-222**
|
|
```js
|
|
const defaultPostConfig = {
|
|
article_length: 'medium',
|
|
language: 'auto',
|
|
tone: '',
|
|
audience: '',
|
|
experience_level: 'general',
|
|
include_images: true,
|
|
web_search: false,
|
|
default_mode: 'chat',
|
|
seo_focus_keyword: '',
|
|
focus_keyword: '',
|
|
seo_secondary_keywords: [],
|
|
seo_meta_description: '',
|
|
seo_enabled: false,
|
|
};
|
|
|
|
const applyProviderMetadata = (config, providerInfo) => { ... };
|
|
```
|
|
|
|
### `src/state/editor.js`
|
|
**Lines: L224-237**
|
|
```js
|
|
const isEditorLocked = false;
|
|
const isRefinementLocked = false;
|
|
const refiningBlockIds = [];
|
|
const refineAllConfirm = { isOpen: false, blockCount: 0, dontAskAgain: false };
|
|
```
|
|
|
|
---
|
|
|
|
## Extraction Order
|
|
|
|
1. [ ] Keep everything in `Sidebar.jsx` first
|
|
2. [ ] Verify build works
|
|
3. [ ] Then extract helpers one by one
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
- [ ] Build compiles
|
|
- [ ] Plugin loads in Gutenberg
|
|
- [ ] All buttons work
|
|
- [ ] No console errors
|