@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.
- package/CHANGELOG.md +9 -0
- package/dist/__tests__/views/ai-settings.render.test.js +34 -0
- package/dist/__tests__/views/ai-settings.render.test.js.map +1 -1
- package/dist/actuate-admin.css +1 -1
- package/dist/components/AICoauthorBubbleMenu.d.ts.map +1 -1
- package/dist/components/AICoauthorBubbleMenu.js +5 -1
- package/dist/components/AICoauthorBubbleMenu.js.map +1 -1
- package/dist/components/BrandVoiceAlignmentBadge.d.ts +6 -0
- package/dist/components/BrandVoiceAlignmentBadge.d.ts.map +1 -0
- package/dist/components/BrandVoiceAlignmentBadge.js +11 -0
- package/dist/components/BrandVoiceAlignmentBadge.js.map +1 -0
- package/dist/components/CoauthorResultPopover.d.ts +5 -1
- package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
- package/dist/components/CoauthorResultPopover.js +35 -6
- package/dist/components/CoauthorResultPopover.js.map +1 -1
- package/dist/components/CommandPalette.d.ts.map +1 -1
- package/dist/components/CommandPalette.js +5 -1
- package/dist/components/CommandPalette.js.map +1 -1
- package/dist/components/seo/SeoEditorDrawer.d.ts.map +1 -1
- package/dist/components/seo/SeoEditorDrawer.js +43 -2
- package/dist/components/seo/SeoEditorDrawer.js.map +1 -1
- package/dist/components/ui/Badge.d.ts +1 -1
- package/dist/lib/brand-voice-client.d.ts +21 -0
- package/dist/lib/brand-voice-client.d.ts.map +1 -0
- package/dist/lib/brand-voice-client.js +27 -0
- package/dist/lib/brand-voice-client.js.map +1 -0
- package/dist/lib/coauthor-client.d.ts +2 -0
- package/dist/lib/coauthor-client.d.ts.map +1 -1
- package/dist/lib/coauthor-client.js +1 -0
- package/dist/lib/coauthor-client.js.map +1 -1
- package/dist/lib/seo-service.d.ts +12 -0
- package/dist/lib/seo-service.d.ts.map +1 -1
- package/dist/lib/seo-service.js +0 -10
- package/dist/lib/seo-service.js.map +1 -1
- package/dist/views/Settings.js +1 -1
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/settings/AISettingsTab.d.ts +3 -1
- package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
- package/dist/views/settings/AISettingsTab.js +2 -2
- package/dist/views/settings/AISettingsTab.js.map +1 -1
- package/dist/views/settings/BrandVoiceCard.d.ts +39 -2
- package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -1
- package/dist/views/settings/BrandVoiceCard.js +215 -3
- package/dist/views/settings/BrandVoiceCard.js.map +1 -1
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts +13 -0
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts.map +1 -0
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js +74 -0
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js.map +1 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.d.ts +7 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.d.ts.map +1 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.js +54 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.js.map +1 -0
- package/dist/views/settings/useAiSettings.d.ts +32 -0
- package/dist/views/settings/useAiSettings.d.ts.map +1 -1
- package/dist/views/settings/useAiSettings.js +85 -3
- package/dist/views/settings/useAiSettings.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/views/ai-settings.render.test.tsx +50 -0
- package/src/components/AICoauthorBubbleMenu.tsx +12 -0
- package/src/components/BrandVoiceAlignmentBadge.tsx +39 -0
- package/src/components/CoauthorResultPopover.tsx +62 -4
- package/src/components/CommandPalette.tsx +12 -0
- package/src/components/seo/SeoEditorDrawer.tsx +65 -1
- package/src/lib/brand-voice-client.ts +38 -0
- package/src/lib/coauthor-client.ts +4 -0
- package/src/lib/seo-service.ts +2 -0
- package/src/views/Settings.tsx +1 -1
- package/src/views/settings/AISettingsTab.tsx +13 -2
- package/src/views/settings/BrandVoiceCard.tsx +592 -76
- package/src/views/settings/brand-voice/BrandVoiceAlignmentPanel.tsx +205 -0
- package/src/views/settings/brand-voice/BrandVoiceRulesSections.tsx +321 -0
- package/src/views/settings/useAiSettings.ts +134 -3
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
|
|
2
|
+
import { cmsApi } from './api.js'
|
|
3
|
+
|
|
4
|
+
export type { BrandAlignmentScoreResult }
|
|
5
|
+
|
|
6
|
+
export interface BrandVoiceFixResult {
|
|
7
|
+
text: string
|
|
8
|
+
deterministicFixes: string[]
|
|
9
|
+
beforeScore: BrandAlignmentScoreResult
|
|
10
|
+
afterScore: BrandAlignmentScoreResult
|
|
11
|
+
usedAi: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function fixBrandVoiceContent(input: {
|
|
15
|
+
content: string
|
|
16
|
+
channel?: string
|
|
17
|
+
useAi?: boolean
|
|
18
|
+
}): Promise<{ ok: boolean; result?: BrandVoiceFixResult; error?: string }> {
|
|
19
|
+
const res = await cmsApi<BrandVoiceFixResult>('/ai/brand-voice/fix', {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
body: JSON.stringify(input),
|
|
22
|
+
})
|
|
23
|
+
if (res.error) return { ok: false, error: res.error }
|
|
24
|
+
if (!res.data?.text) return { ok: false, error: 'No fixed copy was returned.' }
|
|
25
|
+
return { ok: true, result: res.data }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function brandAlignmentLabel(score: number): string {
|
|
29
|
+
if (score >= 85) return 'On brand'
|
|
30
|
+
if (score >= 65) return 'Mostly on brand'
|
|
31
|
+
return 'Off brand'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function brandAlignmentTone(score: number): string {
|
|
35
|
+
if (score >= 85) return 'text-success'
|
|
36
|
+
if (score >= 65) return 'text-warning'
|
|
37
|
+
return 'text-destructive'
|
|
38
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cmsApi } from './api.js'
|
|
2
|
+
import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Inline AI co-author client — thin, typed wrapper around the
|
|
@@ -68,6 +69,7 @@ export interface CoauthorResult {
|
|
|
68
69
|
text: string
|
|
69
70
|
/** Populated only when `action === 'proofread'`. */
|
|
70
71
|
changes?: ProofreadChange[]
|
|
72
|
+
brandAlignment?: BrandAlignmentScoreResult
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
export type CoauthorOutcome =
|
|
@@ -125,6 +127,7 @@ export async function coauthorText(
|
|
|
125
127
|
action?: CoauthorAction
|
|
126
128
|
text?: unknown
|
|
127
129
|
changes?: unknown
|
|
130
|
+
brandAlignment?: BrandAlignmentScoreResult
|
|
128
131
|
}>('/ai/coauthor', {
|
|
129
132
|
method: 'POST',
|
|
130
133
|
body: JSON.stringify(body),
|
|
@@ -155,6 +158,7 @@ export async function coauthorText(
|
|
|
155
158
|
action === 'proofread' && Array.isArray(res.data.changes)
|
|
156
159
|
? (res.data.changes as ProofreadChange[])
|
|
157
160
|
: undefined,
|
|
161
|
+
brandAlignment: res.data.brandAlignment,
|
|
158
162
|
},
|
|
159
163
|
}
|
|
160
164
|
}
|
package/src/lib/seo-service.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* Endpoint paths here are the contract implemented by cms-core
|
|
9
9
|
* `packages/cms-core/src/api/handlers.ts` across phases 2-3 and 6.
|
|
10
10
|
*/
|
|
11
|
+
import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
|
|
11
12
|
import { cmsApi } from './api.js'
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -643,6 +644,7 @@ export interface SeoAiResult {
|
|
|
643
644
|
text?: string
|
|
644
645
|
alternatives?: string[]
|
|
645
646
|
structuredData?: Record<string, unknown>
|
|
647
|
+
brandAlignment?: BrandAlignmentScoreResult
|
|
646
648
|
/** True when the AI provider is not configured (graceful fallback). */
|
|
647
649
|
unavailable?: boolean
|
|
648
650
|
}
|
package/src/views/Settings.tsx
CHANGED
|
@@ -325,7 +325,7 @@ export function Settings({
|
|
|
325
325
|
</Tabs.Content>
|
|
326
326
|
|
|
327
327
|
<Tabs.Content value="ai" className="space-y-4">
|
|
328
|
-
<AISettingsTab role={session?.user?.role} />
|
|
328
|
+
<AISettingsTab role={session?.user?.role} config={config} />
|
|
329
329
|
</Tabs.Content>
|
|
330
330
|
|
|
331
331
|
<Tabs.Content value="users">
|
|
@@ -30,9 +30,11 @@ const PROVIDER_OPTIONS: Array<{ value: AiProviderKey; label: string }> = [
|
|
|
30
30
|
export interface AISettingsTabProps {
|
|
31
31
|
/** Current user's role. Only ADMIN can persist changes. */
|
|
32
32
|
role?: string
|
|
33
|
+
/** Resolved CMS config — used to list content collections for brand voice analysis. */
|
|
34
|
+
config?: unknown
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
export function AISettingsTab({ role }: AISettingsTabProps) {
|
|
37
|
+
export function AISettingsTab({ role, config }: AISettingsTabProps) {
|
|
36
38
|
const canEdit = role === 'ADMIN'
|
|
37
39
|
const ai = useAiSettings(canEdit)
|
|
38
40
|
|
|
@@ -89,7 +91,16 @@ export function AISettingsTab({ role }: AISettingsTabProps) {
|
|
|
89
91
|
onToggle={ai.toggleFeature}
|
|
90
92
|
onSetFeatureModel={ai.setFeatureModel}
|
|
91
93
|
/>
|
|
92
|
-
<BrandVoiceCard
|
|
94
|
+
<BrandVoiceCard
|
|
95
|
+
value={ai.form.brandVoice}
|
|
96
|
+
canEdit={canEdit}
|
|
97
|
+
onChange={ai.setBrandVoice}
|
|
98
|
+
config={config}
|
|
99
|
+
onAnalyze={canEdit ? ai.analyzeBrandVoice : undefined}
|
|
100
|
+
onScore={canEdit ? ai.scoreBrandVoice : undefined}
|
|
101
|
+
editMode={ai.brandVoiceEditMode}
|
|
102
|
+
onEditModeChange={ai.setBrandVoiceEditMode}
|
|
103
|
+
/>
|
|
93
104
|
<MonthlyUsageCard
|
|
94
105
|
usage={ai.usage}
|
|
95
106
|
monthlyTokenLimit={ai.form.monthlyTokenLimit}
|