@actuate-media/cms-admin 0.56.2 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/__tests__/views/ai-settings.render.test.js +34 -0
  3. package/dist/__tests__/views/ai-settings.render.test.js.map +1 -1
  4. package/dist/actuate-admin.css +1 -1
  5. package/dist/components/AICoauthorBubbleMenu.d.ts.map +1 -1
  6. package/dist/components/AICoauthorBubbleMenu.js +5 -1
  7. package/dist/components/AICoauthorBubbleMenu.js.map +1 -1
  8. package/dist/components/BrandVoiceAlignmentBadge.d.ts +6 -0
  9. package/dist/components/BrandVoiceAlignmentBadge.d.ts.map +1 -0
  10. package/dist/components/BrandVoiceAlignmentBadge.js +11 -0
  11. package/dist/components/BrandVoiceAlignmentBadge.js.map +1 -0
  12. package/dist/components/CoauthorResultPopover.d.ts +5 -1
  13. package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
  14. package/dist/components/CoauthorResultPopover.js +35 -6
  15. package/dist/components/CoauthorResultPopover.js.map +1 -1
  16. package/dist/components/CommandPalette.d.ts.map +1 -1
  17. package/dist/components/CommandPalette.js +5 -1
  18. package/dist/components/CommandPalette.js.map +1 -1
  19. package/dist/components/seo/SeoEditorDrawer.d.ts.map +1 -1
  20. package/dist/components/seo/SeoEditorDrawer.js +43 -2
  21. package/dist/components/seo/SeoEditorDrawer.js.map +1 -1
  22. package/dist/components/ui/Badge.d.ts +1 -1
  23. package/dist/lib/brand-voice-client.d.ts +21 -0
  24. package/dist/lib/brand-voice-client.d.ts.map +1 -0
  25. package/dist/lib/brand-voice-client.js +27 -0
  26. package/dist/lib/brand-voice-client.js.map +1 -0
  27. package/dist/lib/coauthor-client.d.ts +2 -0
  28. package/dist/lib/coauthor-client.d.ts.map +1 -1
  29. package/dist/lib/coauthor-client.js +1 -0
  30. package/dist/lib/coauthor-client.js.map +1 -1
  31. package/dist/lib/seo-service.d.ts +12 -0
  32. package/dist/lib/seo-service.d.ts.map +1 -1
  33. package/dist/lib/seo-service.js +0 -10
  34. package/dist/lib/seo-service.js.map +1 -1
  35. package/dist/views/Settings.js +1 -1
  36. package/dist/views/Settings.js.map +1 -1
  37. package/dist/views/settings/AISettingsTab.d.ts +3 -1
  38. package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
  39. package/dist/views/settings/AISettingsTab.js +2 -2
  40. package/dist/views/settings/AISettingsTab.js.map +1 -1
  41. package/dist/views/settings/BrandVoiceCard.d.ts +39 -2
  42. package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -1
  43. package/dist/views/settings/BrandVoiceCard.js +215 -3
  44. package/dist/views/settings/BrandVoiceCard.js.map +1 -1
  45. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts +13 -0
  46. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts.map +1 -0
  47. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js +74 -0
  48. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js.map +1 -0
  49. package/dist/views/settings/brand-voice/BrandVoiceRulesSections.d.ts +7 -0
  50. package/dist/views/settings/brand-voice/BrandVoiceRulesSections.d.ts.map +1 -0
  51. package/dist/views/settings/brand-voice/BrandVoiceRulesSections.js +54 -0
  52. package/dist/views/settings/brand-voice/BrandVoiceRulesSections.js.map +1 -0
  53. package/dist/views/settings/useAiSettings.d.ts +32 -0
  54. package/dist/views/settings/useAiSettings.d.ts.map +1 -1
  55. package/dist/views/settings/useAiSettings.js +85 -3
  56. package/dist/views/settings/useAiSettings.js.map +1 -1
  57. package/package.json +2 -2
  58. package/src/__tests__/views/ai-settings.render.test.tsx +50 -0
  59. package/src/components/AICoauthorBubbleMenu.tsx +12 -0
  60. package/src/components/BrandVoiceAlignmentBadge.tsx +39 -0
  61. package/src/components/CoauthorResultPopover.tsx +62 -4
  62. package/src/components/CommandPalette.tsx +12 -0
  63. package/src/components/seo/SeoEditorDrawer.tsx +65 -1
  64. package/src/lib/brand-voice-client.ts +38 -0
  65. package/src/lib/coauthor-client.ts +4 -0
  66. package/src/lib/seo-service.ts +2 -0
  67. package/src/views/Settings.tsx +1 -1
  68. package/src/views/settings/AISettingsTab.tsx +13 -2
  69. package/src/views/settings/BrandVoiceCard.tsx +592 -76
  70. package/src/views/settings/brand-voice/BrandVoiceAlignmentPanel.tsx +205 -0
  71. package/src/views/settings/brand-voice/BrandVoiceRulesSections.tsx +321 -0
  72. package/src/views/settings/useAiSettings.ts +134 -3
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { useCallback, useEffect, useMemo, useState } from 'react';
3
+ import { defaultStructuredProfile, parseStructuredProfile, } from '@actuate-media/cms-core/brand-voice';
3
4
  import { cmsApi } from '../../lib/api.js';
4
5
  const EMPTY_BRAND_VOICE = {
5
6
  enabled: false,
@@ -8,6 +9,11 @@ const EMPTY_BRAND_VOICE = {
8
9
  audience: '',
9
10
  guidelines: '',
10
11
  sampleText: '',
12
+ document: '',
13
+ version: 1,
14
+ status: 'draft',
15
+ generatedFrom: [],
16
+ structured: defaultStructuredProfile(),
11
17
  };
12
18
  function formFromResponse(res) {
13
19
  return {
@@ -28,6 +34,13 @@ function formFromResponse(res) {
28
34
  audience: res.settings.brandVoice?.audience ?? '',
29
35
  guidelines: res.settings.brandVoice?.guidelines ?? '',
30
36
  sampleText: res.settings.brandVoice?.sampleText ?? '',
37
+ document: res.settings.brandVoice?.document ?? '',
38
+ version: res.settings.brandVoice?.version ?? 1,
39
+ status: res.settings.brandVoice?.status ?? 'draft',
40
+ generatedFrom: res.settings.brandVoice?.generatedFrom ?? [],
41
+ structured: res.settings.brandVoice?.document?.trim()
42
+ ? parseStructuredProfile(res.settings.brandVoice.document)
43
+ : defaultStructuredProfile(),
31
44
  },
32
45
  };
33
46
  }
@@ -45,7 +58,8 @@ function brandVoiceIsEmpty(bv) {
45
58
  !bv.tone.trim() &&
46
59
  !bv.audience.trim() &&
47
60
  !bv.guidelines.trim() &&
48
- !bv.sampleText.trim());
61
+ !bv.sampleText.trim() &&
62
+ !bv.document.trim());
49
63
  }
50
64
  export function useAiSettings(canEdit) {
51
65
  const [loading, setLoading] = useState(true);
@@ -59,6 +73,7 @@ export function useAiSettings(canEdit) {
59
73
  const [saveState, setSaveState] = useState('idle');
60
74
  const [saveError, setSaveError] = useState(null);
61
75
  const [busyProviderId, setBusyProviderId] = useState(null);
76
+ const [brandVoiceEditMode, setBrandVoiceEditMode] = useState('form');
62
77
  const [reloadKey, setReloadKey] = useState(0);
63
78
  const loadModels = useCallback(async () => {
64
79
  const res = await cmsApi('/ai/models');
@@ -135,6 +150,49 @@ export function useAiSettings(canEdit) {
135
150
  setForm((prev) => ({ ...prev, brandVoice: { ...prev.brandVoice, ...patch } }));
136
151
  setSaveState('idle');
137
152
  }, []);
153
+ const analyzeBrandVoice = useCallback(async (input) => {
154
+ if (!canEdit)
155
+ return { ok: false, error: 'You do not have permission to do this.' };
156
+ try {
157
+ const res = await cmsApi('/ai/brand-voice/analyze', {
158
+ method: 'POST',
159
+ body: JSON.stringify(input),
160
+ });
161
+ if (res.error)
162
+ return { ok: false, error: res.error };
163
+ if (!res.data?.draft)
164
+ return { ok: false, error: 'No draft profile was returned.' };
165
+ const structured = res.data.draft.document?.trim()
166
+ ? parseStructuredProfile(res.data.draft.document)
167
+ : defaultStructuredProfile();
168
+ return {
169
+ ok: true,
170
+ draft: { ...res.data.draft, structured },
171
+ sampleCount: res.data.sampleCount,
172
+ };
173
+ }
174
+ catch {
175
+ return { ok: false, error: 'Brand voice analysis failed.' };
176
+ }
177
+ }, [canEdit]);
178
+ const scoreBrandVoice = useCallback(async (input) => {
179
+ if (!canEdit)
180
+ return { ok: false, error: 'You do not have permission to do this.' };
181
+ try {
182
+ const res = await cmsApi('/ai/brand-voice/score', {
183
+ method: 'POST',
184
+ body: JSON.stringify(input),
185
+ });
186
+ if (res.error)
187
+ return { ok: false, error: res.error };
188
+ if (!res.data)
189
+ return { ok: false, error: 'No score was returned.' };
190
+ return { ok: true, result: res.data };
191
+ }
192
+ catch {
193
+ return { ok: false, error: 'Brand voice scoring failed.' };
194
+ }
195
+ }, [canEdit]);
138
196
  const budgetError = useMemo(() => {
139
197
  if (form.monthlyTokenLimit === '')
140
198
  return null;
@@ -159,8 +217,23 @@ export function useAiSettings(canEdit) {
159
217
  'audience',
160
218
  'guidelines',
161
219
  'sampleText',
220
+ 'document',
221
+ 'version',
222
+ 'status',
223
+ 'generatedFrom',
224
+ 'structured',
162
225
  ];
163
- if (bvKeys.some((k) => form.brandVoice[k] !== baseline.brandVoice[k]))
226
+ if (bvKeys.some((k) => {
227
+ if (k === 'generatedFrom') {
228
+ return (JSON.stringify(form.brandVoice.generatedFrom) !==
229
+ JSON.stringify(baseline.brandVoice.generatedFrom));
230
+ }
231
+ if (k === 'structured') {
232
+ return (JSON.stringify(form.brandVoice.structured) !==
233
+ JSON.stringify(baseline.brandVoice.structured));
234
+ }
235
+ return form.brandVoice[k] !== baseline.brandVoice[k];
236
+ }))
164
237
  return true;
165
238
  return form.features.some((f, i) => {
166
239
  const base = baseline.features[i];
@@ -195,6 +268,11 @@ export function useAiSettings(canEdit) {
195
268
  audience: form.brandVoice.audience,
196
269
  guidelines: form.brandVoice.guidelines,
197
270
  sampleText: form.brandVoice.sampleText,
271
+ document: form.brandVoice.document,
272
+ version: form.brandVoice.version,
273
+ status: form.brandVoice.status,
274
+ generatedFrom: form.brandVoice.generatedFrom,
275
+ preferDocument: brandVoiceEditMode === 'document',
198
276
  },
199
277
  }),
200
278
  });
@@ -211,7 +289,7 @@ export function useAiSettings(canEdit) {
211
289
  setSaveState('error');
212
290
  setSaveError(err instanceof Error ? err.message : 'Failed to save AI settings.');
213
291
  }
214
- }, [canEdit, budgetError, form]);
292
+ }, [canEdit, budgetError, form, brandVoiceEditMode]);
215
293
  const reset = useCallback(() => {
216
294
  setForm(baseline);
217
295
  setSaveState('idle');
@@ -330,6 +408,10 @@ export function useAiSettings(canEdit) {
330
408
  toggleFeature,
331
409
  setFeatureModel,
332
410
  setBrandVoice,
411
+ analyzeBrandVoice,
412
+ scoreBrandVoice,
413
+ brandVoiceEditMode,
414
+ setBrandVoiceEditMode,
333
415
  dirty,
334
416
  budgetError,
335
417
  saveState,
@@ -1 +1 @@
1
- {"version":3,"file":"useAiSettings.js","sourceRoot":"","sources":["../../../src/views/settings/useAiSettings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAiSettings.js","sourceRoot":"","sources":["../../../src/views/settings/useAiSettings.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cms-admin",
3
- "version": "0.56.2",
3
+ "version": "0.57.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/actuate-media/actuatecms.git",
@@ -89,7 +89,7 @@
89
89
  "tailwindcss": "^4.0.0",
90
90
  "typescript": "^5.7.0",
91
91
  "vitest": "^4.1.0",
92
- "@actuate-media/cms-core": "0.76.1",
92
+ "@actuate-media/cms-core": "0.77.0",
93
93
  "@actuate-media/component-blocks": "0.2.1"
94
94
  },
95
95
  "scripts": {
@@ -103,6 +103,21 @@ const cmsApi = vi.fn(async (endpoint: string, options?: { method?: string }) =>
103
103
  if (endpoint === '/ai/models' && method === 'GET')
104
104
  return { data: { models: MODELS }, status: 200 }
105
105
  if (endpoint === '/ai/usage/summary') return { data: USAGE, status: 200 }
106
+ if (endpoint === '/ai/brand-voice/analyze' && method === 'POST') {
107
+ return {
108
+ data: {
109
+ draft: {
110
+ name: 'Acme Voice',
111
+ tone: 'confident, warm',
112
+ audience: 'B2B marketers',
113
+ guidelines: '- Do: lead with benefits',
114
+ sampleText: 'We help teams ship with clarity.',
115
+ },
116
+ sampleCount: 3,
117
+ },
118
+ status: 200,
119
+ }
120
+ }
106
121
  if (endpoint === '/ai/providers/p1/test' && method === 'POST') {
107
122
  return {
108
123
  data: {
@@ -278,6 +293,41 @@ describe('AISettingsTab', () => {
278
293
  expect(body.brandVoice).toMatchObject({ enabled: true, tone: 'confident, warm' })
279
294
  })
280
295
 
296
+ it('analyzes published content and drafts brand voice fields', async () => {
297
+ render(
298
+ <AISettingsTab
299
+ role="ADMIN"
300
+ config={{
301
+ collections: {
302
+ pages: { slug: 'pages', type: 'page', labels: { plural: 'Pages' } },
303
+ posts: { slug: 'posts', type: 'post', labels: { plural: 'Posts' } },
304
+ },
305
+ }}
306
+ />,
307
+ )
308
+ const region = await screen.findByRole('region', { name: 'Brand voice' })
309
+ fireEvent.click(within(region).getByRole('button', { name: 'Analyze & draft profile' }))
310
+
311
+ await waitFor(() =>
312
+ expect(cmsApi).toHaveBeenCalledWith(
313
+ '/ai/brand-voice/analyze',
314
+ expect.objectContaining({ method: 'POST' }),
315
+ ),
316
+ )
317
+
318
+ expect((within(region).getByLabelText('Tone') as HTMLInputElement).value).toBe(
319
+ 'confident, warm',
320
+ )
321
+ expect((within(region).getByLabelText('Name') as HTMLInputElement).value).toBe('Acme Voice')
322
+ })
323
+
324
+ it('shows export/import controls for the profile document', async () => {
325
+ render(<AISettingsTab role="ADMIN" />)
326
+ const region = await screen.findByRole('region', { name: 'Brand voice' })
327
+ expect(within(region).getByRole('button', { name: 'Export .md' })).toBeTruthy()
328
+ expect(within(region).getByRole('button', { name: 'Import .md' })).toBeTruthy()
329
+ })
330
+
281
331
  it('disables brand voice fields for non-admins', async () => {
282
332
  render(<AISettingsTab role="EDITOR" />)
283
333
  const region = await screen.findByRole('region', { name: 'Brand voice' })
@@ -11,6 +11,7 @@ import {
11
11
  type CoauthorAction,
12
12
  type ProofreadChange,
13
13
  } from '../lib/coauthor-client.js'
14
+ import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
14
15
  import { CoauthorResultPopover } from './CoauthorResultPopover.js'
15
16
 
16
17
  export interface AICoauthorBubbleMenuProps {
@@ -32,6 +33,7 @@ interface ResultState {
32
33
  after: string
33
34
  error?: string
34
35
  changes?: ProofreadChange[]
36
+ brandAlignment?: BrandAlignmentScoreResult
35
37
  from: number
36
38
  to: number
37
39
  }
@@ -97,6 +99,7 @@ export function AICoauthorBubbleMenu({ editor }: AICoauthorBubbleMenuProps) {
97
99
  loading: false,
98
100
  after: outcome.result.text,
99
101
  changes: outcome.result.changes,
102
+ brandAlignment: outcome.result.brandAlignment,
100
103
  error: undefined,
101
104
  }))
102
105
  setPendingAction(null)
@@ -120,6 +123,13 @@ export function AICoauthorBubbleMenu({ editor }: AICoauthorBubbleMenuProps) {
120
123
  }
121
124
  }, [state.after])
122
125
 
126
+ const handleAfterChange = useCallback(
127
+ (text: string, brandAlignment?: BrandAlignmentScoreResult) => {
128
+ setState((prev) => ({ ...prev, after: text, brandAlignment }))
129
+ },
130
+ [],
131
+ )
132
+
123
133
  const handleDiscard = useCallback(() => {
124
134
  setState(INITIAL)
125
135
  setPendingAction(null)
@@ -177,6 +187,8 @@ export function AICoauthorBubbleMenu({ editor }: AICoauthorBubbleMenuProps) {
177
187
  after={state.after}
178
188
  error={state.error}
179
189
  changes={state.changes}
190
+ brandAlignment={state.brandAlignment}
191
+ onAfterChange={handleAfterChange}
180
192
  applyLabel="Replace selection"
181
193
  onApply={handleApply}
182
194
  onCopy={handleCopy}
@@ -0,0 +1,39 @@
1
+ 'use client'
2
+
3
+ import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
4
+ import { brandAlignmentLabel, brandAlignmentTone } from '../lib/brand-voice-client.js'
5
+
6
+ export function BrandVoiceAlignmentBadge({
7
+ alignment,
8
+ compact = false,
9
+ }: {
10
+ alignment: BrandAlignmentScoreResult
11
+ compact?: boolean
12
+ }) {
13
+ const tone = brandAlignmentTone(alignment.score)
14
+ const label = brandAlignmentLabel(alignment.score)
15
+ const errorCount = alignment.issues.filter((i) => i.severity === 'error').length
16
+ const warningCount = alignment.issues.filter((i) => i.severity === 'warning').length
17
+
18
+ return (
19
+ <div
20
+ className="border-border bg-muted/40 inline-flex flex-wrap items-center gap-2 rounded-md border px-2.5 py-1.5 text-sm"
21
+ aria-label={`Brand voice score ${alignment.score} out of 100`}
22
+ >
23
+ <span className={`font-medium ${tone}`}>{alignment.score}/100</span>
24
+ <span className="text-muted-foreground">{label}</span>
25
+ {!compact && alignment.channel && (
26
+ <span className="text-muted-foreground text-xs">
27
+ · {alignment.channel.replace(/_/g, ' ')}
28
+ </span>
29
+ )}
30
+ {(errorCount > 0 || warningCount > 0) && (
31
+ <span className="text-muted-foreground text-xs">
32
+ · {errorCount > 0 ? `${errorCount} issue${errorCount === 1 ? '' : 's'}` : ''}
33
+ {errorCount > 0 && warningCount > 0 ? ', ' : ''}
34
+ {warningCount > 0 ? `${warningCount} warning${warningCount === 1 ? '' : 's'}` : ''}
35
+ </span>
36
+ )}
37
+ </div>
38
+ )
39
+ }
@@ -1,9 +1,13 @@
1
1
  'use client'
2
2
 
3
- import { useEffect, useRef } from 'react'
4
- import { Check, Copy, Loader2, Sparkles, X } from 'lucide-react'
3
+ import { useEffect, useRef, useState } from 'react'
4
+ import { Check, Copy, Loader2, Sparkles, Wand2, X } from 'lucide-react'
5
+ import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
5
6
  import type { CoauthorAction, ProofreadChange } from '../lib/coauthor-client.js'
6
7
  import { coauthorActionLabel } from '../lib/coauthor-client.js'
8
+ import { fixBrandVoiceContent } from '../lib/brand-voice-client.js'
9
+ import { BrandVoiceAlignmentBadge } from './BrandVoiceAlignmentBadge.js'
10
+ import { toast } from 'sonner'
7
11
 
8
12
  export interface CoauthorResultPopoverProps {
9
13
  open: boolean
@@ -13,6 +17,9 @@ export interface CoauthorResultPopoverProps {
13
17
  after: string
14
18
  error?: string
15
19
  changes?: ProofreadChange[]
20
+ brandAlignment?: BrandAlignmentScoreResult
21
+ /** Called when fix-to-brand updates the after text. */
22
+ onAfterChange?: (text: string, alignment?: BrandAlignmentScoreResult) => void
16
23
  /** Label for the apply target, e.g. "Apply to editor" or "Replace selection". */
17
24
  applyLabel?: string
18
25
  onApply: () => void
@@ -39,12 +46,15 @@ export function CoauthorResultPopover({
39
46
  after,
40
47
  error,
41
48
  changes,
49
+ brandAlignment,
50
+ onAfterChange,
42
51
  applyLabel,
43
52
  onApply,
44
53
  onCopy,
45
54
  onDiscard,
46
55
  }: CoauthorResultPopoverProps) {
47
56
  const dialogRef = useRef<HTMLDivElement>(null)
57
+ const [fixing, setFixing] = useState(false)
48
58
 
49
59
  useEffect(() => {
50
60
  if (!open) return
@@ -65,8 +75,35 @@ export function CoauthorResultPopover({
65
75
 
66
76
  if (!open) return null
67
77
 
68
- const applyDisabled = loading || !!error || after.length === 0
69
- const copyDisabled = loading || !!error || after.length === 0
78
+ const applyDisabled = loading || fixing || !!error || after.length === 0
79
+ const copyDisabled = loading || fixing || !!error || after.length === 0
80
+ const showFix =
81
+ !loading &&
82
+ !error &&
83
+ after.length > 0 &&
84
+ brandAlignment &&
85
+ brandAlignment.score < 85 &&
86
+ onAfterChange
87
+
88
+ async function handleFix() {
89
+ if (!onAfterChange || !after.trim()) return
90
+ setFixing(true)
91
+ try {
92
+ const res = await fixBrandVoiceContent({ content: after, channel: 'blog' })
93
+ if (!res.ok || !res.result) {
94
+ toast.error(res.error ?? 'Could not fix copy for brand voice.')
95
+ return
96
+ }
97
+ onAfterChange(res.result.text, res.result.afterScore)
98
+ toast.success(
99
+ res.result.usedAi
100
+ ? 'Copy revised to match brand voice.'
101
+ : 'Applied brand voice rule fixes.',
102
+ )
103
+ } finally {
104
+ setFixing(false)
105
+ }
106
+ }
70
107
 
71
108
  return (
72
109
  <div
@@ -162,6 +199,27 @@ export function CoauthorResultPopover({
162
199
  </div>
163
200
  )}
164
201
 
202
+ {brandAlignment && !loading && !error && (
203
+ <div className="border-border flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3">
204
+ <BrandVoiceAlignmentBadge alignment={brandAlignment} />
205
+ {showFix && (
206
+ <button
207
+ type="button"
208
+ onClick={handleFix}
209
+ disabled={fixing}
210
+ className="border-border bg-card text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm disabled:cursor-not-allowed disabled:opacity-50"
211
+ >
212
+ {fixing ? (
213
+ <Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden />
214
+ ) : (
215
+ <Wand2 className="h-3.5 w-3.5" aria-hidden />
216
+ )}
217
+ Fix to match brand voice
218
+ </button>
219
+ )}
220
+ </div>
221
+ )}
222
+
165
223
  <div className="border-border bg-muted flex items-center justify-end gap-2 border-t px-4 py-3">
166
224
  <button
167
225
  type="button"
@@ -31,6 +31,7 @@ import {
31
31
  type CoauthorAction,
32
32
  type ProofreadChange,
33
33
  } from '../lib/coauthor-client.js'
34
+ import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
34
35
  import {
35
36
  isAiSlashCommandInput,
36
37
  orderedAiActions,
@@ -116,6 +117,7 @@ interface AiResultState {
116
117
  after: string
117
118
  error?: string
118
119
  changes?: ProofreadChange[]
120
+ brandAlignment?: BrandAlignmentScoreResult
119
121
  /** Editor captured at submission time; null means clipboard-only. */
120
122
  target: Editor | null
121
123
  }
@@ -258,6 +260,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
258
260
  loading: false,
259
261
  after: outcome.result.text,
260
262
  changes: outcome.result.changes,
263
+ brandAlignment: outcome.result.brandAlignment,
261
264
  error: undefined,
262
265
  }))
263
266
  },
@@ -294,6 +297,13 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
294
297
  }
295
298
  }, [aiResult.after])
296
299
 
300
+ const handleAiAfterChange = useCallback(
301
+ (after: string, brandAlignment?: BrandAlignmentScoreResult) => {
302
+ setAiResult((prev) => ({ ...prev, after, brandAlignment }))
303
+ },
304
+ [],
305
+ )
306
+
297
307
  const handleAiDiscard = useCallback(() => {
298
308
  setAiResult(INITIAL_AI_RESULT)
299
309
  }, [])
@@ -314,6 +324,8 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
314
324
  after={aiResult.after}
315
325
  error={aiResult.error}
316
326
  changes={aiResult.changes}
327
+ brandAlignment={aiResult.brandAlignment}
328
+ onAfterChange={handleAiAfterChange}
317
329
  applyLabel={aiResult.target ? 'Apply to editor' : 'Copy to clipboard'}
318
330
  onApply={handleAiApply}
319
331
  onCopy={handleAiCopy}
@@ -1,8 +1,9 @@
1
1
  'use client'
2
2
 
3
3
  import { cloneElement, isValidElement, useEffect, useId, useState, type ReactElement } from 'react'
4
- import { Sparkles, Check } from 'lucide-react'
4
+ import { Sparkles, Check, Loader2, Wand2 } from 'lucide-react'
5
5
  import { toast } from 'sonner'
6
+ import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
6
7
  import {
7
8
  fetchSeoContentRecord,
8
9
  updateSeoFields,
@@ -11,6 +12,8 @@ import {
11
12
  type SeoFieldPayload,
12
13
  type LlmsInclude,
13
14
  } from '../../lib/seo-service.js'
15
+ import { fixBrandVoiceContent } from '../../lib/brand-voice-client.js'
16
+ import { BrandVoiceAlignmentBadge } from '../BrandVoiceAlignmentBadge.js'
14
17
  import { Drawer } from './Drawer.js'
15
18
  import { SeoLoading, SeoErrorState, btnPrimary, btnSecondary, gradeMeta } from './primitives.js'
16
19
 
@@ -28,6 +31,11 @@ type AiField =
28
31
  const KEY_TAKEAWAY_MAX = 240
29
32
  const LLMS_DESC_MAX = 160
30
33
 
34
+ function seoBrandChannel(field: AiField): string | undefined {
35
+ if (field === 'metaDescription' || field === 'ogDescription') return 'meta_description'
36
+ return undefined
37
+ }
38
+
31
39
  function CharCount({ value, max }: { value: string; max: number }) {
32
40
  const over = value.length > max
33
41
  return (
@@ -90,6 +98,10 @@ export function SeoEditorDrawer({
90
98
  const [error, setError] = useState<string | null>(null)
91
99
  const [saving, setSaving] = useState(false)
92
100
  const [aiBusy, setAiBusy] = useState<AiField | null>(null)
101
+ const [aiFixBusy, setAiFixBusy] = useState<AiField | null>(null)
102
+ const [aiAlignments, setAiAlignments] = useState<
103
+ Partial<Record<AiField, BrandAlignmentScoreResult>>
104
+ >({})
93
105
  const [form, setForm] = useState<SeoFieldPayload>({})
94
106
 
95
107
  useEffect(() => {
@@ -141,6 +153,9 @@ export function SeoEditorDrawer({
141
153
  }
142
154
  if (result.text) {
143
155
  update({ [field]: result.text } as Partial<SeoFieldPayload>)
156
+ if (result.brandAlignment) {
157
+ setAiAlignments((prev) => ({ ...prev, [field]: result.brandAlignment }))
158
+ }
144
159
  toast.success('AI suggestion applied — review before saving.')
145
160
  } else {
146
161
  toast.error('No suggestion was returned.')
@@ -152,6 +167,53 @@ export function SeoEditorDrawer({
152
167
  }
153
168
  }
154
169
 
170
+ async function handleAiFix(field: AiField) {
171
+ const text = (form[field as keyof SeoFieldPayload] as string | undefined) ?? ''
172
+ if (!text.trim()) return
173
+ setAiFixBusy(field)
174
+ try {
175
+ const res = await fixBrandVoiceContent({
176
+ content: text,
177
+ channel: seoBrandChannel(field),
178
+ })
179
+ if (!res.ok || !res.result) {
180
+ toast.error(res.error ?? 'Could not fix copy for brand voice.')
181
+ return
182
+ }
183
+ update({ [field]: res.result.text } as Partial<SeoFieldPayload>)
184
+ setAiAlignments((prev) => ({ ...prev, [field]: res.result!.afterScore }))
185
+ toast.success('Copy adjusted to match brand voice.')
186
+ } finally {
187
+ setAiFixBusy(null)
188
+ }
189
+ }
190
+
191
+ function alignmentRow(field: AiField) {
192
+ const alignment = aiAlignments[field]
193
+ if (!alignment) return null
194
+ const fixing = aiFixBusy === field
195
+ return (
196
+ <div className="mt-2 flex flex-wrap items-center gap-2">
197
+ <BrandVoiceAlignmentBadge alignment={alignment} compact />
198
+ {alignment.score < 85 && (
199
+ <button
200
+ type="button"
201
+ onClick={() => handleAiFix(field)}
202
+ disabled={fixing || aiBusy !== null}
203
+ className="text-primary hover:bg-accent focus-visible:ring-ring inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium focus-visible:ring-2 focus-visible:outline-none disabled:opacity-60"
204
+ >
205
+ {fixing ? (
206
+ <Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden />
207
+ ) : (
208
+ <Wand2 className="h-3.5 w-3.5" aria-hidden />
209
+ )}
210
+ Fix for brand voice
211
+ </button>
212
+ )}
213
+ </div>
214
+ )
215
+ }
216
+
155
217
  async function handleSave() {
156
218
  if (!entityType || !entityId) return
157
219
  setSaving(true)
@@ -252,6 +314,7 @@ export function SeoEditorDrawer({
252
314
  onChange={(e) => update({ metaDescription: e.target.value })}
253
315
  placeholder="Short summary shown under the title in search results"
254
316
  />
317
+ {alignmentRow('metaDescription')}
255
318
  </Field>
256
319
 
257
320
  <Field label="Focus keyword" hint={aiButton('focusKeyword')}>
@@ -307,6 +370,7 @@ export function SeoEditorDrawer({
307
370
  onChange={(e) => update({ ogDescription: e.target.value })}
308
371
  placeholder={form.metaDescription || 'Description when shared on social media'}
309
372
  />
373
+ {alignmentRow('ogDescription')}
310
374
  </Field>
311
375
  <div className="border-border overflow-hidden rounded-lg border">
312
376
  {record.ogImage ? (