@zenith-open/zenithcms-plugin-ai-architect-ui 1.0.0-beta.10 → 1.0.0-beta.8

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.
@@ -0,0 +1,2 @@
1
+ declare const AIWriterPage: () => import("react/jsx-runtime").JSX.Element;
2
+ export default AIWriterPage;
@@ -0,0 +1,192 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from 'react';
3
+ import { Sparkles, Send, Loader2, Copy, Zap, Terminal, Cpu, PenTool, ShieldCheck, Search, Image as ImageIcon, CheckCircle2, AlertCircle, ChevronRight, RotateCcw, Save, Download, Code2, Wand2, Hash } from 'lucide-react';
4
+ import api from '../lib/api';
5
+ import { motion, AnimatePresence } from 'framer-motion';
6
+ import { cn } from '../lib/utils';
7
+ import toast from 'react-hot-toast';
8
+ import { useTheme } from '../context/ThemeContext';
9
+ import { PageHeader } from '../components/ui/PageHeader';
10
+ // ── Tool Definitions ───────────────────────────────────────────────────────────
11
+ const TOOLS = [
12
+ { id: 'seo', name: 'SEO Analysis', icon: Search, endpoint: '/content-tools/seo-analysis', desc: 'Score title, meta, content', color: 'text-amber-400' },
13
+ { id: 'quality', name: 'Quality Audit', icon: ShieldCheck, endpoint: '/content-tools/quality', desc: 'Readability + word structure', color: 'text-z-active-text' },
14
+ { id: 'improve', name: 'Refine Text', icon: Wand2, endpoint: '/content-tools/ai/improve', desc: 'AI-powered rewrite', color: 'text-purple-400' },
15
+ { id: 'meta', name: 'Meta Generator', icon: Hash, endpoint: '/content-tools/ai/meta-description', desc: 'Auto SEO meta description', color: 'text-z-active-text' },
16
+ { id: 'alt', name: 'Alt Text', icon: ImageIcon, endpoint: '/content-tools/ai/alt-text', desc: 'Generate image alt text', color: 'text-pink-400' },
17
+ ];
18
+ const MODES = [
19
+ { id: 'writer', label: 'Writer', icon: PenTool, desc: 'Generate content from a prompt' },
20
+ { id: 'architect', label: 'Architect', icon: Cpu, desc: 'Design a collection schema with AI' },
21
+ { id: 'tools', label: 'Tools', icon: Zap, desc: 'SEO, quality, meta & more' },
22
+ ];
23
+ // ── Result Renderers ──────────────────────────────────────────────────────────
24
+ function SeoResultView({ data }) {
25
+ return (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "flex items-end gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary mb-1", children: "SEO Score" }), _jsx("span", { className: cn('text-5xl font-black tabular-nums', data.score >= 70 ? 'text-z-active-text' : data.score >= 45 ? 'text-amber-400' : 'text-red-400'), children: data.score }), _jsx("span", { className: "text-lg text-z-secondary font-black", children: "/100" })] }), _jsx("div", { className: "flex-1 h-2 bg-z-hover rounded-full overflow-hidden mb-3", children: _jsx("div", { className: cn('h-full transition-all duration-700', data.score >= 70 ? 'bg-z-accent' : data.score >= 45 ? 'bg-amber-500' : 'bg-red-500'), style: { width: `${data.score}%` } }) })] }), data.passed?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-active-text/70", children: "Passing" }), data.passed.map((p, i) => (_jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(CheckCircle2, { size: 11, className: "text-z-active-text flex-shrink-0" }), p] }, i)))] })), data.issues?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-red-500/70", children: "Issues" }), data.issues.map((p, i) => (_jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(AlertCircle, { size: 11, className: "text-red-500 flex-shrink-0" }), p] }, i)))] })), data.suggestions?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-amber-500/70", children: "Suggestions" }), data.suggestions.map((p, i) => (_jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(ChevronRight, { size: 11, className: "text-amber-500 flex-shrink-0" }), p] }, i)))] }))] }));
26
+ }
27
+ function QualityResultView({ data }) {
28
+ const gradeColor = { A: 'text-z-active-text', B: 'text-z-active-text', C: 'text-amber-400', D: 'text-orange-400', F: 'text-red-400' };
29
+ return (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "flex items-start gap-6", children: [_jsxs("div", { children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary mb-1", children: "Grade" }), _jsx("span", { className: cn('text-6xl font-black', gradeColor[data.grade] || 'text-white'), children: data.grade })] }), _jsx("div", { className: "grid grid-cols-3 gap-3 flex-1 pt-1", children: [
30
+ { label: 'Words', val: data.wordCount },
31
+ { label: 'Sentences', val: data.sentenceCount },
32
+ { label: 'Avg Words/Sent', val: data.avgWordsPerSentence },
33
+ ].map(m => (_jsxs("div", { className: "bg-z-hover border border-z-border p-3", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-widest text-z-secondary mb-1", children: m.label }), _jsx("p", { className: "text-lg font-black text-white tabular-nums", children: m.val })] }, m.label))) })] }), data.issues?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-red-500/70", children: "Issues" }), data.issues.map((p, i) => _jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(AlertCircle, { size: 11, className: "text-red-500 flex-shrink-0" }), p] }, i))] })), data.suggestions?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-active-text/70", children: "Suggestions" }), data.suggestions.map((p, i) => _jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(CheckCircle2, { size: 11, className: "text-z-active-text flex-shrink-0" }), p] }, i))] }))] }));
34
+ }
35
+ function SchemaResultView({ data }) {
36
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3 flex-wrap", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-black text-white tracking-tight", children: data.name }), _jsxs("p", { className: "text-[9px] text-z-secondary font-mono mt-0.5", children: ["/", data.slug] })] }), _jsxs("div", { className: "flex gap-2", children: [data.drafts && _jsx("span", { className: "px-2 py-0.5 text-[7px] font-black uppercase tracking-widest bg-z-accent/10 border border-z-accent/20 text-z-active-text", children: "Drafts" }), data.timestamps && _jsx("span", { className: "px-2 py-0.5 text-[7px] font-black uppercase tracking-widest bg-gray-500/10 border border-gray-500/20 text-z-muted", children: "Timestamps" })] })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: [data.fields?.length || 0, " Fields"] }), data.fields?.map((f, i) => (_jsxs("div", { className: "flex items-center justify-between px-3 py-2 bg-z-hover border border-z-border hover:border-z-border-strong transition-colors group", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-[9px] font-mono text-z-active-text", children: f.name }), f.required && _jsx("span", { className: "text-[6px] font-black text-red-500 uppercase tracking-wider", children: "required" })] }), _jsx("span", { className: "text-[8px] text-gray-600 uppercase tracking-widest font-black", children: f.type })] }, i)))] })] }));
37
+ }
38
+ // ── Main Component ─────────────────────────────────────────────────────────────
39
+ const AIWriterPage = () => {
40
+ const { theme } = useTheme();
41
+ const dark = theme === 'dark';
42
+ const [mode, setMode] = useState('writer');
43
+ const [prompt, setPrompt] = useState('');
44
+ const [loading, setLoading] = useState(false);
45
+ const [result, setResult] = useState(null);
46
+ const [activeTool, setActiveTool] = useState('seo');
47
+ const [history, setHistory] = useState([]);
48
+ const [schemaForSave, setSchemaForSave] = useState(null);
49
+ const [savingSchema, setSavingSchema] = useState(false);
50
+ const textareaRef = useRef(null);
51
+ // Auto-resize textarea
52
+ useEffect(() => {
53
+ if (textareaRef.current) {
54
+ textareaRef.current.style.height = 'auto';
55
+ textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 300)}px`;
56
+ }
57
+ }, [prompt]);
58
+ const handleExecute = async () => {
59
+ if (!prompt.trim() && activeTool !== 'alt')
60
+ return;
61
+ setLoading(true);
62
+ setResult(null);
63
+ setSchemaForSave(null);
64
+ try {
65
+ let res;
66
+ let resultData;
67
+ if (mode === 'architect') {
68
+ res = await api.post('/system/ai-architect', { prompt });
69
+ resultData = res.data.data.schema;
70
+ setSchemaForSave(resultData);
71
+ }
72
+ else if (mode === 'writer') {
73
+ res = await api.post('/content-tools/ai/generate', { prompt });
74
+ resultData = res.data.data.text;
75
+ }
76
+ else {
77
+ const tool = TOOLS.find(t => t.id === activeTool);
78
+ let payload = { content: prompt };
79
+ if (activeTool === 'improve') {
80
+ payload = { text: prompt, instruction: 'Make it more professional, clear, and concise. Improve grammar and flow.' };
81
+ }
82
+ else if (activeTool === 'meta') {
83
+ payload = { title: 'Content', content: prompt };
84
+ }
85
+ else if (activeTool === 'seo') {
86
+ payload = { title: prompt.split('\n')[0]?.substring(0, 60), content: prompt, description: prompt.substring(0, 160) };
87
+ }
88
+ else if (activeTool === 'alt') {
89
+ payload = { imageUrl: prompt };
90
+ }
91
+ res = await api.post(tool.endpoint, payload);
92
+ const d = res.data.data;
93
+ if (activeTool === 'seo')
94
+ resultData = d;
95
+ else if (activeTool === 'quality')
96
+ resultData = d;
97
+ else if (activeTool === 'improve')
98
+ resultData = d.text;
99
+ else if (activeTool === 'meta')
100
+ resultData = d.description;
101
+ else if (activeTool === 'alt')
102
+ resultData = d.altText;
103
+ }
104
+ setResult(resultData);
105
+ setHistory(prev => [{
106
+ id: Date.now().toString(),
107
+ mode,
108
+ prompt: prompt.substring(0, 80),
109
+ result: resultData,
110
+ timestamp: new Date()
111
+ }, ...prev.slice(0, 19)]);
112
+ toast.success('Generated');
113
+ }
114
+ catch (err) {
115
+ const msg = err?.response?.data?.error?.message || err?.response?.data?.message || 'AI request failed';
116
+ toast.error(msg);
117
+ }
118
+ finally {
119
+ setLoading(false);
120
+ }
121
+ };
122
+ const handleKeyDown = (e) => {
123
+ if ((e.metaKey || e.ctrlKey) && e.key === 'Enter')
124
+ handleExecute();
125
+ };
126
+ const saveSchemaToDb = async () => {
127
+ if (!schemaForSave)
128
+ return;
129
+ setSavingSchema(true);
130
+ try {
131
+ await api.post('/schemas', schemaForSave);
132
+ toast.success(`Collection "${schemaForSave.name}" created!`);
133
+ setSchemaForSave(null);
134
+ }
135
+ catch (err) {
136
+ toast.error(err?.response?.data?.error?.message || 'Failed to save schema');
137
+ }
138
+ finally {
139
+ setSavingSchema(false);
140
+ }
141
+ };
142
+ const copyResult = () => {
143
+ const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
144
+ navigator.clipboard.writeText(text);
145
+ toast.success('Copied to clipboard');
146
+ };
147
+ const downloadResult = () => {
148
+ const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
149
+ const ext = mode === 'architect' ? 'json' : 'txt';
150
+ const blob = new Blob([text], { type: 'text/plain' });
151
+ const url = URL.createObjectURL(blob);
152
+ const a = document.createElement('a');
153
+ a.href = url;
154
+ a.download = `zenith-ai-output.${ext}`;
155
+ a.click();
156
+ URL.revokeObjectURL(url);
157
+ };
158
+ const renderResult = () => {
159
+ if (!result)
160
+ return null;
161
+ if (mode === 'architect')
162
+ return _jsx(SchemaResultView, { data: result });
163
+ if (mode === 'tools' && activeTool === 'seo')
164
+ return _jsx(SeoResultView, { data: result });
165
+ if (mode === 'tools' && activeTool === 'quality')
166
+ return _jsx(QualityResultView, { data: result });
167
+ return (_jsx(motion.div, { initial: { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, className: "whitespace-pre-wrap text-[12px] leading-relaxed text-gray-300 font-sans", children: typeof result === 'string' ? result : JSON.stringify(result, null, 2) }));
168
+ };
169
+ const activePlaceholder = mode === 'architect'
170
+ ? 'Describe a collection schema... e.g., "An e-commerce product with variants, pricing, and inventory tracking"'
171
+ : mode === 'writer'
172
+ ? 'Describe the content you want to generate... e.g., "Write a compelling blog intro about sustainable fashion"'
173
+ : activeTool === 'alt'
174
+ ? 'Paste an image URL to generate alt text...'
175
+ : activeTool === 'meta'
176
+ ? 'Paste your content to generate a meta description...'
177
+ : 'Paste text to analyze...';
178
+ return (_jsxs("div", { className: "flex flex-col h-[calc(100vh-64px)] overflow-hidden", children: [_jsx(PageHeader, { title: "AI Architect", description: "Generate content, design schemas, and analyze text quality", actions: _jsx("div", { className: cn('flex p-0.5 border', dark ? 'bg-black border-z-border' : 'bg-z-panel border-z-border'), children: MODES.map(m => (_jsxs("button", { onClick: () => { setMode(m.id); setResult(null); setSchemaForSave(null); }, title: m.desc, className: cn('flex items-center gap-2 px-4 py-2 text-[9px] font-black uppercase tracking-widest transition-all', mode === m.id
179
+ ? (dark ? 'bg-white text-black' : 'bg-gray-900 text-white')
180
+ : (dark ? 'text-z-secondary hover:text-white' : 'text-z-secondary hover:text-z-primary')), children: [_jsx(m.icon, { size: 11 }), _jsx("span", { className: "hidden sm:inline", children: m.label })] }, m.id))) }) }), _jsxs("div", { className: "flex flex-1 overflow-hidden", children: [_jsxs("div", { className: cn('w-56 flex-shrink-0 border-r flex flex-col hidden lg:flex', dark ? 'border-z-border bg-black' : 'border-z-border bg-gray-50'), children: [_jsx("div", { className: cn('px-4 py-3 border-b flex-shrink-0', dark ? 'border-z-border' : 'border-z-border'), children: _jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: "History" }) }), _jsxs("div", { className: "flex-1 overflow-y-auto p-2 space-y-1", children: [history.length === 0 && (_jsx("p", { className: "text-[8px] text-gray-600 uppercase tracking-widest p-2 text-center mt-4", children: "No history yet" })), history.map(h => (_jsxs("button", { onClick: () => { setResult(h.result); setSchemaForSave(h.mode === 'architect' ? h.result : null); }, className: cn('w-full text-left p-2.5 border border-transparent transition-all', dark ? 'hover:bg-z-hover hover:border-z-border' : 'hover:bg-white hover:border-z-border'), children: [_jsx("div", { className: "flex items-center gap-1.5 mb-1", children: _jsx("span", { className: cn('text-[7px] font-black uppercase tracking-widest', h.mode === 'architect' ? 'text-purple-400' : h.mode === 'tools' ? 'text-amber-400' : 'text-z-active-text'), children: h.mode }) }), _jsx("p", { className: "text-[9px] text-z-secondary truncate", children: h.prompt })] }, h.id)))] })] }), _jsxs("div", { className: "flex-1 flex flex-col min-w-0 border-r", style: { borderColor: dark ? 'rgba(255,255,255,0.08)' : '#e5e7eb' }, children: [_jsx(AnimatePresence, { children: mode === 'tools' && (_jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, className: cn('flex-shrink-0 border-b overflow-hidden', dark ? 'border-z-border' : 'border-z-border'), children: _jsx("div", { className: "p-3 flex gap-2 flex-wrap", children: TOOLS.map(tool => (_jsxs("button", { onClick: () => { setActiveTool(tool.id); setResult(null); }, title: tool.desc, className: cn('flex items-center gap-2 px-3 py-2 text-[9px] font-black uppercase tracking-widest border transition-all', activeTool === tool.id
181
+ ? (dark ? 'bg-white text-black border-white' : 'bg-gray-900 text-white border-gray-900')
182
+ : (dark ? 'border-z-border text-z-secondary hover:text-white hover:border-white/20' : 'border-z-border text-z-secondary hover:border-gray-400 hover:text-z-primary')), children: [_jsx(tool.icon, { size: 11, className: activeTool === tool.id ? '' : tool.color }), tool.name] }, tool.id))) }) })) }), _jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [_jsxs("div", { className: cn('flex-shrink-0 flex items-center gap-3 px-5 py-3 border-b', dark ? 'border-z-border' : 'border-z-border'), children: [_jsx(Terminal, { size: 12, className: "text-z-secondary" }), _jsx("span", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: mode === 'architect' ? 'Schema Prompt' : mode === 'writer' ? 'Content Prompt' : TOOLS.find(t => t.id === activeTool)?.name }), _jsx("span", { className: "ml-auto text-[8px] text-gray-600 uppercase tracking-widest hidden sm:block", children: "\u2318 + Enter to run" })] }), _jsx("textarea", { ref: textareaRef, value: prompt, onChange: e => setPrompt(e.target.value), onKeyDown: handleKeyDown, placeholder: activePlaceholder, className: cn('flex-1 w-full p-5 text-sm outline-none resize-none font-sans leading-relaxed', dark
183
+ ? 'bg-transparent text-white placeholder:text-gray-700'
184
+ : 'bg-transparent text-z-primary placeholder:text-z-muted') }), _jsx("div", { className: cn('flex-shrink-0 p-4 border-t', dark ? 'border-z-border' : 'border-z-border'), children: _jsxs("div", { className: "flex items-center gap-3", children: [prompt.trim() && (_jsx("button", { onClick: () => { setPrompt(''); setResult(null); }, className: "p-2.5 text-gray-600 hover:text-white transition-colors border border-transparent hover:border-white/10", title: "Clear", children: _jsx(RotateCcw, { size: 14 }) })), _jsx("button", { onClick: handleExecute, disabled: loading || (!prompt.trim() && activeTool !== 'alt'), className: cn('flex-1 py-3 font-black uppercase tracking-widest text-[10px] transition-all flex items-center justify-center gap-2.5', 'bg-z-accent hover:opacity-90 text-white', 'disabled:opacity-40 disabled:cursor-not-allowed', 'shadow-sm hover:shadow-sm'), children: loading
185
+ ? _jsxs(_Fragment, { children: [_jsx(Loader2, { size: 13, className: "animate-spin" }), " Generating\u2026"] })
186
+ : _jsxs(_Fragment, { children: [_jsx(Send, { size: 13 }), " ", mode === 'architect' ? 'Design Schema' : mode === 'writer' ? 'Generate Content' : 'Analyze'] }) })] }) })] })] }), _jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [_jsxs("div", { className: cn('flex-shrink-0 flex items-center justify-between px-5 py-3 border-b', dark ? 'border-z-border' : 'border-z-border'), children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx(Sparkles, { size: 12, className: result ? 'text-z-active-text' : 'text-z-secondary' }), _jsx("span", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: "Output" }), result && _jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-z-accent shadow-sm" })] }), result && (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: copyResult, title: "Copy", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: _jsx(Copy, { size: 13 }) }), _jsx("button", { onClick: downloadResult, title: "Download", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: _jsx(Download, { size: 13 }) }), mode === 'architect' && (_jsx("button", { onClick: () => { setResult(null); setSchemaForSave(null); }, title: "Clear", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: _jsx(RotateCcw, { size: 13 }) }))] }))] }), _jsx("div", { className: "flex-1 overflow-auto p-6", children: loading ? (_jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-4", children: [_jsxs("div", { className: "relative", children: [_jsx(Loader2, { size: 32, className: "animate-spin text-z-active-text" }), _jsx("div", { className: "absolute inset-0 blur-xl bg-z-accent/20 animate-pulse" })] }), _jsx("p", { className: "text-[9px] font-black uppercase tracking-[0.4em] text-z-secondary animate-pulse", children: mode === 'architect' ? 'Designing Schema…' : mode === 'writer' ? 'Writing Content…' : 'Analyzing…' })] })) : !result ? (_jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-5 opacity-30", children: [_jsx(Cpu, { size: 40, className: "text-z-secondary" }), _jsxs("div", { className: "text-center space-y-1", children: [_jsx("p", { className: "text-[9px] font-black uppercase tracking-[0.4em] text-z-secondary", children: "Awaiting Input" }), _jsx("p", { className: "text-[8px] text-gray-600 uppercase tracking-widest", children: mode === 'architect' ? 'Describe a collection to generate a schema' : mode === 'writer' ? 'Write a prompt to generate content' : 'Paste content to analyze' })] })] })) : (_jsx(AnimatePresence, { mode: "wait", children: _jsx(motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.2 }, children: renderResult() }, JSON.stringify(result).substring(0, 50)) })) }), _jsx(AnimatePresence, { children: result && mode === 'architect' && schemaForSave && (_jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, className: cn('flex-shrink-0 border-t overflow-hidden', dark ? 'border-z-border' : 'border-z-border'), children: _jsxs("div", { className: "px-5 py-3 flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-[8px] text-z-secondary uppercase tracking-widest", children: "Schema looks good? Save it as a live collection." }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { onClick: () => {
187
+ const text = JSON.stringify(schemaForSave, null, 2);
188
+ navigator.clipboard.writeText(text);
189
+ toast.success('Schema copied as JSON');
190
+ }, className: cn('px-4 py-2 border text-[9px] font-black uppercase tracking-widest flex items-center gap-2 transition-all', dark ? 'border-z-border text-z-muted hover:text-white hover:border-white/20' : 'border-z-border text-z-secondary hover:border-gray-400'), children: [_jsx(Code2, { size: 11 }), " Copy JSON"] }), _jsxs("button", { onClick: saveSchemaToDb, disabled: savingSchema, className: "px-5 py-2 bg-z-accent hover:opacity-90 text-white text-[9px] font-black uppercase tracking-widest flex items-center gap-2 transition-all disabled:opacity-50 shadow-sm", children: [savingSchema ? _jsx(Loader2, { size: 11, className: "animate-spin" }) : _jsx(Save, { size: 11 }), "Save Collection"] })] })] }) })) })] })] })] }));
191
+ };
192
+ export default AIWriterPage;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface SettingsAiProps {
3
+ settings: Record<string, any>;
4
+ setSettings: (s: any) => void;
5
+ theme: 'light' | 'dark';
6
+ }
7
+ declare const SettingsAi: React.FC<SettingsAiProps>;
8
+ export default SettingsAi;
@@ -0,0 +1,245 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Lock, Loader2, CheckCircle2, AlertCircle, ExternalLink, Eye, EyeOff, Cpu, Zap, ChevronRight, Info, TestTube2 } from 'lucide-react';
4
+ import { cn } from '../../lib/utils';
5
+ import api from '../../lib/api';
6
+ import toast from 'react-hot-toast';
7
+ const PROVIDERS = [
8
+ {
9
+ id: 'openrouter',
10
+ name: 'OpenRouter',
11
+ color: 'text-z-active-text',
12
+ description: 'Unified gateway to 200+ models from any provider via one API key',
13
+ docsUrl: 'https://openrouter.ai/keys',
14
+ keyPlaceholder: 'sk-or-v1-...',
15
+ keyField: 'openRouterApiKey',
16
+ badge: 'Recommended',
17
+ models: [
18
+ { value: 'anthropic/claude-3.5-sonnet', label: 'Claude 3.5 Sonnet', tier: 'pro' },
19
+ { value: 'anthropic/claude-3.5-haiku', label: 'Claude 3.5 Haiku', tier: 'pro' },
20
+ { value: 'anthropic/claude-3-opus', label: 'Claude 3 Opus', tier: 'ultra' },
21
+ { value: 'openai/gpt-4o', label: 'GPT-4o', tier: 'pro' },
22
+ { value: 'openai/gpt-4o-mini', label: 'GPT-4o Mini', tier: 'free' },
23
+ { value: 'openai/gpt-4-turbo', label: 'GPT-4 Turbo', tier: 'pro' },
24
+ { value: 'google/gemini-pro-1.5', label: 'Gemini 1.5 Pro', tier: 'pro' },
25
+ { value: 'google/gemini-flash-1.5', label: 'Gemini 1.5 Flash', tier: 'free' },
26
+ { value: 'meta-llama/llama-3.3-70b-instruct', label: 'Llama 3.3 70B', tier: 'free' },
27
+ { value: 'mistralai/mistral-large', label: 'Mistral Large', tier: 'pro' },
28
+ { value: 'mistralai/mixtral-8x7b-instruct', label: 'Mixtral 8x7B', tier: 'free' },
29
+ { value: 'deepseek/deepseek-r1', label: 'DeepSeek R1', tier: 'pro' },
30
+ { value: 'x-ai/grok-beta', label: 'Grok Beta', tier: 'pro' },
31
+ { value: 'cohere/command-r-plus', label: 'Cohere Command R+', tier: 'pro' },
32
+ { value: 'perplexity/llama-3.1-sonar-large-128k-online', label: 'Perplexity Sonar Large', tier: 'pro' },
33
+ ],
34
+ },
35
+ {
36
+ id: 'openai',
37
+ name: 'OpenAI',
38
+ color: 'text-z-active-text',
39
+ description: 'Direct access to GPT-4o, o1, and all OpenAI models',
40
+ docsUrl: 'https://platform.openai.com/api-keys',
41
+ keyPlaceholder: 'sk-proj-...',
42
+ keyField: 'openaiApiKey',
43
+ models: [
44
+ { value: 'gpt-4o', label: 'GPT-4o', tier: 'pro' },
45
+ { value: 'gpt-4o-mini', label: 'GPT-4o Mini', tier: 'free' },
46
+ { value: 'gpt-4-turbo', label: 'GPT-4 Turbo', tier: 'pro' },
47
+ { value: 'o1-preview', label: 'o1 Preview', tier: 'ultra' },
48
+ { value: 'o1-mini', label: 'o1 Mini', tier: 'pro' },
49
+ { value: 'o3-mini', label: 'o3 Mini', tier: 'pro' },
50
+ ],
51
+ },
52
+ {
53
+ id: 'anthropic',
54
+ name: 'Anthropic',
55
+ color: 'text-orange-400',
56
+ description: 'Direct access to Claude models with vision and context support',
57
+ docsUrl: 'https://console.anthropic.com/settings/keys',
58
+ keyPlaceholder: 'sk-ant-...',
59
+ keyField: 'anthropicApiKey',
60
+ models: [
61
+ { value: 'claude-3-5-sonnet-20241022', label: 'Claude 3.5 Sonnet', tier: 'pro' },
62
+ { value: 'claude-3-5-haiku-20241022', label: 'Claude 3.5 Haiku', tier: 'free' },
63
+ { value: 'claude-3-opus-20240229', label: 'Claude 3 Opus', tier: 'ultra' },
64
+ ],
65
+ },
66
+ {
67
+ id: 'google',
68
+ name: 'Google Gemini',
69
+ color: 'text-z-active-text',
70
+ description: 'Gemini Pro/Flash with long context and multimodal capabilities',
71
+ docsUrl: 'https://aistudio.google.com/app/apikey',
72
+ keyPlaceholder: 'AIza...',
73
+ keyField: 'googleApiKey',
74
+ models: [
75
+ { value: 'gemini-1.5-pro-latest', label: 'Gemini 1.5 Pro', tier: 'pro' },
76
+ { value: 'gemini-1.5-flash-latest', label: 'Gemini 1.5 Flash', tier: 'free' },
77
+ { value: 'gemini-2.0-flash-exp', label: 'Gemini 2.0 Flash', tier: 'pro' },
78
+ ],
79
+ },
80
+ {
81
+ id: 'groq',
82
+ name: 'Groq',
83
+ color: 'text-pink-400',
84
+ description: 'Ultra-fast inference with LPU hardware — 800+ tokens/sec',
85
+ docsUrl: 'https://console.groq.com/keys',
86
+ keyPlaceholder: 'gsk_...',
87
+ keyField: 'groqApiKey',
88
+ badge: 'Fastest',
89
+ models: [
90
+ { value: 'llama-3.3-70b-versatile', label: 'Llama 3.3 70B', tier: 'free' },
91
+ { value: 'llama-3.1-8b-instant', label: 'Llama 3.1 8B Instant', tier: 'free' },
92
+ { value: 'mixtral-8x7b-32768', label: 'Mixtral 8x7B', tier: 'free' },
93
+ { value: 'gemma2-9b-it', label: 'Gemma 2 9B', tier: 'free' },
94
+ ],
95
+ },
96
+ {
97
+ id: 'nvidia',
98
+ name: 'NVIDIA NIM',
99
+ color: 'text-green-400',
100
+ description: 'NVIDIA-hosted models with GPU-accelerated inference',
101
+ docsUrl: 'https://build.nvidia.com/explore/discover',
102
+ keyPlaceholder: 'nvapi-...',
103
+ keyField: 'nvidiaApiKey',
104
+ models: [
105
+ { value: 'meta/llama-3.1-405b-instruct', label: 'Llama 3.1 405B', tier: 'ultra' },
106
+ { value: 'meta/llama-3.1-70b-instruct', label: 'Llama 3.1 70B', tier: 'pro' },
107
+ { value: 'meta/llama-3.1-8b-instruct', label: 'Llama 3.1 8B', tier: 'free' },
108
+ { value: 'mistralai/mistral-large-2-instruct', label: 'Mistral Large 2', tier: 'pro' },
109
+ { value: 'nvidia/llama-3.1-nemotron-70b-instruct', label: 'Nemotron 70B', tier: 'pro' },
110
+ ],
111
+ },
112
+ {
113
+ id: 'together',
114
+ name: 'Together AI',
115
+ color: 'text-yellow-400',
116
+ description: 'Open-source models on fast distributed inference infrastructure',
117
+ docsUrl: 'https://api.together.xyz/settings/api-keys',
118
+ keyPlaceholder: 'together-...',
119
+ keyField: 'togetherApiKey',
120
+ models: [
121
+ { value: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', label: 'Llama 3.3 70B Turbo', tier: 'pro' },
122
+ { value: 'mistralai/Mixtral-8x7B-Instruct-v0.1', label: 'Mixtral 8x7B', tier: 'free' },
123
+ { value: 'deepseek-ai/DeepSeek-R1', label: 'DeepSeek R1', tier: 'pro' },
124
+ ],
125
+ },
126
+ {
127
+ id: 'mistral',
128
+ name: 'Mistral AI',
129
+ color: 'text-amber-400',
130
+ description: 'Direct access to Mistral, Codestral, and Pixtral models',
131
+ docsUrl: 'https://console.mistral.ai/api-keys',
132
+ keyPlaceholder: 'mistral-...',
133
+ keyField: 'mistralApiKey',
134
+ models: [
135
+ { value: 'mistral-large-latest', label: 'Mistral Large', tier: 'pro' },
136
+ { value: 'mistral-small-latest', label: 'Mistral Small', tier: 'free' },
137
+ { value: 'codestral-latest', label: 'Codestral', tier: 'pro' },
138
+ { value: 'pixtral-large-latest', label: 'Pixtral Large', tier: 'ultra' },
139
+ ],
140
+ },
141
+ {
142
+ id: 'cohere',
143
+ name: 'Cohere',
144
+ color: 'text-teal-400',
145
+ description: 'Enterprise-grade models optimized for search and RAG workflows',
146
+ docsUrl: 'https://dashboard.cohere.com/api-keys',
147
+ keyPlaceholder: 'co_...',
148
+ keyField: 'cohereApiKey',
149
+ models: [
150
+ { value: 'command-r-plus', label: 'Command R+', tier: 'ultra' },
151
+ { value: 'command-r', label: 'Command R', tier: 'pro' },
152
+ { value: 'command-light', label: 'Command Light', tier: 'free' },
153
+ ],
154
+ },
155
+ {
156
+ id: 'xai',
157
+ name: 'xAI / Grok',
158
+ color: 'text-gray-300',
159
+ description: "Elon Musk's xAI Grok model with real-time X/Twitter integration",
160
+ docsUrl: 'https://console.x.ai/',
161
+ keyPlaceholder: 'xai-...',
162
+ keyField: 'xaiApiKey',
163
+ models: [
164
+ { value: 'grok-beta', label: 'Grok Beta', tier: 'pro' },
165
+ { value: 'grok-vision-beta', label: 'Grok Vision Beta', tier: 'pro' },
166
+ ],
167
+ },
168
+ ];
169
+ const TIER_BADGE = {
170
+ free: 'bg-z-active-bg text-z-active-text border-z-accent/20',
171
+ pro: 'bg-z-accent/10 text-z-active-text border-z-accent/20',
172
+ ultra: 'bg-purple-500/10 text-purple-400 border-purple-500/20',
173
+ };
174
+ const SettingsAi = ({ settings, setSettings, theme }) => {
175
+ const dark = theme === 'dark';
176
+ const [validating, setValidating] = useState(false);
177
+ const [testResult, setTestResult] = useState(null);
178
+ const [showKeys, setShowKeys] = useState({});
179
+ const [expandedProvider, setExpandedProvider] = useState('openrouter');
180
+ const [dynamicModels, setDynamicModels] = useState({});
181
+ const [fetchingModels, setFetchingModels] = useState(null);
182
+ const activeProvider = PROVIDERS.find(p => {
183
+ const key = settings[p.keyField]?.trim();
184
+ return key && key !== '[MASKED_CREDENTIAL]';
185
+ }) || PROVIDERS.find(p => p.id === 'openrouter');
186
+ const handleValidate = async () => {
187
+ setValidating(true);
188
+ setTestResult(null);
189
+ try {
190
+ const providerId = settings.aiProvider || 'openrouter';
191
+ const providerConfig = PROVIDERS.find(p => p.id === providerId);
192
+ const apiKeyField = providerConfig ? providerConfig.keyField : 'openRouterApiKey';
193
+ const apiKey = settings[apiKeyField];
194
+ const res = await api.post('/system/settings/ai/validate', {
195
+ provider: providerId,
196
+ model: settings.aiModel,
197
+ apiKey: apiKey
198
+ });
199
+ setTestResult({ ok: true, msg: res.data.message || 'API Key is valid' });
200
+ toast.success('AI connection verified');
201
+ }
202
+ catch (err) {
203
+ const msg = err?.response?.data?.error?.message || err?.response?.data?.message || 'Connection failed';
204
+ setTestResult({ ok: false, msg });
205
+ toast.error('AI connection failed');
206
+ }
207
+ finally {
208
+ setValidating(false);
209
+ }
210
+ };
211
+ const handleFetchModels = async (providerId, apiKeyField) => {
212
+ setFetchingModels(providerId);
213
+ try {
214
+ const apiKey = settings[apiKeyField];
215
+ const res = await api.post('/system/settings/ai/models', {
216
+ provider: providerId,
217
+ apiKey: apiKey
218
+ });
219
+ const models = res.data?.data || [];
220
+ setDynamicModels(prev => ({ ...prev, [providerId]: models }));
221
+ toast.success(`Fetched ${models.length} models for ${providerId}`);
222
+ }
223
+ catch (err) {
224
+ const msg = err?.response?.data?.error?.message || err?.response?.data?.message || 'Failed to fetch models';
225
+ toast.error(msg);
226
+ }
227
+ finally {
228
+ setFetchingModels(null);
229
+ }
230
+ };
231
+ const toggleKey = (id) => setShowKeys(prev => ({ ...prev, [id]: !prev[id] }));
232
+ const inp = (dark) => cn('w-full border px-3 py-2.5 text-sm font-semibold outline-none transition-colors rounded-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black', dark
233
+ ? 'bg-black border-z-border text-white placeholder:text-gray-700 focus:border-z-accent'
234
+ : 'bg-z-panel border-z-border text-z-primary placeholder:text-z-muted focus:border-z-accent');
235
+ return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: cn('p-5 border space-y-4 shadow-sm', dark ? 'bg-z-panel backdrop-blur-md border-z-border' : 'bg-z-input border-z-border'), children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx(Cpu, { size: 14, className: "text-z-active-text" }), _jsx("span", { className: cn('text-sm font-semibold ', dark ? 'text-white' : 'text-z-primary'), children: "Active Model" }), _jsx("span", { className: "ml-auto text-sm text-z-secondary", children: "Used by all AI features" })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-sm font-semibold text-z-secondary", children: "AI Provider" }), _jsx("select", { value: settings.aiProvider || 'openrouter', onChange: e => setSettings({ ...settings, aiProvider: e.target.value, aiModel: PROVIDERS.find(p => p.id === e.target.value)?.models[0]?.value || '' }), className: inp(dark), children: PROVIDERS.map(p => _jsx("option", { value: p.id, children: p.name }, p.id)) })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-sm font-semibold text-z-secondary", children: "Model" }), _jsx("select", { value: settings.aiModel || '', onChange: e => setSettings({ ...settings, aiModel: e.target.value }), className: inp(dark), children: (dynamicModels[settings.aiProvider || 'openrouter'] || PROVIDERS.find(p => p.id === (settings.aiProvider || 'openrouter'))?.models || []).map(m => (_jsxs("option", { value: m.value, children: [m.label, " ", m.tier ? `(${m.tier})` : ''] }, m.value))) })] })] }), _jsxs("div", { className: "flex items-center gap-3 pt-1", children: [_jsxs("button", { onClick: handleValidate, disabled: validating, className: "px-4 py-2 bg-z-accent hover:opacity-90 shadow-sm text-white text-sm font-semibold flex items-center gap-2 disabled:opacity-50 transition-all", children: [validating ? _jsx(Loader2, { size: 11, className: "animate-spin" }) : _jsx(TestTube2, { size: 11 }), "Test Connection"] }), testResult && (_jsxs("div", { className: cn('flex items-center gap-2 text-sm font-semibold ', testResult.ok ? 'text-z-active-text' : 'text-red-400'), children: [testResult.ok ? _jsx(CheckCircle2, { size: 11 }) : _jsx(AlertCircle, { size: 11 }), testResult.msg] }))] })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx(Lock, { size: 12, className: "text-z-secondary" }), _jsx("span", { className: "text-sm font-semibold text-z-secondary", children: "Provider API Keys" }), _jsx("span", { className: "ml-auto text-sm text-gray-600", children: "All keys encrypted at rest" })] }), PROVIDERS.map(provider => {
236
+ const isExpanded = expandedProvider === provider.id;
237
+ const keyValue = settings[provider.keyField] || '';
238
+ const hasKey = keyValue.trim() && keyValue !== '[MASKED_CREDENTIAL]';
239
+ const isMasked = keyValue === '[MASKED_CREDENTIAL]';
240
+ return (_jsxs("div", { className: cn('border transition-all shadow-sm', isExpanded
241
+ ? (dark ? 'border-white/15 bg-black/80 backdrop-blur-md shadow-sm' : 'border-z-border-strong bg-white')
242
+ : ('z-card-interactive')), children: [_jsxs("button", { onClick: () => setExpandedProvider(isExpanded ? '' : provider.id), className: "w-full flex items-center gap-3 px-4 py-3 text-left", children: [_jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [_jsx("div", { className: cn('w-2 h-2 rounded-full flex-shrink-0', hasKey || isMasked ? 'bg-z-accent shadow-sm' : 'bg-gray-700') }), _jsx("div", { className: cn('text-sm font-semibold', provider.color), children: provider.name }), provider.badge && (_jsx("span", { className: "text-sm font-semibold px-1.5 py-0.5 bg-z-active-bg border border-z-active-border text-z-active-text", children: provider.badge })), _jsx("span", { className: "text-sm text-gray-600 truncate hidden sm:block", children: provider.description })] }), _jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [isMasked && _jsx("span", { className: "text-sm text-z-active-text font-semibold", children: "Configured" }), hasKey && !isMasked && _jsx("span", { className: "text-sm text-z-active-text font-semibold", children: "Active" }), _jsx(ChevronRight, { size: 12, className: cn('text-z-secondary transition-transform', isExpanded && 'rotate-90') })] })] }), isExpanded && (_jsxs("div", { className: "px-4 pb-4 space-y-3 border-t", style: { borderColor: dark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)' }, children: [_jsx("p", { className: "text-sm text-z-secondary pt-3", children: provider.description }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-semibold text-z-secondary", children: "API Key" }), _jsxs("a", { href: provider.docsUrl, target: "_blank", rel: "noopener noreferrer", className: "text-sm text-z-active-text hover:text-z-active-text flex items-center gap-1 transition-colors", children: ["Get Key ", _jsx(ExternalLink, { size: 9 })] })] }), _jsxs("div", { className: "relative", children: [_jsx("input", { type: showKeys[provider.id] ? 'text' : 'password', value: keyValue, onChange: e => setSettings({ ...settings, [provider.keyField]: e.target.value }), placeholder: isMasked ? '••••••••••••••••' : provider.keyPlaceholder, className: cn(inp(dark), 'pr-10 font-mono') }), _jsx("button", { type: "button", onClick: () => toggleKey(provider.id), className: "absolute right-3 top-1/2 -translate-y-1/2 text-z-secondary hover:text-white transition-colors", children: showKeys[provider.id] ? _jsx(EyeOff, { size: 13 }) : _jsx(Eye, { size: 13 }) })] }), isMasked && (_jsxs("p", { className: "text-sm text-amber-500/70 flex items-center gap-1", children: [_jsx(Lock, { size: 9 }), " Key is stored \u2014 enter a new value to replace it"] }))] }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("label", { className: "text-sm font-semibold text-z-secondary", children: ["Available Models ", dynamicModels[provider.id] ? `(${dynamicModels[provider.id].length})` : ''] }), _jsxs("button", { type: "button", onClick: () => handleFetchModels(provider.id, provider.keyField), disabled: fetchingModels === provider.id || (!hasKey && !isMasked), className: "text-sm text-z-active-text hover:text-z-active-text flex items-center gap-1 disabled:opacity-50 transition-colors", children: [fetchingModels === provider.id ? _jsx(Loader2, { size: 9, className: "animate-spin" }) : _jsx(Zap, { size: 9 }), "Fetch Models"] })] }), _jsx("div", { className: "flex flex-wrap gap-1.5 max-h-[120px] overflow-y-auto pr-2 custom-scrollbar", children: (dynamicModels[provider.id] || provider.models).map(m => (_jsx("span", { title: m.value, className: cn('text-sm font-semibold px-2 py-1 border', m.tier ? TIER_BADGE[m.tier] : 'bg-z-hover border-white/10 text-z-muted'), children: m.label }, m.value))) })] })] }))] }, provider.id));
243
+ })] }), _jsxs("div", { className: cn('flex gap-3 p-4 border', dark ? 'bg-z-accent/5 border-z-accent/15' : 'bg-z-active-bg border-z-active-border'), children: [_jsx(Info, { size: 12, className: "text-z-active-text flex-shrink-0 mt-0.5" }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-semibold text-z-active-text", children: "Provider Priority" }), _jsx("p", { className: "text-sm text-z-secondary leading-relaxed", children: "The AI engine auto-selects providers in this order: OpenRouter \u2192 xAI \u2192 NVIDIA NIM \u2192 Groq \u2192 Together AI \u2192 Mistral \u2192 Cohere \u2192 OpenAI \u2192 Anthropic \u2192 Google Gemini. Set the \"Active Model\" above to override. Keys are never sent to the client." })] })] })] }));
244
+ };
245
+ export default SettingsAi;
@@ -0,0 +1 @@
1
+ export * from './plugin';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './plugin';
@@ -1,55 +1,60 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect } from 'react';
3
- import { Sparkles, Send, Loader2, Copy, Zap, Terminal, Cpu, PenTool, ShieldCheck, Search, Image as ImageIcon, CheckCircle2, AlertCircle, ChevronRight, RotateCcw, Save, Download, Code2, Wand2, Hash } from 'lucide-react';
4
- import api from '../../admin/src/lib/api';
5
- import { motion, AnimatePresence } from 'framer-motion';
6
- import { cn } from '../../admin/src/lib/utils';
7
- import toast from 'react-hot-toast';
8
- import { useTheme } from '../../admin/src/context/ThemeContext';
9
- import { PageHeader } from '../../admin/src/components/ui/PageHeader';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const lucide_react_1 = require("lucide-react");
9
+ const api_1 = __importDefault(require("../../admin/src/lib/api"));
10
+ const framer_motion_1 = require("framer-motion");
11
+ const utils_1 = require("../../admin/src/lib/utils");
12
+ const react_hot_toast_1 = __importDefault(require("react-hot-toast"));
13
+ const ThemeContext_1 = require("../../admin/src/context/ThemeContext");
14
+ const PageHeader_1 = require("../../admin/src/components/ui/PageHeader");
10
15
  // ── Tool Definitions ───────────────────────────────────────────────────────────
11
16
  const TOOLS = [
12
- { id: 'seo', name: 'SEO Analysis', icon: Search, endpoint: '/content-tools/seo-analysis', desc: 'Score title, meta, content', color: 'text-amber-400' },
13
- { id: 'quality', name: 'Quality Audit', icon: ShieldCheck, endpoint: '/content-tools/quality', desc: 'Readability + word structure', color: 'text-z-active-text' },
14
- { id: 'improve', name: 'Refine Text', icon: Wand2, endpoint: '/content-tools/ai/improve', desc: 'AI-powered rewrite', color: 'text-purple-400' },
15
- { id: 'meta', name: 'Meta Generator', icon: Hash, endpoint: '/content-tools/ai/meta-description', desc: 'Auto SEO meta description', color: 'text-z-active-text' },
16
- { id: 'alt', name: 'Alt Text', icon: ImageIcon, endpoint: '/content-tools/ai/alt-text', desc: 'Generate image alt text', color: 'text-pink-400' },
17
+ { id: 'seo', name: 'SEO Analysis', icon: lucide_react_1.Search, endpoint: '/content-tools/seo-analysis', desc: 'Score title, meta, content', color: 'text-amber-400' },
18
+ { id: 'quality', name: 'Quality Audit', icon: lucide_react_1.ShieldCheck, endpoint: '/content-tools/quality', desc: 'Readability + word structure', color: 'text-z-active-text' },
19
+ { id: 'improve', name: 'Refine Text', icon: lucide_react_1.Wand2, endpoint: '/content-tools/ai/improve', desc: 'AI-powered rewrite', color: 'text-purple-400' },
20
+ { id: 'meta', name: 'Meta Generator', icon: lucide_react_1.Hash, endpoint: '/content-tools/ai/meta-description', desc: 'Auto SEO meta description', color: 'text-z-active-text' },
21
+ { id: 'alt', name: 'Alt Text', icon: lucide_react_1.Image, endpoint: '/content-tools/ai/alt-text', desc: 'Generate image alt text', color: 'text-pink-400' },
17
22
  ];
18
23
  const MODES = [
19
- { id: 'writer', label: 'Writer', icon: PenTool, desc: 'Generate content from a prompt' },
20
- { id: 'architect', label: 'Architect', icon: Cpu, desc: 'Design a collection schema with AI' },
21
- { id: 'tools', label: 'Tools', icon: Zap, desc: 'SEO, quality, meta & more' },
24
+ { id: 'writer', label: 'Writer', icon: lucide_react_1.PenTool, desc: 'Generate content from a prompt' },
25
+ { id: 'architect', label: 'Architect', icon: lucide_react_1.Cpu, desc: 'Design a collection schema with AI' },
26
+ { id: 'tools', label: 'Tools', icon: lucide_react_1.Zap, desc: 'SEO, quality, meta & more' },
22
27
  ];
23
28
  // ── Result Renderers ──────────────────────────────────────────────────────────
24
29
  function SeoResultView({ data }) {
25
- return (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "flex items-end gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary mb-1", children: "SEO Score" }), _jsx("span", { className: cn('text-5xl font-black tabular-nums', data.score >= 70 ? 'text-z-active-text' : data.score >= 45 ? 'text-amber-400' : 'text-red-400'), children: data.score }), _jsx("span", { className: "text-lg text-z-secondary font-black", children: "/100" })] }), _jsx("div", { className: "flex-1 h-2 bg-z-hover rounded-full overflow-hidden mb-3", children: _jsx("div", { className: cn('h-full transition-all duration-700', data.score >= 70 ? 'bg-z-accent' : data.score >= 45 ? 'bg-amber-500' : 'bg-red-500'), style: { width: `${data.score}%` } }) })] }), data.passed?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-active-text/70", children: "Passing" }), data.passed.map((p, i) => (_jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(CheckCircle2, { size: 11, className: "text-z-active-text flex-shrink-0" }), p] }, i)))] })), data.issues?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-red-500/70", children: "Issues" }), data.issues.map((p, i) => (_jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(AlertCircle, { size: 11, className: "text-red-500 flex-shrink-0" }), p] }, i)))] })), data.suggestions?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-amber-500/70", children: "Suggestions" }), data.suggestions.map((p, i) => (_jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(ChevronRight, { size: 11, className: "text-amber-500 flex-shrink-0" }), p] }, i)))] }))] }));
30
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-end gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary mb-1", children: "SEO Score" }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-5xl font-black tabular-nums', data.score >= 70 ? 'text-z-active-text' : data.score >= 45 ? 'text-amber-400' : 'text-red-400'), children: data.score }), (0, jsx_runtime_1.jsx)("span", { className: "text-lg text-z-secondary font-black", children: "/100" })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 h-2 bg-z-hover rounded-full overflow-hidden mb-3", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('h-full transition-all duration-700', data.score >= 70 ? 'bg-z-accent' : data.score >= 45 ? 'bg-amber-500' : 'bg-red-500'), style: { width: `${data.score}%` } }) })] }), data.passed?.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-active-text/70", children: "Passing" }), data.passed.map((p, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle2, { size: 11, className: "text-z-active-text flex-shrink-0" }), p] }, i)))] })), data.issues?.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-red-500/70", children: "Issues" }), data.issues.map((p, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { size: 11, className: "text-red-500 flex-shrink-0" }), p] }, i)))] })), data.suggestions?.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-amber-500/70", children: "Suggestions" }), data.suggestions.map((p, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 11, className: "text-amber-500 flex-shrink-0" }), p] }, i)))] }))] }));
26
31
  }
27
32
  function QualityResultView({ data }) {
28
33
  const gradeColor = { A: 'text-z-active-text', B: 'text-z-active-text', C: 'text-amber-400', D: 'text-orange-400', F: 'text-red-400' };
29
- return (_jsxs("div", { className: "space-y-5", children: [_jsxs("div", { className: "flex items-start gap-6", children: [_jsxs("div", { children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary mb-1", children: "Grade" }), _jsx("span", { className: cn('text-6xl font-black', gradeColor[data.grade] || 'text-white'), children: data.grade })] }), _jsx("div", { className: "grid grid-cols-3 gap-3 flex-1 pt-1", children: [
34
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-6", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary mb-1", children: "Grade" }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-6xl font-black', gradeColor[data.grade] || 'text-white'), children: data.grade })] }), (0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-3 gap-3 flex-1 pt-1", children: [
30
35
  { label: 'Words', val: data.wordCount },
31
36
  { label: 'Sentences', val: data.sentenceCount },
32
37
  { label: 'Avg Words/Sent', val: data.avgWordsPerSentence },
33
- ].map(m => (_jsxs("div", { className: "bg-z-hover border border-z-border p-3", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-widest text-z-secondary mb-1", children: m.label }), _jsx("p", { className: "text-lg font-black text-white tabular-nums", children: m.val })] }, m.label))) })] }), data.issues?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-red-500/70", children: "Issues" }), data.issues.map((p, i) => _jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(AlertCircle, { size: 11, className: "text-red-500 flex-shrink-0" }), p] }, i))] })), data.suggestions?.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-active-text/70", children: "Suggestions" }), data.suggestions.map((p, i) => _jsxs("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [_jsx(CheckCircle2, { size: 11, className: "text-z-active-text flex-shrink-0" }), p] }, i))] }))] }));
38
+ ].map(m => ((0, jsx_runtime_1.jsxs)("div", { className: "bg-z-hover border border-z-border p-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-widest text-z-secondary mb-1", children: m.label }), (0, jsx_runtime_1.jsx)("p", { className: "text-lg font-black text-white tabular-nums", children: m.val })] }, m.label))) })] }), data.issues?.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-red-500/70", children: "Issues" }), data.issues.map((p, i) => (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { size: 11, className: "text-red-500 flex-shrink-0" }), p] }, i))] })), data.suggestions?.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-active-text/70", children: "Suggestions" }), data.suggestions.map((p, i) => (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5 text-[10px] text-z-muted", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle2, { size: 11, className: "text-z-active-text flex-shrink-0" }), p] }, i))] }))] }));
34
39
  }
35
40
  function SchemaResultView({ data }) {
36
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3 flex-wrap", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-black text-white tracking-tight", children: data.name }), _jsxs("p", { className: "text-[9px] text-z-secondary font-mono mt-0.5", children: ["/", data.slug] })] }), _jsxs("div", { className: "flex gap-2", children: [data.drafts && _jsx("span", { className: "px-2 py-0.5 text-[7px] font-black uppercase tracking-widest bg-z-accent/10 border border-z-accent/20 text-z-active-text", children: "Drafts" }), data.timestamps && _jsx("span", { className: "px-2 py-0.5 text-[7px] font-black uppercase tracking-widest bg-gray-500/10 border border-gray-500/20 text-z-muted", children: "Timestamps" })] })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: [data.fields?.length || 0, " Fields"] }), data.fields?.map((f, i) => (_jsxs("div", { className: "flex items-center justify-between px-3 py-2 bg-z-hover border border-z-border hover:border-z-border-strong transition-colors group", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-[9px] font-mono text-z-active-text", children: f.name }), f.required && _jsx("span", { className: "text-[6px] font-black text-red-500 uppercase tracking-wider", children: "required" })] }), _jsx("span", { className: "text-[8px] text-gray-600 uppercase tracking-widest font-black", children: f.type })] }, i)))] })] }));
41
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between gap-3 flex-wrap", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-lg font-black text-white tracking-tight", children: data.name }), (0, jsx_runtime_1.jsxs)("p", { className: "text-[9px] text-z-secondary font-mono mt-0.5", children: ["/", data.slug] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [data.drafts && (0, jsx_runtime_1.jsx)("span", { className: "px-2 py-0.5 text-[7px] font-black uppercase tracking-widest bg-z-accent/10 border border-z-accent/20 text-z-active-text", children: "Drafts" }), data.timestamps && (0, jsx_runtime_1.jsx)("span", { className: "px-2 py-0.5 text-[7px] font-black uppercase tracking-widest bg-gray-500/10 border border-gray-500/20 text-z-muted", children: "Timestamps" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsxs)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: [data.fields?.length || 0, " Fields"] }), data.fields?.map((f, i) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between px-3 py-2 bg-z-hover border border-z-border hover:border-z-border-strong transition-colors group", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-[9px] font-mono text-z-active-text", children: f.name }), f.required && (0, jsx_runtime_1.jsx)("span", { className: "text-[6px] font-black text-red-500 uppercase tracking-wider", children: "required" })] }), (0, jsx_runtime_1.jsx)("span", { className: "text-[8px] text-gray-600 uppercase tracking-widest font-black", children: f.type })] }, i)))] })] }));
37
42
  }
38
43
  // ── Main Component ─────────────────────────────────────────────────────────────
39
44
  const AIWriterPage = () => {
40
- const { theme } = useTheme();
45
+ const { theme } = (0, ThemeContext_1.useTheme)();
41
46
  const dark = theme === 'dark';
42
- const [mode, setMode] = useState('writer');
43
- const [prompt, setPrompt] = useState('');
44
- const [loading, setLoading] = useState(false);
45
- const [result, setResult] = useState(null);
46
- const [activeTool, setActiveTool] = useState('seo');
47
- const [history, setHistory] = useState([]);
48
- const [schemaForSave, setSchemaForSave] = useState(null);
49
- const [savingSchema, setSavingSchema] = useState(false);
50
- const textareaRef = useRef(null);
47
+ const [mode, setMode] = (0, react_1.useState)('writer');
48
+ const [prompt, setPrompt] = (0, react_1.useState)('');
49
+ const [loading, setLoading] = (0, react_1.useState)(false);
50
+ const [result, setResult] = (0, react_1.useState)(null);
51
+ const [activeTool, setActiveTool] = (0, react_1.useState)('seo');
52
+ const [history, setHistory] = (0, react_1.useState)([]);
53
+ const [schemaForSave, setSchemaForSave] = (0, react_1.useState)(null);
54
+ const [savingSchema, setSavingSchema] = (0, react_1.useState)(false);
55
+ const textareaRef = (0, react_1.useRef)(null);
51
56
  // Auto-resize textarea
52
- useEffect(() => {
57
+ (0, react_1.useEffect)(() => {
53
58
  if (textareaRef.current) {
54
59
  textareaRef.current.style.height = 'auto';
55
60
  textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 300)}px`;
@@ -65,12 +70,12 @@ const AIWriterPage = () => {
65
70
  let res;
66
71
  let resultData;
67
72
  if (mode === 'architect') {
68
- res = await api.post('/system/ai-architect', { prompt });
73
+ res = await api_1.default.post('/system/ai-architect', { prompt });
69
74
  resultData = res.data.data.schema;
70
75
  setSchemaForSave(resultData);
71
76
  }
72
77
  else if (mode === 'writer') {
73
- res = await api.post('/content-tools/ai/generate', { prompt });
78
+ res = await api_1.default.post('/content-tools/ai/generate', { prompt });
74
79
  resultData = res.data.data.text;
75
80
  }
76
81
  else {
@@ -88,7 +93,7 @@ const AIWriterPage = () => {
88
93
  else if (activeTool === 'alt') {
89
94
  payload = { imageUrl: prompt };
90
95
  }
91
- res = await api.post(tool.endpoint, payload);
96
+ res = await api_1.default.post(tool.endpoint, payload);
92
97
  const d = res.data.data;
93
98
  if (activeTool === 'seo')
94
99
  resultData = d;
@@ -109,11 +114,11 @@ const AIWriterPage = () => {
109
114
  result: resultData,
110
115
  timestamp: new Date()
111
116
  }, ...prev.slice(0, 19)]);
112
- toast.success('Generated');
117
+ react_hot_toast_1.default.success('Generated');
113
118
  }
114
119
  catch (err) {
115
120
  const msg = err?.response?.data?.error?.message || err?.response?.data?.message || 'AI request failed';
116
- toast.error(msg);
121
+ react_hot_toast_1.default.error(msg);
117
122
  }
118
123
  finally {
119
124
  setLoading(false);
@@ -128,12 +133,12 @@ const AIWriterPage = () => {
128
133
  return;
129
134
  setSavingSchema(true);
130
135
  try {
131
- await api.post('/schemas', schemaForSave);
132
- toast.success(`Collection "${schemaForSave.name}" created!`);
136
+ await api_1.default.post('/schemas', schemaForSave);
137
+ react_hot_toast_1.default.success(`Collection "${schemaForSave.name}" created!`);
133
138
  setSchemaForSave(null);
134
139
  }
135
140
  catch (err) {
136
- toast.error(err?.response?.data?.error?.message || 'Failed to save schema');
141
+ react_hot_toast_1.default.error(err?.response?.data?.error?.message || 'Failed to save schema');
137
142
  }
138
143
  finally {
139
144
  setSavingSchema(false);
@@ -142,7 +147,7 @@ const AIWriterPage = () => {
142
147
  const copyResult = () => {
143
148
  const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
144
149
  navigator.clipboard.writeText(text);
145
- toast.success('Copied to clipboard');
150
+ react_hot_toast_1.default.success('Copied to clipboard');
146
151
  };
147
152
  const downloadResult = () => {
148
153
  const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
@@ -159,12 +164,12 @@ const AIWriterPage = () => {
159
164
  if (!result)
160
165
  return null;
161
166
  if (mode === 'architect')
162
- return _jsx(SchemaResultView, { data: result });
167
+ return (0, jsx_runtime_1.jsx)(SchemaResultView, { data: result });
163
168
  if (mode === 'tools' && activeTool === 'seo')
164
- return _jsx(SeoResultView, { data: result });
169
+ return (0, jsx_runtime_1.jsx)(SeoResultView, { data: result });
165
170
  if (mode === 'tools' && activeTool === 'quality')
166
- return _jsx(QualityResultView, { data: result });
167
- return (_jsx(motion.div, { initial: { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, className: "whitespace-pre-wrap text-[12px] leading-relaxed text-gray-300 font-sans", children: typeof result === 'string' ? result : JSON.stringify(result, null, 2) }));
171
+ return (0, jsx_runtime_1.jsx)(QualityResultView, { data: result });
172
+ return ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, className: "whitespace-pre-wrap text-[12px] leading-relaxed text-gray-300 font-sans", children: typeof result === 'string' ? result : JSON.stringify(result, null, 2) }));
168
173
  };
169
174
  const activePlaceholder = mode === 'architect'
170
175
  ? 'Describe a collection schema... e.g., "An e-commerce product with variants, pricing, and inventory tracking"'
@@ -175,18 +180,18 @@ const AIWriterPage = () => {
175
180
  : activeTool === 'meta'
176
181
  ? 'Paste your content to generate a meta description...'
177
182
  : 'Paste text to analyze...';
178
- return (_jsxs("div", { className: "flex flex-col h-[calc(100vh-64px)] overflow-hidden", children: [_jsx(PageHeader, { title: "AI Architect", description: "Generate content, design schemas, and analyze text quality", actions: _jsx("div", { className: cn('flex p-0.5 border', dark ? 'bg-black border-z-border' : 'bg-z-panel border-z-border'), children: MODES.map(m => (_jsxs("button", { onClick: () => { setMode(m.id); setResult(null); setSchemaForSave(null); }, title: m.desc, className: cn('flex items-center gap-2 px-4 py-2 text-[9px] font-black uppercase tracking-widest transition-all', mode === m.id
183
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col h-[calc(100vh-64px)] overflow-hidden", children: [(0, jsx_runtime_1.jsx)(PageHeader_1.PageHeader, { title: "AI Architect", description: "Generate content, design schemas, and analyze text quality", actions: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('flex p-0.5 border', dark ? 'bg-black border-z-border' : 'bg-z-panel border-z-border'), children: MODES.map(m => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => { setMode(m.id); setResult(null); setSchemaForSave(null); }, title: m.desc, className: (0, utils_1.cn)('flex items-center gap-2 px-4 py-2 text-[9px] font-black uppercase tracking-widest transition-all', mode === m.id
179
184
  ? (dark ? 'bg-white text-black' : 'bg-gray-900 text-white')
180
- : (dark ? 'text-z-secondary hover:text-white' : 'text-z-secondary hover:text-z-primary')), children: [_jsx(m.icon, { size: 11 }), _jsx("span", { className: "hidden sm:inline", children: m.label })] }, m.id))) }) }), _jsxs("div", { className: "flex flex-1 overflow-hidden", children: [_jsxs("div", { className: cn('w-56 flex-shrink-0 border-r flex flex-col hidden lg:flex', dark ? 'border-z-border bg-black' : 'border-z-border bg-gray-50'), children: [_jsx("div", { className: cn('px-4 py-3 border-b flex-shrink-0', dark ? 'border-z-border' : 'border-z-border'), children: _jsx("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: "History" }) }), _jsxs("div", { className: "flex-1 overflow-y-auto p-2 space-y-1", children: [history.length === 0 && (_jsx("p", { className: "text-[8px] text-gray-600 uppercase tracking-widest p-2 text-center mt-4", children: "No history yet" })), history.map(h => (_jsxs("button", { onClick: () => { setResult(h.result); setSchemaForSave(h.mode === 'architect' ? h.result : null); }, className: cn('w-full text-left p-2.5 border border-transparent transition-all', dark ? 'hover:bg-z-hover hover:border-z-border' : 'hover:bg-white hover:border-z-border'), children: [_jsx("div", { className: "flex items-center gap-1.5 mb-1", children: _jsx("span", { className: cn('text-[7px] font-black uppercase tracking-widest', h.mode === 'architect' ? 'text-purple-400' : h.mode === 'tools' ? 'text-amber-400' : 'text-z-active-text'), children: h.mode }) }), _jsx("p", { className: "text-[9px] text-z-secondary truncate", children: h.prompt })] }, h.id)))] })] }), _jsxs("div", { className: "flex-1 flex flex-col min-w-0 border-r", style: { borderColor: dark ? 'rgba(255,255,255,0.08)' : '#e5e7eb' }, children: [_jsx(AnimatePresence, { children: mode === 'tools' && (_jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, className: cn('flex-shrink-0 border-b overflow-hidden', dark ? 'border-z-border' : 'border-z-border'), children: _jsx("div", { className: "p-3 flex gap-2 flex-wrap", children: TOOLS.map(tool => (_jsxs("button", { onClick: () => { setActiveTool(tool.id); setResult(null); }, title: tool.desc, className: cn('flex items-center gap-2 px-3 py-2 text-[9px] font-black uppercase tracking-widest border transition-all', activeTool === tool.id
185
+ : (dark ? 'text-z-secondary hover:text-white' : 'text-z-secondary hover:text-z-primary')), children: [(0, jsx_runtime_1.jsx)(m.icon, { size: 11 }), (0, jsx_runtime_1.jsx)("span", { className: "hidden sm:inline", children: m.label })] }, m.id))) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-1 overflow-hidden", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('w-56 flex-shrink-0 border-r flex flex-col hidden lg:flex', dark ? 'border-z-border bg-black' : 'border-z-border bg-gray-50'), children: [(0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('px-4 py-3 border-b flex-shrink-0', dark ? 'border-z-border' : 'border-z-border'), children: (0, jsx_runtime_1.jsx)("p", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: "History" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 overflow-y-auto p-2 space-y-1", children: [history.length === 0 && ((0, jsx_runtime_1.jsx)("p", { className: "text-[8px] text-gray-600 uppercase tracking-widest p-2 text-center mt-4", children: "No history yet" })), history.map(h => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => { setResult(h.result); setSchemaForSave(h.mode === 'architect' ? h.result : null); }, className: (0, utils_1.cn)('w-full text-left p-2.5 border border-transparent transition-all', dark ? 'hover:bg-z-hover hover:border-z-border' : 'hover:bg-white hover:border-z-border'), children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-1.5 mb-1", children: (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-[7px] font-black uppercase tracking-widest', h.mode === 'architect' ? 'text-purple-400' : h.mode === 'tools' ? 'text-amber-400' : 'text-z-active-text'), children: h.mode }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-[9px] text-z-secondary truncate", children: h.prompt })] }, h.id)))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col min-w-0 border-r", style: { borderColor: dark ? 'rgba(255,255,255,0.08)' : '#e5e7eb' }, children: [(0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: mode === 'tools' && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, className: (0, utils_1.cn)('flex-shrink-0 border-b overflow-hidden', dark ? 'border-z-border' : 'border-z-border'), children: (0, jsx_runtime_1.jsx)("div", { className: "p-3 flex gap-2 flex-wrap", children: TOOLS.map(tool => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => { setActiveTool(tool.id); setResult(null); }, title: tool.desc, className: (0, utils_1.cn)('flex items-center gap-2 px-3 py-2 text-[9px] font-black uppercase tracking-widest border transition-all', activeTool === tool.id
181
186
  ? (dark ? 'bg-white text-black border-white' : 'bg-gray-900 text-white border-gray-900')
182
- : (dark ? 'border-z-border text-z-secondary hover:text-white hover:border-white/20' : 'border-z-border text-z-secondary hover:border-gray-400 hover:text-z-primary')), children: [_jsx(tool.icon, { size: 11, className: activeTool === tool.id ? '' : tool.color }), tool.name] }, tool.id))) }) })) }), _jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [_jsxs("div", { className: cn('flex-shrink-0 flex items-center gap-3 px-5 py-3 border-b', dark ? 'border-z-border' : 'border-z-border'), children: [_jsx(Terminal, { size: 12, className: "text-z-secondary" }), _jsx("span", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: mode === 'architect' ? 'Schema Prompt' : mode === 'writer' ? 'Content Prompt' : TOOLS.find(t => t.id === activeTool)?.name }), _jsx("span", { className: "ml-auto text-[8px] text-gray-600 uppercase tracking-widest hidden sm:block", children: "\u2318 + Enter to run" })] }), _jsx("textarea", { ref: textareaRef, value: prompt, onChange: e => setPrompt(e.target.value), onKeyDown: handleKeyDown, placeholder: activePlaceholder, className: cn('flex-1 w-full p-5 text-sm outline-none resize-none font-sans leading-relaxed', dark
187
+ : (dark ? 'border-z-border text-z-secondary hover:text-white hover:border-white/20' : 'border-z-border text-z-secondary hover:border-gray-400 hover:text-z-primary')), children: [(0, jsx_runtime_1.jsx)(tool.icon, { size: 11, className: activeTool === tool.id ? '' : tool.color }), tool.name] }, tool.id))) }) })) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex-shrink-0 flex items-center gap-3 px-5 py-3 border-b', dark ? 'border-z-border' : 'border-z-border'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Terminal, { size: 12, className: "text-z-secondary" }), (0, jsx_runtime_1.jsx)("span", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: mode === 'architect' ? 'Schema Prompt' : mode === 'writer' ? 'Content Prompt' : TOOLS.find(t => t.id === activeTool)?.name }), (0, jsx_runtime_1.jsx)("span", { className: "ml-auto text-[8px] text-gray-600 uppercase tracking-widest hidden sm:block", children: "\u2318 + Enter to run" })] }), (0, jsx_runtime_1.jsx)("textarea", { ref: textareaRef, value: prompt, onChange: e => setPrompt(e.target.value), onKeyDown: handleKeyDown, placeholder: activePlaceholder, className: (0, utils_1.cn)('flex-1 w-full p-5 text-sm outline-none resize-none font-sans leading-relaxed', dark
183
188
  ? 'bg-transparent text-white placeholder:text-gray-700'
184
- : 'bg-transparent text-z-primary placeholder:text-z-muted') }), _jsx("div", { className: cn('flex-shrink-0 p-4 border-t', dark ? 'border-z-border' : 'border-z-border'), children: _jsxs("div", { className: "flex items-center gap-3", children: [prompt.trim() && (_jsx("button", { onClick: () => { setPrompt(''); setResult(null); }, className: "p-2.5 text-gray-600 hover:text-white transition-colors border border-transparent hover:border-white/10", title: "Clear", children: _jsx(RotateCcw, { size: 14 }) })), _jsx("button", { onClick: handleExecute, disabled: loading || (!prompt.trim() && activeTool !== 'alt'), className: cn('flex-1 py-3 font-black uppercase tracking-widest text-[10px] transition-all flex items-center justify-center gap-2.5', 'bg-z-accent hover:opacity-90 text-white', 'disabled:opacity-40 disabled:cursor-not-allowed', 'shadow-sm hover:shadow-sm'), children: loading
185
- ? _jsxs(_Fragment, { children: [_jsx(Loader2, { size: 13, className: "animate-spin" }), " Generating\u2026"] })
186
- : _jsxs(_Fragment, { children: [_jsx(Send, { size: 13 }), " ", mode === 'architect' ? 'Design Schema' : mode === 'writer' ? 'Generate Content' : 'Analyze'] }) })] }) })] })] }), _jsxs("div", { className: "flex-1 flex flex-col min-w-0", children: [_jsxs("div", { className: cn('flex-shrink-0 flex items-center justify-between px-5 py-3 border-b', dark ? 'border-z-border' : 'border-z-border'), children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx(Sparkles, { size: 12, className: result ? 'text-z-active-text' : 'text-z-secondary' }), _jsx("span", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: "Output" }), result && _jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-z-accent shadow-sm" })] }), result && (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: copyResult, title: "Copy", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: _jsx(Copy, { size: 13 }) }), _jsx("button", { onClick: downloadResult, title: "Download", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: _jsx(Download, { size: 13 }) }), mode === 'architect' && (_jsx("button", { onClick: () => { setResult(null); setSchemaForSave(null); }, title: "Clear", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: _jsx(RotateCcw, { size: 13 }) }))] }))] }), _jsx("div", { className: "flex-1 overflow-auto p-6", children: loading ? (_jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-4", children: [_jsxs("div", { className: "relative", children: [_jsx(Loader2, { size: 32, className: "animate-spin text-z-active-text" }), _jsx("div", { className: "absolute inset-0 blur-xl bg-z-accent/20 animate-pulse" })] }), _jsx("p", { className: "text-[9px] font-black uppercase tracking-[0.4em] text-z-secondary animate-pulse", children: mode === 'architect' ? 'Designing Schema…' : mode === 'writer' ? 'Writing Content…' : 'Analyzing…' })] })) : !result ? (_jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-5 opacity-30", children: [_jsx(Cpu, { size: 40, className: "text-z-secondary" }), _jsxs("div", { className: "text-center space-y-1", children: [_jsx("p", { className: "text-[9px] font-black uppercase tracking-[0.4em] text-z-secondary", children: "Awaiting Input" }), _jsx("p", { className: "text-[8px] text-gray-600 uppercase tracking-widest", children: mode === 'architect' ? 'Describe a collection to generate a schema' : mode === 'writer' ? 'Write a prompt to generate content' : 'Paste content to analyze' })] })] })) : (_jsx(AnimatePresence, { mode: "wait", children: _jsx(motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.2 }, children: renderResult() }, JSON.stringify(result).substring(0, 50)) })) }), _jsx(AnimatePresence, { children: result && mode === 'architect' && schemaForSave && (_jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, className: cn('flex-shrink-0 border-t overflow-hidden', dark ? 'border-z-border' : 'border-z-border'), children: _jsxs("div", { className: "px-5 py-3 flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-[8px] text-z-secondary uppercase tracking-widest", children: "Schema looks good? Save it as a live collection." }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { onClick: () => {
189
+ : 'bg-transparent text-z-primary placeholder:text-z-muted') }), (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('flex-shrink-0 p-4 border-t', dark ? 'border-z-border' : 'border-z-border'), children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [prompt.trim() && ((0, jsx_runtime_1.jsx)("button", { onClick: () => { setPrompt(''); setResult(null); }, className: "p-2.5 text-gray-600 hover:text-white transition-colors border border-transparent hover:border-white/10", title: "Clear", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCcw, { size: 14 }) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleExecute, disabled: loading || (!prompt.trim() && activeTool !== 'alt'), className: (0, utils_1.cn)('flex-1 py-3 font-black uppercase tracking-widest text-[10px] transition-all flex items-center justify-center gap-2.5', 'bg-z-accent hover:opacity-90 text-white', 'disabled:opacity-40 disabled:cursor-not-allowed', 'shadow-sm hover:shadow-sm'), children: loading
190
+ ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { size: 13, className: "animate-spin" }), " Generating\u2026"] })
191
+ : (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Send, { size: 13 }), " ", mode === 'architect' ? 'Design Schema' : mode === 'writer' ? 'Generate Content' : 'Analyze'] }) })] }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col min-w-0", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex-shrink-0 flex items-center justify-between px-5 py-3 border-b', dark ? 'border-z-border' : 'border-z-border'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Sparkles, { size: 12, className: result ? 'text-z-active-text' : 'text-z-secondary' }), (0, jsx_runtime_1.jsx)("span", { className: "text-[8px] font-black uppercase tracking-[0.3em] text-z-secondary", children: "Output" }), result && (0, jsx_runtime_1.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-z-accent shadow-sm" })] }), result && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)("button", { onClick: copyResult, title: "Copy", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { size: 13 }) }), (0, jsx_runtime_1.jsx)("button", { onClick: downloadResult, title: "Download", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Download, { size: 13 }) }), mode === 'architect' && ((0, jsx_runtime_1.jsx)("button", { onClick: () => { setResult(null); setSchemaForSave(null); }, title: "Clear", className: "p-2 text-z-secondary hover:text-white transition-colors border border-transparent hover:border-white/10", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RotateCcw, { size: 13 }) }))] }))] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 overflow-auto p-6", children: loading ? ((0, jsx_runtime_1.jsxs)("div", { className: "h-full flex flex-col items-center justify-center gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { size: 32, className: "animate-spin text-z-active-text" }), (0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 blur-xl bg-z-accent/20 animate-pulse" })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-[9px] font-black uppercase tracking-[0.4em] text-z-secondary animate-pulse", children: mode === 'architect' ? 'Designing Schema…' : mode === 'writer' ? 'Writing Content…' : 'Analyzing…' })] })) : !result ? ((0, jsx_runtime_1.jsxs)("div", { className: "h-full flex flex-col items-center justify-center gap-5 opacity-30", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Cpu, { size: 40, className: "text-z-secondary" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-center space-y-1", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[9px] font-black uppercase tracking-[0.4em] text-z-secondary", children: "Awaiting Input" }), (0, jsx_runtime_1.jsx)("p", { className: "text-[8px] text-gray-600 uppercase tracking-widest", children: mode === 'architect' ? 'Describe a collection to generate a schema' : mode === 'writer' ? 'Write a prompt to generate content' : 'Paste content to analyze' })] })] })) : ((0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.2 }, children: renderResult() }, JSON.stringify(result).substring(0, 50)) })) }), (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: result && mode === 'architect' && schemaForSave && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: 'auto', opacity: 1 }, exit: { height: 0, opacity: 0 }, className: (0, utils_1.cn)('flex-shrink-0 border-t overflow-hidden', dark ? 'border-z-border' : 'border-z-border'), children: (0, jsx_runtime_1.jsxs)("div", { className: "px-5 py-3 flex items-center justify-between gap-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-[8px] text-z-secondary uppercase tracking-widest", children: "Schema looks good? Save it as a live collection." }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => {
187
192
  const text = JSON.stringify(schemaForSave, null, 2);
188
193
  navigator.clipboard.writeText(text);
189
- toast.success('Schema copied as JSON');
190
- }, className: cn('px-4 py-2 border text-[9px] font-black uppercase tracking-widest flex items-center gap-2 transition-all', dark ? 'border-z-border text-z-muted hover:text-white hover:border-white/20' : 'border-z-border text-z-secondary hover:border-gray-400'), children: [_jsx(Code2, { size: 11 }), " Copy JSON"] }), _jsxs("button", { onClick: saveSchemaToDb, disabled: savingSchema, className: "px-5 py-2 bg-z-accent hover:opacity-90 text-white text-[9px] font-black uppercase tracking-widest flex items-center gap-2 transition-all disabled:opacity-50 shadow-sm", children: [savingSchema ? _jsx(Loader2, { size: 11, className: "animate-spin" }) : _jsx(Save, { size: 11 }), "Save Collection"] })] })] }) })) })] })] })] }));
194
+ react_hot_toast_1.default.success('Schema copied as JSON');
195
+ }, className: (0, utils_1.cn)('px-4 py-2 border text-[9px] font-black uppercase tracking-widest flex items-center gap-2 transition-all', dark ? 'border-z-border text-z-muted hover:text-white hover:border-white/20' : 'border-z-border text-z-secondary hover:border-gray-400'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Code2, { size: 11 }), " Copy JSON"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: saveSchemaToDb, disabled: savingSchema, className: "px-5 py-2 bg-z-accent hover:opacity-90 text-white text-[9px] font-black uppercase tracking-widest flex items-center gap-2 transition-all disabled:opacity-50 shadow-sm", children: [savingSchema ? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { size: 11, className: "animate-spin" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Save, { size: 11 }), "Save Collection"] })] })] }) })) })] })] })] }));
191
196
  };
192
- export default AIWriterPage;
197
+ exports.default = AIWriterPage;
@@ -1,9 +1,14 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
- import { Lock, Loader2, CheckCircle2, AlertCircle, ExternalLink, Eye, EyeOff, Cpu, Zap, ChevronRight, Info, TestTube2 } from 'lucide-react';
4
- import { cn } from '../../admin/src/lib/utils';
5
- import api from '../../admin/src/lib/api';
6
- import toast from 'react-hot-toast';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const lucide_react_1 = require("lucide-react");
9
+ const utils_1 = require("../../admin/src/lib/utils");
10
+ const api_1 = __importDefault(require("../../admin/src/lib/api"));
11
+ const react_hot_toast_1 = __importDefault(require("react-hot-toast"));
7
12
  const PROVIDERS = [
8
13
  {
9
14
  id: 'openrouter',
@@ -173,12 +178,12 @@ const TIER_BADGE = {
173
178
  };
174
179
  const SettingsAi = ({ settings, setSettings, theme }) => {
175
180
  const dark = theme === 'dark';
176
- const [validating, setValidating] = useState(false);
177
- const [testResult, setTestResult] = useState(null);
178
- const [showKeys, setShowKeys] = useState({});
179
- const [expandedProvider, setExpandedProvider] = useState('openrouter');
180
- const [dynamicModels, setDynamicModels] = useState({});
181
- const [fetchingModels, setFetchingModels] = useState(null);
181
+ const [validating, setValidating] = (0, react_1.useState)(false);
182
+ const [testResult, setTestResult] = (0, react_1.useState)(null);
183
+ const [showKeys, setShowKeys] = (0, react_1.useState)({});
184
+ const [expandedProvider, setExpandedProvider] = (0, react_1.useState)('openrouter');
185
+ const [dynamicModels, setDynamicModels] = (0, react_1.useState)({});
186
+ const [fetchingModels, setFetchingModels] = (0, react_1.useState)(null);
182
187
  const activeProvider = PROVIDERS.find(p => {
183
188
  const key = settings[p.keyField]?.trim();
184
189
  return key && key !== '[MASKED_CREDENTIAL]';
@@ -191,18 +196,18 @@ const SettingsAi = ({ settings, setSettings, theme }) => {
191
196
  const providerConfig = PROVIDERS.find(p => p.id === providerId);
192
197
  const apiKeyField = providerConfig ? providerConfig.keyField : 'openRouterApiKey';
193
198
  const apiKey = settings[apiKeyField];
194
- const res = await api.post('/system/settings/ai/validate', {
199
+ const res = await api_1.default.post('/system/settings/ai/validate', {
195
200
  provider: providerId,
196
201
  model: settings.aiModel,
197
202
  apiKey: apiKey
198
203
  });
199
204
  setTestResult({ ok: true, msg: res.data.message || 'API Key is valid' });
200
- toast.success('AI connection verified');
205
+ react_hot_toast_1.default.success('AI connection verified');
201
206
  }
202
207
  catch (err) {
203
208
  const msg = err?.response?.data?.error?.message || err?.response?.data?.message || 'Connection failed';
204
209
  setTestResult({ ok: false, msg });
205
- toast.error('AI connection failed');
210
+ react_hot_toast_1.default.error('AI connection failed');
206
211
  }
207
212
  finally {
208
213
  setValidating(false);
@@ -212,34 +217,34 @@ const SettingsAi = ({ settings, setSettings, theme }) => {
212
217
  setFetchingModels(providerId);
213
218
  try {
214
219
  const apiKey = settings[apiKeyField];
215
- const res = await api.post('/system/settings/ai/models', {
220
+ const res = await api_1.default.post('/system/settings/ai/models', {
216
221
  provider: providerId,
217
222
  apiKey: apiKey
218
223
  });
219
224
  const models = res.data?.data || [];
220
225
  setDynamicModels(prev => ({ ...prev, [providerId]: models }));
221
- toast.success(`Fetched ${models.length} models for ${providerId}`);
226
+ react_hot_toast_1.default.success(`Fetched ${models.length} models for ${providerId}`);
222
227
  }
223
228
  catch (err) {
224
229
  const msg = err?.response?.data?.error?.message || err?.response?.data?.message || 'Failed to fetch models';
225
- toast.error(msg);
230
+ react_hot_toast_1.default.error(msg);
226
231
  }
227
232
  finally {
228
233
  setFetchingModels(null);
229
234
  }
230
235
  };
231
236
  const toggleKey = (id) => setShowKeys(prev => ({ ...prev, [id]: !prev[id] }));
232
- const inp = (dark) => cn('w-full border px-3 py-2.5 text-sm font-semibold outline-none transition-colors rounded-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black', dark
237
+ const inp = (dark) => (0, utils_1.cn)('w-full border px-3 py-2.5 text-sm font-semibold outline-none transition-colors rounded-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black', dark
233
238
  ? 'bg-black border-z-border text-white placeholder:text-gray-700 focus:border-z-accent'
234
239
  : 'bg-z-panel border-z-border text-z-primary placeholder:text-z-muted focus:border-z-accent');
235
- return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: cn('p-5 border space-y-4 shadow-sm', dark ? 'bg-z-panel backdrop-blur-md border-z-border' : 'bg-z-input border-z-border'), children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx(Cpu, { size: 14, className: "text-z-active-text" }), _jsx("span", { className: cn('text-sm font-semibold ', dark ? 'text-white' : 'text-z-primary'), children: "Active Model" }), _jsx("span", { className: "ml-auto text-sm text-z-secondary", children: "Used by all AI features" })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-sm font-semibold text-z-secondary", children: "AI Provider" }), _jsx("select", { value: settings.aiProvider || 'openrouter', onChange: e => setSettings({ ...settings, aiProvider: e.target.value, aiModel: PROVIDERS.find(p => p.id === e.target.value)?.models[0]?.value || '' }), className: inp(dark), children: PROVIDERS.map(p => _jsx("option", { value: p.id, children: p.name }, p.id)) })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-sm font-semibold text-z-secondary", children: "Model" }), _jsx("select", { value: settings.aiModel || '', onChange: e => setSettings({ ...settings, aiModel: e.target.value }), className: inp(dark), children: (dynamicModels[settings.aiProvider || 'openrouter'] || PROVIDERS.find(p => p.id === (settings.aiProvider || 'openrouter'))?.models || []).map(m => (_jsxs("option", { value: m.value, children: [m.label, " ", m.tier ? `(${m.tier})` : ''] }, m.value))) })] })] }), _jsxs("div", { className: "flex items-center gap-3 pt-1", children: [_jsxs("button", { onClick: handleValidate, disabled: validating, className: "px-4 py-2 bg-z-accent hover:opacity-90 shadow-sm text-white text-sm font-semibold flex items-center gap-2 disabled:opacity-50 transition-all", children: [validating ? _jsx(Loader2, { size: 11, className: "animate-spin" }) : _jsx(TestTube2, { size: 11 }), "Test Connection"] }), testResult && (_jsxs("div", { className: cn('flex items-center gap-2 text-sm font-semibold ', testResult.ok ? 'text-z-active-text' : 'text-red-400'), children: [testResult.ok ? _jsx(CheckCircle2, { size: 11 }) : _jsx(AlertCircle, { size: 11 }), testResult.msg] }))] })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3", children: [_jsx(Lock, { size: 12, className: "text-z-secondary" }), _jsx("span", { className: "text-sm font-semibold text-z-secondary", children: "Provider API Keys" }), _jsx("span", { className: "ml-auto text-sm text-gray-600", children: "All keys encrypted at rest" })] }), PROVIDERS.map(provider => {
240
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('p-5 border space-y-4 shadow-sm', dark ? 'bg-z-panel backdrop-blur-md border-z-border' : 'bg-z-input border-z-border'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2.5", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Cpu, { size: 14, className: "text-z-active-text" }), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-sm font-semibold ', dark ? 'text-white' : 'text-z-primary'), children: "Active Model" }), (0, jsx_runtime_1.jsx)("span", { className: "ml-auto text-sm text-z-secondary", children: "Used by all AI features" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-sm font-semibold text-z-secondary", children: "AI Provider" }), (0, jsx_runtime_1.jsx)("select", { value: settings.aiProvider || 'openrouter', onChange: e => setSettings({ ...settings, aiProvider: e.target.value, aiModel: PROVIDERS.find(p => p.id === e.target.value)?.models[0]?.value || '' }), className: inp(dark), children: PROVIDERS.map(p => (0, jsx_runtime_1.jsx)("option", { value: p.id, children: p.name }, p.id)) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-sm font-semibold text-z-secondary", children: "Model" }), (0, jsx_runtime_1.jsx)("select", { value: settings.aiModel || '', onChange: e => setSettings({ ...settings, aiModel: e.target.value }), className: inp(dark), children: (dynamicModels[settings.aiProvider || 'openrouter'] || PROVIDERS.find(p => p.id === (settings.aiProvider || 'openrouter'))?.models || []).map(m => ((0, jsx_runtime_1.jsxs)("option", { value: m.value, children: [m.label, " ", m.tier ? `(${m.tier})` : ''] }, m.value))) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3 pt-1", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleValidate, disabled: validating, className: "px-4 py-2 bg-z-accent hover:opacity-90 shadow-sm text-white text-sm font-semibold flex items-center gap-2 disabled:opacity-50 transition-all", children: [validating ? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { size: 11, className: "animate-spin" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.TestTube2, { size: 11 }), "Test Connection"] }), testResult && ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex items-center gap-2 text-sm font-semibold ', testResult.ok ? 'text-z-active-text' : 'text-red-400'), children: [testResult.ok ? (0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle2, { size: 11 }) : (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { size: 11 }), testResult.msg] }))] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 mb-3", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Lock, { size: 12, className: "text-z-secondary" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-semibold text-z-secondary", children: "Provider API Keys" }), (0, jsx_runtime_1.jsx)("span", { className: "ml-auto text-sm text-gray-600", children: "All keys encrypted at rest" })] }), PROVIDERS.map(provider => {
236
241
  const isExpanded = expandedProvider === provider.id;
237
242
  const keyValue = settings[provider.keyField] || '';
238
243
  const hasKey = keyValue.trim() && keyValue !== '[MASKED_CREDENTIAL]';
239
244
  const isMasked = keyValue === '[MASKED_CREDENTIAL]';
240
- return (_jsxs("div", { className: cn('border transition-all shadow-sm', isExpanded
245
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('border transition-all shadow-sm', isExpanded
241
246
  ? (dark ? 'border-white/15 bg-black/80 backdrop-blur-md shadow-sm' : 'border-z-border-strong bg-white')
242
- : ('z-card-interactive')), children: [_jsxs("button", { onClick: () => setExpandedProvider(isExpanded ? '' : provider.id), className: "w-full flex items-center gap-3 px-4 py-3 text-left", children: [_jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [_jsx("div", { className: cn('w-2 h-2 rounded-full flex-shrink-0', hasKey || isMasked ? 'bg-z-accent shadow-sm' : 'bg-gray-700') }), _jsx("div", { className: cn('text-sm font-semibold', provider.color), children: provider.name }), provider.badge && (_jsx("span", { className: "text-sm font-semibold px-1.5 py-0.5 bg-z-active-bg border border-z-active-border text-z-active-text", children: provider.badge })), _jsx("span", { className: "text-sm text-gray-600 truncate hidden sm:block", children: provider.description })] }), _jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [isMasked && _jsx("span", { className: "text-sm text-z-active-text font-semibold", children: "Configured" }), hasKey && !isMasked && _jsx("span", { className: "text-sm text-z-active-text font-semibold", children: "Active" }), _jsx(ChevronRight, { size: 12, className: cn('text-z-secondary transition-transform', isExpanded && 'rotate-90') })] })] }), isExpanded && (_jsxs("div", { className: "px-4 pb-4 space-y-3 border-t", style: { borderColor: dark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)' }, children: [_jsx("p", { className: "text-sm text-z-secondary pt-3", children: provider.description }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-semibold text-z-secondary", children: "API Key" }), _jsxs("a", { href: provider.docsUrl, target: "_blank", rel: "noopener noreferrer", className: "text-sm text-z-active-text hover:text-z-active-text flex items-center gap-1 transition-colors", children: ["Get Key ", _jsx(ExternalLink, { size: 9 })] })] }), _jsxs("div", { className: "relative", children: [_jsx("input", { type: showKeys[provider.id] ? 'text' : 'password', value: keyValue, onChange: e => setSettings({ ...settings, [provider.keyField]: e.target.value }), placeholder: isMasked ? '••••••••••••••••' : provider.keyPlaceholder, className: cn(inp(dark), 'pr-10 font-mono') }), _jsx("button", { type: "button", onClick: () => toggleKey(provider.id), className: "absolute right-3 top-1/2 -translate-y-1/2 text-z-secondary hover:text-white transition-colors", children: showKeys[provider.id] ? _jsx(EyeOff, { size: 13 }) : _jsx(Eye, { size: 13 }) })] }), isMasked && (_jsxs("p", { className: "text-sm text-amber-500/70 flex items-center gap-1", children: [_jsx(Lock, { size: 9 }), " Key is stored \u2014 enter a new value to replace it"] }))] }), _jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("label", { className: "text-sm font-semibold text-z-secondary", children: ["Available Models ", dynamicModels[provider.id] ? `(${dynamicModels[provider.id].length})` : ''] }), _jsxs("button", { type: "button", onClick: () => handleFetchModels(provider.id, provider.keyField), disabled: fetchingModels === provider.id || (!hasKey && !isMasked), className: "text-sm text-z-active-text hover:text-z-active-text flex items-center gap-1 disabled:opacity-50 transition-colors", children: [fetchingModels === provider.id ? _jsx(Loader2, { size: 9, className: "animate-spin" }) : _jsx(Zap, { size: 9 }), "Fetch Models"] })] }), _jsx("div", { className: "flex flex-wrap gap-1.5 max-h-[120px] overflow-y-auto pr-2 custom-scrollbar", children: (dynamicModels[provider.id] || provider.models).map(m => (_jsx("span", { title: m.value, className: cn('text-sm font-semibold px-2 py-1 border', m.tier ? TIER_BADGE[m.tier] : 'bg-z-hover border-white/10 text-z-muted'), children: m.label }, m.value))) })] })] }))] }, provider.id));
243
- })] }), _jsxs("div", { className: cn('flex gap-3 p-4 border', dark ? 'bg-z-accent/5 border-z-accent/15' : 'bg-z-active-bg border-z-active-border'), children: [_jsx(Info, { size: 12, className: "text-z-active-text flex-shrink-0 mt-0.5" }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-semibold text-z-active-text", children: "Provider Priority" }), _jsx("p", { className: "text-sm text-z-secondary leading-relaxed", children: "The AI engine auto-selects providers in this order: OpenRouter \u2192 xAI \u2192 NVIDIA NIM \u2192 Groq \u2192 Together AI \u2192 Mistral \u2192 Cohere \u2192 OpenAI \u2192 Anthropic \u2192 Google Gemini. Set the \"Active Model\" above to override. Keys are never sent to the client." })] })] })] }));
247
+ : ('z-card-interactive')), children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setExpandedProvider(isExpanded ? '' : provider.id), className: "w-full flex items-center gap-3 px-4 py-3 text-left", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3 flex-1 min-w-0", children: [(0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('w-2 h-2 rounded-full flex-shrink-0', hasKey || isMasked ? 'bg-z-accent shadow-sm' : 'bg-gray-700') }), (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('text-sm font-semibold', provider.color), children: provider.name }), provider.badge && ((0, jsx_runtime_1.jsx)("span", { className: "text-sm font-semibold px-1.5 py-0.5 bg-z-active-bg border border-z-active-border text-z-active-text", children: provider.badge })), (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-gray-600 truncate hidden sm:block", children: provider.description })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 flex-shrink-0", children: [isMasked && (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-z-active-text font-semibold", children: "Configured" }), hasKey && !isMasked && (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-z-active-text font-semibold", children: "Active" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 12, className: (0, utils_1.cn)('text-z-secondary transition-transform', isExpanded && 'rotate-90') })] })] }), isExpanded && ((0, jsx_runtime_1.jsxs)("div", { className: "px-4 pb-4 space-y-3 border-t", style: { borderColor: dark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)' }, children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-z-secondary pt-3", children: provider.description }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("label", { className: "text-sm font-semibold text-z-secondary", children: "API Key" }), (0, jsx_runtime_1.jsxs)("a", { href: provider.docsUrl, target: "_blank", rel: "noopener noreferrer", className: "text-sm text-z-active-text hover:text-z-active-text flex items-center gap-1 transition-colors", children: ["Get Key ", (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { size: 9 })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)("input", { type: showKeys[provider.id] ? 'text' : 'password', value: keyValue, onChange: e => setSettings({ ...settings, [provider.keyField]: e.target.value }), placeholder: isMasked ? '••••••••••••••••' : provider.keyPlaceholder, className: (0, utils_1.cn)(inp(dark), 'pr-10 font-mono') }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => toggleKey(provider.id), className: "absolute right-3 top-1/2 -translate-y-1/2 text-z-secondary hover:text-white transition-colors", children: showKeys[provider.id] ? (0, jsx_runtime_1.jsx)(lucide_react_1.EyeOff, { size: 13 }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Eye, { size: 13 }) })] }), isMasked && ((0, jsx_runtime_1.jsxs)("p", { className: "text-sm text-amber-500/70 flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Lock, { size: 9 }), " Key is stored \u2014 enter a new value to replace it"] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-1.5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("label", { className: "text-sm font-semibold text-z-secondary", children: ["Available Models ", dynamicModels[provider.id] ? `(${dynamicModels[provider.id].length})` : ''] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => handleFetchModels(provider.id, provider.keyField), disabled: fetchingModels === provider.id || (!hasKey && !isMasked), className: "text-sm text-z-active-text hover:text-z-active-text flex items-center gap-1 disabled:opacity-50 transition-colors", children: [fetchingModels === provider.id ? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { size: 9, className: "animate-spin" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Zap, { size: 9 }), "Fetch Models"] })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-1.5 max-h-[120px] overflow-y-auto pr-2 custom-scrollbar", children: (dynamicModels[provider.id] || provider.models).map(m => ((0, jsx_runtime_1.jsx)("span", { title: m.value, className: (0, utils_1.cn)('text-sm font-semibold px-2 py-1 border', m.tier ? TIER_BADGE[m.tier] : 'bg-z-hover border-white/10 text-z-muted'), children: m.label }, m.value))) })] })] }))] }, provider.id));
248
+ })] }), (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex gap-3 p-4 border', dark ? 'bg-z-accent/5 border-z-accent/15' : 'bg-z-active-bg border-z-active-border'), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Info, { size: 12, className: "text-z-active-text flex-shrink-0 mt-0.5" }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-1", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-semibold text-z-active-text", children: "Provider Priority" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-z-secondary leading-relaxed", children: "The AI engine auto-selects providers in this order: OpenRouter \u2192 xAI \u2192 NVIDIA NIM \u2192 Groq \u2192 Together AI \u2192 Mistral \u2192 Cohere \u2192 OpenAI \u2192 Anthropic \u2192 Google Gemini. Set the \"Active Model\" above to override. Keys are never sent to the client." })] })] })] }));
244
249
  };
245
- export default SettingsAi;
250
+ exports.default = SettingsAi;
@@ -1 +1,17 @@
1
- export * from './plugin';
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./plugin"), exports);
@@ -1,2 +1,10 @@
1
- export { default as AIWriterPage } from './AIWriterPage';
2
- export { default as SettingsAi } from './SettingsAi';
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SettingsAi = exports.AIWriterPage = void 0;
7
+ var AIWriterPage_1 = require("./AIWriterPage");
8
+ Object.defineProperty(exports, "AIWriterPage", { enumerable: true, get: function () { return __importDefault(AIWriterPage_1).default; } });
9
+ var SettingsAi_1 = require("./SettingsAi");
10
+ Object.defineProperty(exports, "SettingsAi", { enumerable: true, get: function () { return __importDefault(SettingsAi_1).default; } });
@@ -0,0 +1,2 @@
1
+ export { default as AIWriterPage } from './AIWriterPage';
2
+ export { default as SettingsAi } from './SettingsAi';
package/dist/plugin.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default as AIWriterPage } from './AIWriterPage';
2
+ export { default as SettingsAi } from './SettingsAi';
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@zenith-open/zenithcms-plugin-ai-architect-ui",
3
- "version": "1.0.0-beta.10",
4
- "type": "module",
3
+ "version": "1.0.0-beta.8",
5
4
  "description": "AI Copilot and SEO Architect UI Plugin for Zenith CMS",
6
5
  "main": "dist/index.js",
7
6
  "types": "dist/index.d.ts",