@actuate-media/cms-admin 0.33.0 → 0.34.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 (46) hide show
  1. package/dist/__tests__/views/ai-settings.render.test.d.ts +2 -0
  2. package/dist/__tests__/views/ai-settings.render.test.d.ts.map +1 -0
  3. package/dist/__tests__/views/ai-settings.render.test.js +182 -0
  4. package/dist/__tests__/views/ai-settings.render.test.js.map +1 -0
  5. package/dist/actuate-admin.css +1 -1
  6. package/dist/views/Settings.d.ts.map +1 -1
  7. package/dist/views/Settings.js +2 -46
  8. package/dist/views/Settings.js.map +1 -1
  9. package/dist/views/settings/AISettingsTab.d.ts +6 -0
  10. package/dist/views/settings/AISettingsTab.d.ts.map +1 -0
  11. package/dist/views/settings/AISettingsTab.js +138 -0
  12. package/dist/views/settings/AISettingsTab.js.map +1 -0
  13. package/dist/views/settings/AiFeaturesCard.d.ts +12 -0
  14. package/dist/views/settings/AiFeaturesCard.d.ts.map +1 -0
  15. package/dist/views/settings/AiFeaturesCard.js +14 -0
  16. package/dist/views/settings/AiFeaturesCard.js.map +1 -0
  17. package/dist/views/settings/CapabilityBadges.d.ts +5 -0
  18. package/dist/views/settings/CapabilityBadges.d.ts.map +1 -0
  19. package/dist/views/settings/CapabilityBadges.js +26 -0
  20. package/dist/views/settings/CapabilityBadges.js.map +1 -0
  21. package/dist/views/settings/ModelSelector.d.ts +12 -0
  22. package/dist/views/settings/ModelSelector.d.ts.map +1 -0
  23. package/dist/views/settings/ModelSelector.js +29 -0
  24. package/dist/views/settings/ModelSelector.js.map +1 -0
  25. package/dist/views/settings/MonthlyUsageCard.d.ts +14 -0
  26. package/dist/views/settings/MonthlyUsageCard.d.ts.map +1 -0
  27. package/dist/views/settings/MonthlyUsageCard.js +30 -0
  28. package/dist/views/settings/MonthlyUsageCard.js.map +1 -0
  29. package/dist/views/settings/ProviderConnectionCard.d.ts +13 -0
  30. package/dist/views/settings/ProviderConnectionCard.d.ts.map +1 -0
  31. package/dist/views/settings/ProviderConnectionCard.js +48 -0
  32. package/dist/views/settings/ProviderConnectionCard.js.map +1 -0
  33. package/dist/views/settings/useAiSettings.d.ts +143 -0
  34. package/dist/views/settings/useAiSettings.d.ts.map +1 -0
  35. package/dist/views/settings/useAiSettings.js +278 -0
  36. package/dist/views/settings/useAiSettings.js.map +1 -0
  37. package/package.json +2 -2
  38. package/src/__tests__/views/ai-settings.render.test.tsx +225 -0
  39. package/src/views/Settings.tsx +2 -139
  40. package/src/views/settings/AISettingsTab.tsx +411 -0
  41. package/src/views/settings/AiFeaturesCard.tsx +49 -0
  42. package/src/views/settings/CapabilityBadges.tsx +66 -0
  43. package/src/views/settings/ModelSelector.tsx +115 -0
  44. package/src/views/settings/MonthlyUsageCard.tsx +118 -0
  45. package/src/views/settings/ProviderConnectionCard.tsx +245 -0
  46. package/src/views/settings/useAiSettings.ts +448 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ai-settings.render.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-settings.render.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/views/ai-settings.render.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,182 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @vitest-environment happy-dom
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
5
+ /**
6
+ * Settings > AI reads three backends: /ai/settings (defaults + masked
7
+ * providers), /ai/models (catalog), /ai/usage/summary. Provider connection
8
+ * actions hit /ai/providers/*. Keys are never returned — only a masked last4.
9
+ */
10
+ const SETTINGS_RESPONSE = {
11
+ settings: {
12
+ defaultProviderId: 'p1',
13
+ defaultModelId: 'anthropic:claude-sonnet-4-latest',
14
+ features: [
15
+ {
16
+ key: 'ai.features.contentWriting',
17
+ label: 'Content writing suggestions',
18
+ description: 'Draft, rewrite, summarize content.',
19
+ enabled: true,
20
+ category: 'content',
21
+ requiredCapabilities: ['text'],
22
+ },
23
+ {
24
+ key: 'ai.features.redirectChainFlattening',
25
+ label: 'Redirect chain flattening',
26
+ description: 'Suggest single-hop redirects.',
27
+ enabled: false,
28
+ category: 'seo',
29
+ requiredCapabilities: ['text'],
30
+ },
31
+ ],
32
+ budget: { monthlyTokenLimit: 1000000 },
33
+ },
34
+ providers: [
35
+ {
36
+ id: 'p1',
37
+ provider: 'anthropic',
38
+ displayName: 'Anthropic (Claude)',
39
+ enabled: true,
40
+ status: 'connected',
41
+ apiKeyLast4: 'f12a',
42
+ apiKeySource: 'database',
43
+ keyManagedExternally: false,
44
+ hasKey: true,
45
+ createdAt: '2026-01-01T00:00:00.000Z',
46
+ updatedAt: '2026-01-01T00:00:00.000Z',
47
+ updatedBy: 'u1',
48
+ },
49
+ ],
50
+ defaultModel: null,
51
+ };
52
+ const MODELS = [
53
+ {
54
+ id: 'anthropic:claude-sonnet-4-latest',
55
+ provider: 'anthropic',
56
+ providerModelId: 'claude-sonnet-4-latest',
57
+ displayName: 'Claude Sonnet (balanced)',
58
+ status: 'available',
59
+ capabilities: { text: true, vision: true, toolCalling: true },
60
+ contextWindow: 200000,
61
+ inputModalities: ['text', 'image'],
62
+ outputModalities: ['text'],
63
+ pricing: { inputPerMillion: 3, outputPerMillion: 15 },
64
+ lastSyncedAt: '2026-01-01T00:00:00.000Z',
65
+ source: 'config',
66
+ },
67
+ ];
68
+ const USAGE = {
69
+ totalTokens: 412000,
70
+ promptTokens: 0,
71
+ completionTokens: 0,
72
+ monthlyTokenLimit: 1000000,
73
+ periodStart: '2026-06-01T00:00:00.000Z',
74
+ periodEnd: '2026-07-01T00:00:00.000Z',
75
+ runCount: 5,
76
+ };
77
+ // Mutable overrides so individual tests can tweak the loaded shape.
78
+ let settingsResponse = SETTINGS_RESPONSE;
79
+ const cmsApi = vi.fn(async (endpoint, options) => {
80
+ const method = options?.method ?? 'GET';
81
+ if (endpoint === '/ai/settings' && method === 'GET')
82
+ return { data: settingsResponse, status: 200 };
83
+ if (endpoint === '/ai/settings' && method === 'PUT')
84
+ return { data: settingsResponse, status: 200 };
85
+ if (endpoint === '/ai/models' && method === 'GET')
86
+ return { data: { models: MODELS }, status: 200 };
87
+ if (endpoint === '/ai/usage/summary')
88
+ return { data: USAGE, status: 200 };
89
+ if (endpoint === '/ai/providers/p1/test' && method === 'POST') {
90
+ return {
91
+ data: {
92
+ provider: settingsResponse.providers[0],
93
+ result: { ok: true, status: 'connected', message: 'Connection successful.' },
94
+ },
95
+ status: 200,
96
+ };
97
+ }
98
+ if (endpoint === '/ai/providers/p1/sync-models' && method === 'POST') {
99
+ return { data: { models: MODELS, fromFallback: false, warning: null }, status: 200 };
100
+ }
101
+ return { data: {}, status: 200 };
102
+ });
103
+ vi.mock('../../lib/api.js', () => ({
104
+ cmsApi: (e, o) => cmsApi(e, o),
105
+ ensureCsrfToken: vi.fn(async () => { }),
106
+ }));
107
+ vi.mock('sonner', () => ({
108
+ toast: { success: vi.fn(), error: vi.fn(), warning: vi.fn(), loading: vi.fn() },
109
+ }));
110
+ const { AISettingsTab } = await import('../../views/settings/AISettingsTab.js');
111
+ function deepClone(v) {
112
+ return JSON.parse(JSON.stringify(v));
113
+ }
114
+ beforeEach(() => {
115
+ cmsApi.mockClear();
116
+ settingsResponse = deepClone(SETTINGS_RESPONSE);
117
+ });
118
+ describe('AISettingsTab', () => {
119
+ it('loads the default provider, model, and capability badges', async () => {
120
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
121
+ expect(await screen.findByText('AI Assistant')).toBeTruthy();
122
+ const assistant = screen.getByRole('region', { name: 'AI Assistant' });
123
+ expect(within(assistant).getByLabelText('Default model').value).toBe('anthropic:claude-sonnet-4-latest');
124
+ // Capability badges render as text (not color-only).
125
+ expect(within(assistant).getByText('Vision')).toBeTruthy();
126
+ expect(within(assistant).getByText('200,000 token context')).toBeTruthy();
127
+ });
128
+ it('shows real monthly usage (never a fabricated number)', async () => {
129
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
130
+ expect(await screen.findByText('412K tokens used')).toBeTruthy();
131
+ expect(screen.getByRole('progressbar').getAttribute('aria-valuenow')).toBe('41');
132
+ });
133
+ it('refreshes the model catalog via the provider sync endpoint', async () => {
134
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
135
+ const assistant = await screen.findByRole('region', { name: 'AI Assistant' });
136
+ fireEvent.click(within(assistant).getByRole('button', { name: 'Refresh models' }));
137
+ await waitFor(() => expect(cmsApi).toHaveBeenCalledWith('/ai/providers/p1/sync-models', expect.objectContaining({ method: 'POST' })));
138
+ });
139
+ it('tests a provider connection', async () => {
140
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
141
+ await screen.findByText('AI Assistant');
142
+ fireEvent.click(screen.getByRole('button', { name: 'Test connection' }));
143
+ await waitFor(() => expect(cmsApi).toHaveBeenCalledWith('/ai/providers/p1/test', expect.objectContaining({ method: 'POST' })));
144
+ });
145
+ it('toggles a feature and saves it to /ai/settings', async () => {
146
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
147
+ await screen.findByText('AI Features');
148
+ fireEvent.click(screen.getByRole('switch', { name: 'Content writing suggestions' }));
149
+ const save = screen.getByRole('button', { name: 'Save Changes' });
150
+ expect(save.disabled).toBe(false);
151
+ fireEvent.click(save);
152
+ await waitFor(() => expect(cmsApi).toHaveBeenCalledWith('/ai/settings', expect.objectContaining({ method: 'PUT' })));
153
+ const putCall = cmsApi.mock.calls.find(([e, o]) => e === '/ai/settings' && o?.method === 'PUT');
154
+ const body = JSON.parse(putCall[1].body);
155
+ const cw = body.features.find((f) => f.key === 'ai.features.contentWriting');
156
+ expect(cw.enabled).toBe(false);
157
+ });
158
+ it('is read-only for non-admins', async () => {
159
+ render(_jsx(AISettingsTab, { role: "EDITOR" }));
160
+ expect(await screen.findByText(/read-only access to AI settings/i)).toBeTruthy();
161
+ const assistant = screen.getByRole('region', { name: 'AI Assistant' });
162
+ expect(within(assistant).getByLabelText('Default model').disabled).toBe(true);
163
+ expect(screen.getByRole('switch', { name: 'Content writing suggestions' })
164
+ .disabled).toBe(true);
165
+ });
166
+ it('renders an env-managed key as read-only', async () => {
167
+ settingsResponse = deepClone(SETTINGS_RESPONSE);
168
+ settingsResponse.providers[0].keyManagedExternally = true;
169
+ settingsResponse.providers[0].apiKeySource = 'environment';
170
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
171
+ expect(await screen.findByText('Managed by environment')).toBeTruthy();
172
+ expect(screen.getByText(/set via an environment variable/i)).toBeTruthy();
173
+ });
174
+ it('warns when the configured default model is no longer available', async () => {
175
+ settingsResponse = deepClone(SETTINGS_RESPONSE);
176
+ settingsResponse.settings.defaultModelId = 'anthropic:ghost-model';
177
+ render(_jsx(AISettingsTab, { role: "ADMIN" }));
178
+ await screen.findByText('AI Assistant');
179
+ expect(await screen.findByText(/selected model is no longer offered by the provider/i)).toBeTruthy();
180
+ });
181
+ });
182
+ //# sourceMappingURL=ai-settings.render.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-settings.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/ai-settings.render.test.tsx"],"names":[],"mappings":"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"}