@nuasite/cms 0.20.1 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editor.js +11246 -11441
- package/package.json +1 -1
- package/src/dev-middleware.ts +14 -4
- package/src/editor/api.ts +0 -251
- package/src/editor/components/markdown-editor-overlay.tsx +7 -26
- package/src/editor/components/toolbar.tsx +0 -75
- package/src/editor/constants.ts +0 -4
- package/src/editor/editor.ts +2 -192
- package/src/editor/hooks/index.ts +0 -3
- package/src/editor/hooks/useBlockEditorHandlers.ts +1 -8
- package/src/editor/hooks/useTooltipState.ts +1 -2
- package/src/editor/index.tsx +2 -18
- package/src/editor/post-message.ts +0 -6
- package/src/editor/signals.ts +0 -166
- package/src/editor/styles.css +0 -108
- package/src/editor/types.ts +0 -66
- package/src/types.ts +0 -4
- package/src/editor/ai.ts +0 -185
- package/src/editor/components/ai-chat.tsx +0 -631
- package/src/editor/components/ai-tooltip.tsx +0 -180
- package/src/editor/hooks/useAIHandlers.ts +0 -345
package/src/editor/styles.css
CHANGED
|
@@ -87,114 +87,6 @@
|
|
|
87
87
|
animation: spin 1s linear infinite;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
/* Markdown styles for AI chat messages */
|
|
91
|
-
.cms-markdown p {
|
|
92
|
-
margin: 0 0 0.5em 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.cms-markdown p:last-child {
|
|
96
|
-
margin-bottom: 0;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.cms-markdown strong {
|
|
100
|
-
font-weight: 700;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.cms-markdown em {
|
|
104
|
-
font-style: italic;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.cms-markdown code {
|
|
108
|
-
background: rgba(255, 255, 255, 0.1);
|
|
109
|
-
padding: 0.1em 0.3em;
|
|
110
|
-
border-radius: 3px;
|
|
111
|
-
font-family: ui-monospace, monospace;
|
|
112
|
-
font-size: 0.9em;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.cms-markdown pre {
|
|
116
|
-
background: rgba(0, 0, 0, 0.3);
|
|
117
|
-
padding: 0.75em;
|
|
118
|
-
border-radius: 4px;
|
|
119
|
-
overflow-x: auto;
|
|
120
|
-
margin: 0.5em 0;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.cms-markdown pre code {
|
|
124
|
-
background: none;
|
|
125
|
-
padding: 0;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.cms-markdown ul {
|
|
129
|
-
margin: 0.5em 0;
|
|
130
|
-
padding-left: 1.5em;
|
|
131
|
-
list-style-type: disc;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.cms-markdown ol {
|
|
135
|
-
margin: 0.5em 0;
|
|
136
|
-
padding-left: 1.5em;
|
|
137
|
-
list-style-type: decimal;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.cms-markdown ul ul {
|
|
141
|
-
list-style-type: circle;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.cms-markdown ul ul ul {
|
|
145
|
-
list-style-type: square;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.cms-markdown li {
|
|
149
|
-
margin: 0.25em 0;
|
|
150
|
-
display: list-item;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.cms-markdown h1, .cms-markdown h2, .cms-markdown h3,
|
|
154
|
-
.cms-markdown h4, .cms-markdown h5, .cms-markdown h6 {
|
|
155
|
-
margin: 0.75em 0 0.25em 0;
|
|
156
|
-
font-weight: 600;
|
|
157
|
-
line-height: 1.3;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.cms-markdown h1 {
|
|
161
|
-
font-size: 1.4em;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.cms-markdown h2 {
|
|
165
|
-
font-size: 1.2em;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.cms-markdown h3 {
|
|
169
|
-
font-size: 1.1em;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.cms-markdown h1:first-child, .cms-markdown h2:first-child, .cms-markdown h3:first-child {
|
|
173
|
-
margin-top: 0;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.cms-markdown hr {
|
|
177
|
-
border: none;
|
|
178
|
-
border-top: 1px solid rgba(255, 255, 255, 0.15);
|
|
179
|
-
margin: 0.75em 0;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.cms-markdown a {
|
|
183
|
-
color: #93c5fd;
|
|
184
|
-
text-decoration: underline;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
.cms-markdown a:hover {
|
|
188
|
-
color: #bfdbfe;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.cms-markdown blockquote {
|
|
192
|
-
border-left: 3px solid #93c5fd;
|
|
193
|
-
margin: 0.5em 0;
|
|
194
|
-
padding-left: 1em;
|
|
195
|
-
color: rgba(255, 255, 255, 0.7);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
90
|
/* Soft Design System Card Component */
|
|
199
91
|
.cms-card {
|
|
200
92
|
background: var(--color-cms-card);
|
package/src/editor/types.ts
CHANGED
|
@@ -240,35 +240,6 @@ export interface SaveBatchResponse {
|
|
|
240
240
|
errors?: Array<{ cmsId: string; error: string }>
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
export interface ChatMessage {
|
|
244
|
-
id: string
|
|
245
|
-
role: 'user' | 'assistant'
|
|
246
|
-
content: string
|
|
247
|
-
elementId?: string
|
|
248
|
-
timestamp: number
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export type AIStatusType =
|
|
252
|
-
| 'thinking'
|
|
253
|
-
| 'coding'
|
|
254
|
-
| 'building'
|
|
255
|
-
| 'deploying'
|
|
256
|
-
| 'complete'
|
|
257
|
-
| null
|
|
258
|
-
|
|
259
|
-
export interface AIState {
|
|
260
|
-
isPromptVisible: boolean
|
|
261
|
-
isProcessing: boolean
|
|
262
|
-
targetElementId: string | null
|
|
263
|
-
streamingContent: string | null
|
|
264
|
-
error: string | null
|
|
265
|
-
isChatOpen: boolean
|
|
266
|
-
chatMessages: ChatMessage[]
|
|
267
|
-
chatContextElementId: string | null
|
|
268
|
-
currentStatus: AIStatusType
|
|
269
|
-
statusMessage: string | null
|
|
270
|
-
}
|
|
271
|
-
|
|
272
243
|
export interface BlockEditorState {
|
|
273
244
|
isOpen: boolean
|
|
274
245
|
currentComponentId: string | null
|
|
@@ -322,7 +293,6 @@ export interface EditorState {
|
|
|
322
293
|
pendingComponentChanges: Map<string, ComponentInstance>
|
|
323
294
|
pendingInserts: Map<string, PendingComponentInsert>
|
|
324
295
|
manifest: CmsManifest
|
|
325
|
-
ai: AIState
|
|
326
296
|
blockEditor: BlockEditorState
|
|
327
297
|
}
|
|
328
298
|
|
|
@@ -481,42 +451,6 @@ export interface MediaUploadResponse {
|
|
|
481
451
|
error?: string
|
|
482
452
|
}
|
|
483
453
|
|
|
484
|
-
// ============================================================================
|
|
485
|
-
// Deployment Status Types
|
|
486
|
-
// ============================================================================
|
|
487
|
-
|
|
488
|
-
export type DeploymentStatusType =
|
|
489
|
-
| 'pending'
|
|
490
|
-
| 'queued'
|
|
491
|
-
| 'running'
|
|
492
|
-
| 'completed'
|
|
493
|
-
| 'failed'
|
|
494
|
-
| 'cancelled'
|
|
495
|
-
|
|
496
|
-
export interface DeploymentStatusResponse {
|
|
497
|
-
currentDeployment: {
|
|
498
|
-
id: string
|
|
499
|
-
status: DeploymentStatusType
|
|
500
|
-
createdAt: string
|
|
501
|
-
startedAt: string | null
|
|
502
|
-
commitMessage: string | null
|
|
503
|
-
} | null
|
|
504
|
-
lastSuccessfulDeployment: {
|
|
505
|
-
completedAt: string
|
|
506
|
-
publishedUrl: string
|
|
507
|
-
} | null
|
|
508
|
-
pendingCount: number
|
|
509
|
-
/** When false, deployment is not available (e.g. local dev) and polling should be skipped */
|
|
510
|
-
deploymentEnabled?: boolean
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
export interface DeploymentState {
|
|
514
|
-
status: DeploymentStatusType | null
|
|
515
|
-
lastDeployedAt: string | null
|
|
516
|
-
isPolling: boolean
|
|
517
|
-
error: string | null
|
|
518
|
-
}
|
|
519
|
-
|
|
520
454
|
// ============================================================================
|
|
521
455
|
// Confirm Dialog Types
|
|
522
456
|
// ============================================================================
|
package/src/types.ts
CHANGED
|
@@ -567,10 +567,6 @@ export interface CmsEditorState {
|
|
|
567
567
|
seo: number
|
|
568
568
|
total: number
|
|
569
569
|
}
|
|
570
|
-
deployment: {
|
|
571
|
-
status: 'pending' | 'queued' | 'running' | 'completed' | 'failed' | 'cancelled' | null
|
|
572
|
-
lastDeployedAt: string | null
|
|
573
|
-
}
|
|
574
570
|
canUndo: boolean
|
|
575
571
|
canRedo: boolean
|
|
576
572
|
}
|
package/src/editor/ai.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { type CmsAiAction, type CmsAiChatRequest, type CmsAiStreamCallbacks, streamAiChat } from './api'
|
|
2
|
-
import { logDebug } from './dom'
|
|
3
|
-
import type { CmsConfig, ComponentProp } from './types'
|
|
4
|
-
|
|
5
|
-
// Re-export for consumers
|
|
6
|
-
export type { CmsAiAction }
|
|
7
|
-
|
|
8
|
-
export interface AIRequest {
|
|
9
|
-
prompt: string
|
|
10
|
-
elementId: string
|
|
11
|
-
currentContent: string
|
|
12
|
-
context?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface AIBlockPropsRequest {
|
|
16
|
-
prompt: string
|
|
17
|
-
componentName: string
|
|
18
|
-
props: ComponentProp[]
|
|
19
|
-
currentValues: Record<string, unknown>
|
|
20
|
-
context?: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface AIStreamCallbacks {
|
|
24
|
-
onStart?: () => void
|
|
25
|
-
onToken?: (token: string, fullText: string) => void
|
|
26
|
-
onComplete?: (finalText: string) => void
|
|
27
|
-
onError?: (error: Error) => void
|
|
28
|
-
/** Called when AI provides status updates (thinking, coding, building, deploying) */
|
|
29
|
-
onStatus?: (status: string, message?: string) => void
|
|
30
|
-
/** Called when AI requests an action (refresh page, show preview, apply edit) */
|
|
31
|
-
onAction?: (action: CmsAiAction) => void
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface AIConfig {
|
|
35
|
-
endpoint: string
|
|
36
|
-
headers?: Record<string, string>
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function getAIConfig(config: CmsConfig): AIConfig {
|
|
40
|
-
return {
|
|
41
|
-
endpoint: config.apiBase,
|
|
42
|
-
headers: {
|
|
43
|
-
'Content-Type': 'application/json',
|
|
44
|
-
},
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export class AIService {
|
|
49
|
-
private config: CmsConfig
|
|
50
|
-
private aiConfig: AIConfig
|
|
51
|
-
private abortController: AbortController | null = null
|
|
52
|
-
|
|
53
|
-
constructor(config: CmsConfig) {
|
|
54
|
-
this.config = config
|
|
55
|
-
this.aiConfig = getAIConfig(config)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Stream AI chat request using rich SSE events
|
|
60
|
-
* Supports status updates, actions (refresh, preview), and streaming text
|
|
61
|
-
*/
|
|
62
|
-
async streamRequest(request: AIRequest, callbacks: AIStreamCallbacks): Promise<void> {
|
|
63
|
-
this.abortController = new AbortController()
|
|
64
|
-
let fullText = ''
|
|
65
|
-
|
|
66
|
-
callbacks.onStart?.()
|
|
67
|
-
|
|
68
|
-
const chatRequest: CmsAiChatRequest = {
|
|
69
|
-
prompt: request.prompt,
|
|
70
|
-
elementId: request.elementId,
|
|
71
|
-
currentContent: request.currentContent,
|
|
72
|
-
context: request.context,
|
|
73
|
-
pageUrl: window.location.href,
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const streamCallbacks: CmsAiStreamCallbacks = {
|
|
77
|
-
onToken: (token, accumulatedText) => {
|
|
78
|
-
fullText = accumulatedText
|
|
79
|
-
callbacks.onToken?.(token, accumulatedText)
|
|
80
|
-
},
|
|
81
|
-
onStatus: (status, message) => {
|
|
82
|
-
logDebug(this.config.debug, 'AI status:', status, message)
|
|
83
|
-
callbacks.onStatus?.(status, message)
|
|
84
|
-
},
|
|
85
|
-
onAction: action => {
|
|
86
|
-
logDebug(this.config.debug, 'AI action:', action)
|
|
87
|
-
callbacks.onAction?.(action)
|
|
88
|
-
},
|
|
89
|
-
onError: (error, code) => {
|
|
90
|
-
logDebug(this.config.debug, 'AI error:', error, code)
|
|
91
|
-
callbacks.onError?.(new Error(error))
|
|
92
|
-
},
|
|
93
|
-
onDone: summary => {
|
|
94
|
-
logDebug(this.config.debug, 'AI done:', summary)
|
|
95
|
-
callbacks.onComplete?.(fullText)
|
|
96
|
-
},
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await streamAiChat(
|
|
101
|
-
this.aiConfig.endpoint,
|
|
102
|
-
chatRequest,
|
|
103
|
-
streamCallbacks,
|
|
104
|
-
this.abortController.signal,
|
|
105
|
-
)
|
|
106
|
-
} catch (error) {
|
|
107
|
-
callbacks.onError?.(error instanceof Error ? error : new Error(String(error)))
|
|
108
|
-
} finally {
|
|
109
|
-
this.abortController = null
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
abort(): void {
|
|
114
|
-
if (this.abortController) {
|
|
115
|
-
this.abortController.abort()
|
|
116
|
-
this.abortController = null
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
isStreaming(): boolean {
|
|
121
|
-
return this.abortController !== null
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Generate prop values for a component using AI
|
|
126
|
-
*/
|
|
127
|
-
async generateBlockProps(request: AIBlockPropsRequest): Promise<Record<string, unknown>> {
|
|
128
|
-
try {
|
|
129
|
-
const response = await fetch(`${this.aiConfig.endpoint}/ai/generate-props`, {
|
|
130
|
-
method: 'POST',
|
|
131
|
-
credentials: 'include',
|
|
132
|
-
headers: this.aiConfig.headers,
|
|
133
|
-
body: JSON.stringify({
|
|
134
|
-
prompt: request.prompt,
|
|
135
|
-
componentName: request.componentName,
|
|
136
|
-
props: request.props,
|
|
137
|
-
currentValues: request.currentValues,
|
|
138
|
-
context: request.context,
|
|
139
|
-
pageUrl: window.location.href,
|
|
140
|
-
}),
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
if (!response.ok) {
|
|
144
|
-
throw new Error(`AI request failed: ${response.status} ${response.statusText}`)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const result = await response.json()
|
|
148
|
-
return result.props || {}
|
|
149
|
-
} catch (error) {
|
|
150
|
-
logDebug(this.config.debug, 'AI generateBlockProps error:', error)
|
|
151
|
-
throw error
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Suggest the best component to use based on user intent
|
|
157
|
-
*/
|
|
158
|
-
async suggestComponent(
|
|
159
|
-
prompt: string,
|
|
160
|
-
availableComponents: Array<{ name: string; description?: string; props: ComponentProp[] }>,
|
|
161
|
-
): Promise<{ componentName: string; suggestedProps: Record<string, unknown> } | null> {
|
|
162
|
-
try {
|
|
163
|
-
const response = await fetch(`${this.aiConfig.endpoint}/ai/suggest-component`, {
|
|
164
|
-
method: 'POST',
|
|
165
|
-
credentials: 'include',
|
|
166
|
-
headers: this.aiConfig.headers,
|
|
167
|
-
body: JSON.stringify({
|
|
168
|
-
prompt,
|
|
169
|
-
availableComponents,
|
|
170
|
-
pageUrl: window.location.href,
|
|
171
|
-
}),
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
if (!response.ok) {
|
|
175
|
-
throw new Error(`AI request failed: ${response.status} ${response.statusText}`)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const result = await response.json()
|
|
179
|
-
return result.suggestion || null
|
|
180
|
-
} catch (error) {
|
|
181
|
-
logDebug(this.config.debug, 'AI suggestComponent error:', error)
|
|
182
|
-
throw error
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|