@nine-lab/nine-mu 0.1.149 → 0.1.151

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nine-lab/nine-mu",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -0,0 +1,503 @@
1
+ class aiMessage extends HTMLElement
2
+ {
3
+ #message;
4
+ #data;
5
+ #unique;
6
+
7
+ constructor() {
8
+ super();
9
+ this.attachShadow({ mode: 'open' });
10
+ }
11
+
12
+ connectedCallback() {
13
+ this.#message = this.getAttribute("message");
14
+
15
+ this.shadowRoot.innerHTML = `
16
+ <style>
17
+ @import "https://cdn.jsdelivr.net/npm/ninegrid2@${ninegrid.version}/dist/css/ai.css";
18
+ ${ninegrid.getCustomPath(this,"ai.css")}
19
+ </style>
20
+
21
+ <div class="chat-message">
22
+ <div class="message"></div>
23
+ <span class="more"><a href="#">more</a></span>
24
+ </div>
25
+
26
+ <div class="grid"></div>
27
+
28
+ <div class="chat-menu">
29
+ <div class="left-menu">
30
+ <div class="filter"></div>
31
+ <div class="database"></div>
32
+ <div class="excel"></div>
33
+ <div class="maximize"></div>
34
+ </div>
35
+ </div>
36
+ `;
37
+ /**
38
+ *
39
+ <svg class="filter" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
40
+ <path d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2z"/>
41
+ </svg>
42
+ <svg class="database" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
43
+ <path d="M4.318 2.687C5.234 2.271 6.536 2 8 2s2.766.27 3.682.687C12.644 3.125 13 3.627 13 4c0 .374-.356.875-1.318 1.313C10.766 5.729 9.464 6 8 6s-2.766-.27-3.682-.687C3.356 4.875 3 4.373 3 4c0-.374.356-.875 1.318-1.313M13 5.698V7c0 .374-.356.875-1.318 1.313C10.766 8.729 9.464 9 8 9s-2.766-.27-3.682-.687C3.356 7.875 3 7.373 3 7V5.698c.271.202.58.378.904.525C4.978 6.711 6.427 7 8 7s3.022-.289 4.096-.777A5 5 0 0 0 13 5.698M14 4c0-1.007-.875-1.755-1.904-2.223C11.022 1.289 9.573 1 8 1s-3.022.289-4.096.777C2.875 2.245 2 2.993 2 4v9c0 1.007.875 1.755 1.904 2.223C4.978 15.71 6.427 16 8 16s3.022-.289 4.096-.777C13.125 14.755 14 14.007 14 13zm-1 4.698V10c0 .374-.356.875-1.318 1.313C10.766 11.729 9.464 12 8 12s-2.766-.27-3.682-.687C3.356 10.875 3 10.373 3 10V8.698c.271.202.58.378.904.525C4.978 9.71 6.427 10 8 10s3.022-.289 4.096-.777A5 5 0 0 0 13 8.698m0 3V13c0 .374-.356.875-1.318 1.313C10.766 14.729 9.464 15 8 15s-2.766-.27-3.682-.687C3.356 13.875 3 13.373 3 13v-1.302c.271.202.58.378.904.525C4.978 12.71 6.427 13 8 13s3.022-.289 4.096-.777c.324-.147.633-.323.904-.525"/>
44
+ </svg>
45
+ <svg class="excel" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
46
+ <path fill-rule="evenodd" d="M14 4.5V14a2 2 0 0 1-2 2h-1v-1h1a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5zM6.472 15.29a1.2 1.2 0 0 1-.111-.449h.765a.58.58 0 0 0 .254.384q.106.073.25.114.143.041.319.041.246 0 .413-.07a.56.56 0 0 0 .255-.193.5.5 0 0 0 .085-.29.39.39 0 0 0-.153-.326q-.152-.12-.462-.193l-.619-.143a1.7 1.7 0 0 1-.539-.214 1 1 0 0 1-.351-.367 1.1 1.1 0 0 1-.123-.524q0-.366.19-.639.19-.272.527-.422.338-.15.777-.149.457 0 .78.152.324.153.5.41.18.255.2.566h-.75a.56.56 0 0 0-.12-.258.6.6 0 0 0-.247-.181.9.9 0 0 0-.369-.068q-.325 0-.513.152a.47.47 0 0 0-.184.384q0 .18.143.3a1 1 0 0 0 .405.175l.62.143q.326.075.566.211a1 1 0 0 1 .375.358q.135.222.135.56 0 .37-.188.656a1.2 1.2 0 0 1-.539.439q-.351.158-.858.158-.381 0-.665-.09a1.4 1.4 0 0 1-.478-.252 1.1 1.1 0 0 1-.29-.375m-2.945-3.358h-.893L1.81 13.37h-.036l-.832-1.438h-.93l1.227 1.983L0 15.931h.861l.853-1.415h.035l.85 1.415h.908L2.253 13.94zm2.727 3.325H4.557v-3.325h-.79v4h2.487z"/>
47
+ </svg>
48
+ <svg class="maximize" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
49
+ <path fill-rule="evenodd" d="M5.828 10.172a.5.5 0 0 0-.707 0l-4.096 4.096V11.5a.5.5 0 0 0-1 0v3.975a.5.5 0 0 0 .5.5H4.5a.5.5 0 0 0 0-1H1.732l4.096-4.096a.5.5 0 0 0 0-.707m4.344 0a.5.5 0 0 1 .707 0l4.096 4.096V11.5a.5.5 0 1 1 1 0v3.975a.5.5 0 0 1-.5.5H11.5a.5.5 0 0 1 0-1h2.768l-4.096-4.096a.5.5 0 0 1 0-.707m0-4.344a.5.5 0 0 0 .707 0l4.096-4.096V4.5a.5.5 0 1 0 1 0V.525a.5.5 0 0 0-.5-.5H11.5a.5.5 0 0 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 0 .707m-4.344 0a.5.5 0 0 1-.707 0L1.025 1.732V4.5a.5.5 0 0 1-1 0V.525a.5.5 0 0 1 .5-.5H4.5a.5.5 0 0 1 0 1H1.732l4.096 4.096a.5.5 0 0 1 0 .707"/>
50
+ </svg>
51
+ */
52
+ requestAnimationFrame(() => {
53
+ const elMessage = this.shadowRoot.querySelector(".message");
54
+ elMessage.setAttribute("title", this.#message);
55
+ elMessage.innerHTML = this.#message.replaceAll("\n\n", "<br/>").replaceAll("\n", "<br/>");
56
+
57
+ this.shadowRoot.querySelector(".filter").addEventListener("click", e => {
58
+
59
+ //if (e.target.classList.contains("disabled")) return;
60
+ if (this.#unique) {
61
+ const grd = document.querySelector("nine-grid");
62
+
63
+ grd.filtering.set(this.#data.map(item =>
64
+ Object.fromEntries(this.#unique.map(key => [key, item[key]]))
65
+ ));
66
+ }
67
+ });
68
+
69
+ this.shadowRoot.querySelector(".database").addEventListener("click", e => {
70
+ //this.shadowRoot.querySelector("nine-grid").maximize();
71
+ const keys = this.#data.map(item =>
72
+ Object.fromEntries(this.#unique.map(key => [key, item[key]]))
73
+ );
74
+
75
+ console.log(keys);
76
+
77
+ this.dispatchEvent(new CustomEvent("database", { bubbles: true, detail: { key : keys } }));
78
+ });
79
+
80
+ this.shadowRoot.querySelector(".maximize").addEventListener("click", e => {
81
+ this.shadowRoot.querySelector("nine-grid").maximize();
82
+ });
83
+
84
+ this.shadowRoot.querySelector(".excel").addEventListener("click", e => {
85
+ this.shadowRoot.querySelector("nine-grid").export();
86
+ });
87
+
88
+ this.shadowRoot.querySelector(".more a").addEventListener("click", () => {
89
+ alert(this.#message);
90
+ });
91
+
92
+ setTimeout(() => {
93
+ const elMore = this.shadowRoot.querySelector(".more");
94
+
95
+ //if (ninegrid.isEllipsis(this.shadowRoot.querySelector(".message"))) {
96
+ if (this.#message.length > 50) {
97
+ elMore.style.display = "flex";
98
+ elMore.style.position = "absolute";
99
+ }
100
+ else {
101
+ elMore.style.display = "none";
102
+ }
103
+ });
104
+ });
105
+ };
106
+
107
+ initialize = (info, data, unique) => {
108
+ this.#data = data;
109
+ this.#unique = unique;
110
+
111
+
112
+ setTimeout(() => {
113
+ if (!unique) {
114
+ this.shadowRoot.querySelector(".filter").classList.add("disabled");
115
+ this.shadowRoot.querySelector(".database").classList.add("disabled");
116
+ }
117
+
118
+ this.#init(info);
119
+ });
120
+ }
121
+
122
+ #init = (info) => {
123
+
124
+ const rowCount = Number(this.getAttribute("row-count"));
125
+ if (rowCount < 1) {
126
+ this.shadowRoot.querySelector(".grid").style.display = "none";
127
+ this.shadowRoot.querySelector(".chat-menu").style.display = "none";
128
+ return;
129
+ }
130
+
131
+ let colgroup = info.map(() => `<col background-color="#888"/>`).join("");
132
+ let thead = info.map(item => `<th>${item.desc}</th>`).join("");
133
+ let tbody = info.map(item => `<td data-bind="${item.name}" text-align="${item.type == 'number' ? 'right' : 'left'}"></td>`).join("");
134
+
135
+
136
+ const html = `
137
+ <nine-grid class="ai" display-row-count="${rowCount > 5 ? 5 : rowCount}" show-title-bar="false" show-menu-icon="false" show-status-bar="false" select-type="row" auto-fit-col="true" show-title-bar="true" show-menu-icon="true" show-status-bar="true" enable-fixed-col="true" row-resizable="false" col-movable="true">
138
+ <table style="display:none;">
139
+ <colgroup>
140
+ <col background-color="#888" width="30" fixed="left" />
141
+ ${colgroup}
142
+ </colgroup>
143
+ <thead>
144
+ <tr>
145
+ <th>No.</th>
146
+ ${thead}
147
+ </tr>
148
+ </thead>
149
+ <tbody>
150
+ <tr>
151
+ <th><ng-row-indicator/></th>
152
+ ${tbody}
153
+ </tr>
154
+ </tbody>
155
+ </table>
156
+ </nine-grid>
157
+ `;
158
+
159
+ this.shadowRoot.querySelector(".grid").innerHTML = html;
160
+
161
+ setTimeout(() => {
162
+ const grd = this.shadowRoot.querySelector("nine-grid");
163
+ grd.data.source = this.#data;
164
+
165
+ //this.scrollIntoView({ behavior: "smooth", block: "end" });
166
+ });
167
+ };
168
+ }
169
+
170
+ class aiIngMessage extends HTMLElement
171
+ {
172
+ #message;
173
+
174
+ constructor() {
175
+ super();
176
+ this.attachShadow({ mode: 'open' });
177
+ }
178
+
179
+ connectedCallback() {
180
+ //const message = this.getAttribute("message");
181
+
182
+ this.#message = ".";
183
+
184
+ this.shadowRoot.innerHTML = `
185
+ <style>
186
+ @import "https://cdn.jsdelivr.net/npm/ninegrid2@${ninegrid.version}/dist/css/ai.css";
187
+ ${ninegrid.getCustomPath(this,"ai.css")}
188
+ </style>
189
+
190
+ <div class="chat-message">
191
+ .
192
+ </div>
193
+ `;
194
+
195
+ this.#init();
196
+ };
197
+
198
+ #init = () => {
199
+ const interval = setInterval(() => {
200
+ this.#message = this.#message.length < 3 ? this.#message + "." : "";
201
+ this.shadowRoot.querySelector(".chat-message").innerHTML = this.#message || "&nbsp;";
202
+ }, 500);
203
+ };
204
+ }
205
+
206
+ class aiMyMessage extends HTMLElement
207
+ {
208
+ constructor() {
209
+ super();
210
+ this.attachShadow({ mode: 'open' });
211
+ }
212
+
213
+ connectedCallback() {
214
+ const message = this.getAttribute("message");
215
+
216
+ this.shadowRoot.innerHTML = `
217
+ <style>
218
+ @import "https://cdn.jsdelivr.net/npm/ninegrid2@${ninegrid.version}/dist/css/ai.css";
219
+ ${ninegrid.getCustomPath(this,"ai.css")}
220
+ </style>
221
+
222
+ <div class="chat-message">
223
+ ${message}
224
+ </div>
225
+ `;
226
+ };
227
+ }
228
+
229
+ // aiProgressMessage 클래스 정의
230
+ // aiProgressMessage 클래스 정의 수정
231
+ class aiProgressMessage extends HTMLElement {
232
+ #progressData = [];
233
+ #progressElements = new Map();
234
+ #animationIntervals = new Map();
235
+
236
+ constructor() {
237
+ super();
238
+ this.attachShadow({ mode: 'open' });
239
+ }
240
+
241
+ connectedCallback() {
242
+ this.shadowRoot.innerHTML = `
243
+ <style>
244
+ @import "https://cdn.jsdelivr.net/npm/ninegrid2@${ninegrid.version}/dist/css/ai.css";
245
+ ${ninegrid.getCustomPath(this, "ai.css")}
246
+ </style>
247
+ <div class="chat-message progress-message">
248
+ <ul class="progress-list"></ul>
249
+ </div>
250
+ `;
251
+ }
252
+
253
+ /**
254
+ * 진행 상태 데이터를 초기화하고 화면에 표시합니다.
255
+ * @param {Array<Object>} data - [{id: 'step1', message: '분석중입니다.', completedMessage: '분석이 완료되었습니다.'}, ...]
256
+ */
257
+ initialize(data) {
258
+ this.#progressData = data.map(item => ({
259
+ ...item,
260
+ status: 'pending',
261
+ originalMessage: item.message
262
+ }));
263
+ setTimeout(() => {
264
+ this.#renderProgress(); // 초기 렌더링 시 현재 진행 단계를 활성화
265
+ this.#updateCurrentActiveProgress(); // 초기 활성 단계 설정
266
+ }, 300);
267
+ }
268
+
269
+ /**
270
+ * 특정 단계의 진행 상태를 업데이트합니다.
271
+ * @param {string} id - 업데이트할 단계의 고유 ID
272
+ * @param {string} status - 'completed' 또는 'pending'
273
+ */
274
+ updateProgress(id, status) {
275
+ const itemIndex = this.#progressData.findIndex(item => item.id === id);
276
+ if (itemIndex > -1) {
277
+ if (this.#progressData[itemIndex].status !== status) {
278
+ this.#progressData[itemIndex].status = status;
279
+ this.#updateProgressItem(this.#progressData[itemIndex]); // 개별 항목 업데이트
280
+ this.#updateCurrentActiveProgress(); // 활성 진행 단계 재설정
281
+ }
282
+ }
283
+ }
284
+
285
+ // 현재 진행 중인 첫 번째 pending 항목을 찾아 'active' 상태로 만들고 애니메이션 시작
286
+ // 이전에 active였던 항목의 애니메이션은 중지
287
+ #updateCurrentActiveProgress() {
288
+ let foundActive = false;
289
+ this.#progressData.forEach(item => {
290
+ const li = this.#progressElements.get(item.id);
291
+ if (!li) return; // 요소가 아직 렌더링되지 않았으면 스킵
292
+
293
+ // 모든 항목에서 'active' 클래스 제거 및 애니메이션 중지
294
+ li.classList.remove('active');
295
+ if (this.#animationIntervals.has(item.id)) {
296
+ clearInterval(this.#animationIntervals.get(item.id));
297
+ this.#animationIntervals.delete(item.id);
298
+ li.querySelector(".animated-dots").textContent = ''; // 점 제거
299
+ }
300
+
301
+ // 첫 번째 pending 항목을 찾으면 'active'로 설정하고 애니메이션 시작
302
+ if (item.status === 'pending' && !foundActive) {
303
+ li.classList.add('active');
304
+ this.#startAnimation(item);
305
+ foundActive = true;
306
+ }
307
+ });
308
+ }
309
+
310
+ #renderProgress() {
311
+ const progressList = this.shadowRoot.querySelector(".progress-list");
312
+ progressList.innerHTML = '';
313
+ this.#progressElements.clear();
314
+ this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
315
+ this.#animationIntervals.clear();
316
+
317
+ this.#progressData.forEach((item, index) => {
318
+ const li = document.createElement("li");
319
+ li.setAttribute("data-id", item.id);
320
+ li.classList.add("progress-item");
321
+ li.innerHTML = `
322
+ <span class="step-number">${index + 1}.</span>
323
+ <span class="text">${item.originalMessage}</span>
324
+ <span class="animated-dots"></span>
325
+ `;
326
+ progressList.appendChild(li);
327
+ this.#progressElements.set(item.id, li);
328
+ // 초기 렌더링 시에는 'active' 상태는 `#updateCurrentActiveProgress`에서 처리
329
+ this.#updateProgressItemVisuals(item); // 텍스트만 업데이트
330
+ });
331
+ }
332
+
333
+ // 항목의 시각적 상태(텍스트, 완료 체크)만 업데이트
334
+ #updateProgressItemVisuals(item) {
335
+ const li = this.#progressElements.get(item.id);
336
+ if (li) {
337
+ li.classList.remove('pending', 'completed');
338
+ li.classList.add(item.status);
339
+
340
+ const textSpan = li.querySelector(".text");
341
+ const dotsSpan = li.querySelector(".animated-dots");
342
+
343
+ if (item.status === 'completed') {
344
+ textSpan.textContent = item.completedMessage;
345
+ dotsSpan.textContent = ''; // 완료 시 점 제거
346
+ } else { // pending 상태
347
+ textSpan.textContent = item.originalMessage;
348
+ // pending이지만 active가 아닌 경우 점 없음 (CSS의 role)
349
+ }
350
+ }
351
+ }
352
+
353
+ // 점 애니메이션 시작 함수
354
+ #startAnimation(item) {
355
+ const li = this.#progressElements.get(item.id);
356
+ if (li) {
357
+ const dotsSpan = li.querySelector(".animated-dots");
358
+ let dotsCount = 0;
359
+ const intervalId = setInterval(() => {
360
+ dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
361
+ dotsSpan.textContent = '.'.repeat(dotsCount);
362
+ }, 300);
363
+ this.#animationIntervals.set(item.id, intervalId);
364
+ }
365
+ }
366
+
367
+ // 개별 항목의 상태 업데이트 (텍스트 변경, 클래스 추가/제거)
368
+ // 애니메이션 시작/중지는 `#updateCurrentActiveProgress`에서 담당
369
+ #updateProgressItem(item) {
370
+ this.#updateProgressItemVisuals(item); // 텍스트와 클래스 업데이트
371
+ }
372
+ }
373
+
374
+
375
+
376
+ class ChatMessage extends HTMLElement
377
+ {
378
+ constructor() {
379
+ super();
380
+ this.attachShadow({ mode: 'open' });
381
+ }
382
+
383
+ connectedCallback() {
384
+ const message = this.getAttribute("message");
385
+
386
+ this.shadowRoot.innerHTML = `
387
+ <style>
388
+ @import "https://cdn.jsdelivr.net/npm/ninegrid2@${ninegrid.version}/dist/css/ai.css";
389
+ ${ninegrid.getCustomPath(this,"ai.css")}
390
+ </style>
391
+
392
+ <div class="chat-body">
393
+ </div>
394
+ `;
395
+
396
+ this.#init();
397
+ };
398
+
399
+ #init = () => {
400
+
401
+ };
402
+
403
+
404
+ add = (sender, message, info, data, unique) => {
405
+
406
+ if (unique && !Array.isArray(unique)) {
407
+ unique = unique.split(",");
408
+ }
409
+
410
+ const target = this.shadowRoot.querySelector(".chat-body");
411
+
412
+ //console.log(data);
413
+
414
+ let el;
415
+ switch (sender) {
416
+ case "me":
417
+ el = document.createElement("nx-ai-my-message");
418
+ el.setAttribute("message", message);
419
+ target.appendChild(el);
420
+ break;
421
+
422
+ case "ing":
423
+ el = document.createElement("nx-ai-ing-message");
424
+ //el.setAttribute("message", message);
425
+ target.appendChild(el);
426
+ break;
427
+
428
+ case "ai":
429
+ this.shadowRoot.querySelectorAll("nx-ai-ing-message").forEach(el => {
430
+ el.remove();
431
+ });
432
+
433
+ el = document.createElement("nx-ai-message");
434
+ el.setAttribute("message", message);
435
+ el.setAttribute("row-count", data ? data.length : 0);
436
+ //el.data = data;
437
+ el.initialize(info, data, unique);
438
+ target.appendChild(el);
439
+ break;
440
+
441
+ default:
442
+ break;
443
+ }
444
+
445
+ setTimeout(() => {
446
+ el.scrollIntoView({ behavior: "smooth", block: "end" });
447
+ }, 200);
448
+ };
449
+
450
+ /**
451
+ * 챗 메시지를 추가합니다.
452
+ * @param {string} sender - 메시지 발신자 ('me', 'ing', 'ai', 'progress')
453
+ * @param {string} message - 메시지 내용 (progress 타입의 경우 사용되지 않음)
454
+ * @param {Array<Object>} info - nine-grid 정보 (ai 타입에만 해당)
455
+ * @param {Array<Object>} data - nine-grid 데이터 (ai 타입에만 해당)
456
+ * @param {Array<string>|string} unique - nine-grid 고유 키 (ai 타입에만 해당)
457
+ * @param {Array<Object>} progressData - aiProgressMessage의 초기 진행 데이터 (progress 타입에만 해당)
458
+ * @returns {HTMLElement|null} 생성된 메시지 엘리먼트 (특히 aiProgressMessage의 경우 업데이트를 위해 반환)
459
+ */
460
+ addProgress = (progressData = null) => { // progressData 파라미터 추가
461
+
462
+ const target = this.shadowRoot.querySelector(".chat-body");
463
+
464
+ this.shadowRoot.querySelectorAll("nx-ai-ing-message").forEach(el => {
465
+ el.remove();
466
+ });
467
+
468
+ let el = document.createElement("nx-ai-progress-message");
469
+ if (progressData) {
470
+ el.initialize(progressData); // progressData로 초기화
471
+ }
472
+ target.appendChild(el);
473
+
474
+ setTimeout(() => {
475
+ if (el) { // el이 null이 아닐 때만 scrollIntoView 호출
476
+ el.scrollIntoView({ behavior: "smooth", block: "end" });
477
+ }
478
+ }, 200);
479
+
480
+ return el; // 생성된 엘리먼트를 반환
481
+ };
482
+ }
483
+
484
+
485
+ if (!customElements.get('nx-ai-message')) {
486
+ customElements.define("nx-ai-message", aiMessage);
487
+ }
488
+
489
+ if (!customElements.get('nx-ai-ing-message')) {
490
+ customElements.define("nx-ai-ing-message", aiIngMessage);
491
+ }
492
+
493
+ if (!customElements.get('nx-ai-my-message')) {
494
+ customElements.define("nx-ai-my-message", aiMyMessage);
495
+ }
496
+
497
+ if (!customElements.get('nx-ai-progress-message')) {
498
+ customElements.define("nx-ai-progress-message", aiProgressMessage);
499
+ }
500
+
501
+ if (!customElements.get('nine-chat-message')) {
502
+ customElements.define("nine-chat-message", ChatMessage);
503
+ }
@@ -95,7 +95,7 @@ export class NineChat extends HTMLElement {
95
95
  <div class="logo"><span></span></div>
96
96
  <div id="status-tag" style="font-size:10px; color:#ff5722; padding:5px;">nine-mu Engine Ready</div>
97
97
  </div>
98
- <nx-ai-chat></nx-ai-chat>
98
+ <nine-chat-message></nine-chat-message>
99
99
  <div class="foot">
100
100
  <div class="apply-src">
101
101
  ${['MyBatis', 'Service', 'Controller', 'JavaScript'].map(t => `