@nine-lab/nine-mu 0.1.327 → 0.1.329
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/css/nine-mu.css +1 -304
- package/dist/nine-mu.js +17 -52
- package/dist/nine-mu.js.map +1 -1
- package/dist/nine-mu.umd.js +3 -3
- package/dist/nine-mu.umd.js.map +1 -1
- package/package.json +1 -1
- package/public/css/nine-mu.css +1 -304
- package/src/components/ChatMessage.js +2 -3
- package/src/components/NineChat.js +6 -85
- package/src/components/NotificationHandler.js +6 -27
package/package.json
CHANGED
package/public/css/nine-mu.css
CHANGED
|
@@ -248,169 +248,6 @@
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
|
|
251
|
-
:host(nx-ai-message) {
|
|
252
|
-
display: flex;
|
|
253
|
-
justify-content: flex-start;
|
|
254
|
-
padding: 5px;
|
|
255
|
-
flex-direction: column;
|
|
256
|
-
|
|
257
|
-
.chat-message {
|
|
258
|
-
max-width: 70%;
|
|
259
|
-
border-radius: 8px;
|
|
260
|
-
font-size: 14px;
|
|
261
|
-
background-color: #fff;
|
|
262
|
-
color: black;
|
|
263
|
-
align-self: flex-start;
|
|
264
|
-
text-align: left;
|
|
265
|
-
position: relative;
|
|
266
|
-
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.15);
|
|
267
|
-
text-overflow: ellipsis;
|
|
268
|
-
padding: 8px 16px;
|
|
269
|
-
display: flex;
|
|
270
|
-
align-items: center;
|
|
271
|
-
|
|
272
|
-
div.message {
|
|
273
|
-
display: contents;
|
|
274
|
-
-webkit-line-clamp: 3;
|
|
275
|
-
-webkit-box-orient: vertical;
|
|
276
|
-
overflow: hidden;
|
|
277
|
-
padding: 0;
|
|
278
|
-
flex-grow: 1;
|
|
279
|
-
/* 줄바꿈 강제 적용 */
|
|
280
|
-
/**word-wrap: break-word;*/ /* 긴 단어를 줄바꿈 */
|
|
281
|
-
overflow-wrap: anywhere; /* 텍스트 길이에 따라 자동 줄바꿈 */
|
|
282
|
-
white-space: normal; /* 공백 처리 */
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
span.more {
|
|
286
|
-
display: none;
|
|
287
|
-
right: 4px;
|
|
288
|
-
bottom: 0px;
|
|
289
|
-
font-size: 9px;
|
|
290
|
-
font-weight: 700;
|
|
291
|
-
|
|
292
|
-
a {
|
|
293
|
-
position: relative;
|
|
294
|
-
color: green;
|
|
295
|
-
text-decoration: none;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
a::after {
|
|
299
|
-
content: "";
|
|
300
|
-
position: absolute;
|
|
301
|
-
left: 0;
|
|
302
|
-
bottom: -2px;
|
|
303
|
-
width: 100%;
|
|
304
|
-
height: 2px;
|
|
305
|
-
background-color: green;
|
|
306
|
-
transform: scaleX(0);
|
|
307
|
-
transition: transform 0.3s ease-in-out;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
a:hover::after {
|
|
311
|
-
transform: scaleX(1);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.grid {
|
|
317
|
-
margin-top: 8px;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.chat-menu {
|
|
321
|
-
display: flex;
|
|
322
|
-
justify-content: space-between; /* 좌우 정렬 */
|
|
323
|
-
align-items: center; /* 세로 중앙 정렬 */
|
|
324
|
-
width: 100%;
|
|
325
|
-
margin-top: 2px;
|
|
326
|
-
|
|
327
|
-
.left-menu{
|
|
328
|
-
display: flex;
|
|
329
|
-
gap: 4px;
|
|
330
|
-
|
|
331
|
-
.filter.disabled, .database.disabled {
|
|
332
|
-
pointer-events: none;
|
|
333
|
-
color: #ccc;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.filter, .database, .excel, .maximize {
|
|
337
|
-
margin-left: 0;
|
|
338
|
-
cursor: pointer;
|
|
339
|
-
color: #999;
|
|
340
|
-
width: 16px;
|
|
341
|
-
height: 16px;
|
|
342
|
-
background-repeat: no-repeat;
|
|
343
|
-
background-position: center;
|
|
344
|
-
background-size: auto;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.filter svg {
|
|
348
|
-
color: #999;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.filter:hover, .database:hover, .excel:hover, .maximize:hover {
|
|
352
|
-
color: green;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
.filter {
|
|
356
|
-
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="gray" viewBox="0 0 16 16"><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"/></svg>');
|
|
357
|
-
}
|
|
358
|
-
.database {
|
|
359
|
-
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="gray" viewBox="0 0 16 16"><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"/></svg>');
|
|
360
|
-
}
|
|
361
|
-
.excel {
|
|
362
|
-
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="gray" viewBox="0 0 16 16"><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"/></svg>');
|
|
363
|
-
}
|
|
364
|
-
.maximize {
|
|
365
|
-
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="gray" viewBox="0 0 16 16"><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"/></svg>');
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
:host(nx-ai-ing-message) {
|
|
373
|
-
display: flex;
|
|
374
|
-
justify-content: flex-start;
|
|
375
|
-
padding: 0;
|
|
376
|
-
|
|
377
|
-
.chat-message {
|
|
378
|
-
padding: 0px 8px;
|
|
379
|
-
color: #999;
|
|
380
|
-
align-self: flex-start;
|
|
381
|
-
text-align: left;
|
|
382
|
-
position: relative;
|
|
383
|
-
font-size: 32px;
|
|
384
|
-
font-weight: bold;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
:host(nx-ai-my-message) {
|
|
390
|
-
display: flex;
|
|
391
|
-
justify-content: flex-end;
|
|
392
|
-
padding: 5px;
|
|
393
|
-
|
|
394
|
-
.chat-message {
|
|
395
|
-
max-width: 70%;
|
|
396
|
-
padding: 8px 16px;
|
|
397
|
-
border-radius: 8px;
|
|
398
|
-
font-size: 14px;
|
|
399
|
-
background-color: #fef01b;
|
|
400
|
-
text-align: left;
|
|
401
|
-
color: #333;
|
|
402
|
-
align-self: flex-end;
|
|
403
|
-
position: relative;
|
|
404
|
-
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.15);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
:host(nx-ai-chat) {
|
|
409
|
-
width: 100%;
|
|
410
|
-
height: 100%;
|
|
411
|
-
overflow: scroll;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
251
|
|
|
415
252
|
|
|
416
253
|
|
|
@@ -512,147 +349,6 @@
|
|
|
512
349
|
animation: slideRight 0.3s ease-out forwards;
|
|
513
350
|
}
|
|
514
351
|
|
|
515
|
-
:host(nine-ai-diff-popup) {
|
|
516
|
-
|
|
517
|
-
div.buttons {
|
|
518
|
-
position: absolute;
|
|
519
|
-
right: 16px;
|
|
520
|
-
/* width: 100px; */
|
|
521
|
-
display: flex;
|
|
522
|
-
flex-direction: row;
|
|
523
|
-
justify-content: flex-end;
|
|
524
|
-
z-index: 1;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
button.save {
|
|
528
|
-
cursor: pointer;
|
|
529
|
-
outline: none;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
:host(nine-ai-diff) {
|
|
534
|
-
width: 100%;
|
|
535
|
-
height: 100%;
|
|
536
|
-
|
|
537
|
-
.wrapper {
|
|
538
|
-
display: flex;
|
|
539
|
-
position: relative;
|
|
540
|
-
--gap: 8px;
|
|
541
|
-
--font-family: monospace;
|
|
542
|
-
height: 100%;
|
|
543
|
-
}
|
|
544
|
-
.panel {
|
|
545
|
-
width: 50%;
|
|
546
|
-
border: 1px solid #ccc;
|
|
547
|
-
--padding: 8px;
|
|
548
|
-
overflow: auto;
|
|
549
|
-
white-space: pre-wrap;
|
|
550
|
-
text-align: left;
|
|
551
|
-
display: flex;
|
|
552
|
-
justify-content: flex-start; /* 좌측 정렬 */
|
|
553
|
-
align-items: flex-start; /* 상단 정렬 */
|
|
554
|
-
flex-direction: column;
|
|
555
|
-
box-sizing: border-box;
|
|
556
|
-
}
|
|
557
|
-
.panel pre {
|
|
558
|
-
margin: 0;
|
|
559
|
-
--padding: 8px;
|
|
560
|
-
text-align: left;
|
|
561
|
-
white-space: pre-wrap;
|
|
562
|
-
word-break: break-word;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
.cm-editor {
|
|
566
|
-
height: 100%;
|
|
567
|
-
width: 100%;
|
|
568
|
-
--padding-left: 80px;
|
|
569
|
-
}
|
|
570
|
-
.cm-content { /* CodeMirror 텍스트 내용을 감싸는 내부 div */
|
|
571
|
-
}
|
|
572
|
-
/* 각 라인에 버튼 공간 확보 */
|
|
573
|
-
|
|
574
|
-
/* ideDiff.css */
|
|
575
|
-
|
|
576
|
-
/* 기본적인 CodeMirror 라인 포지셔닝 */
|
|
577
|
-
.cm-line {
|
|
578
|
-
position: relative;
|
|
579
|
-
--display: flex;
|
|
580
|
-
padding-left: 18px;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
/* 병합 버튼 컨테이너 */
|
|
584
|
-
.cm-merge-button-container {
|
|
585
|
-
position: absolute;
|
|
586
|
-
height: 16px;
|
|
587
|
-
width: 16px; /* 버튼 너비 고정으로 겹침 방지 */
|
|
588
|
-
left: 2px; /* 라인 번호 영역 바로 옆에 배치. 필요에 따라 조절하세요. */
|
|
589
|
-
top: 50%;
|
|
590
|
-
transform: translateY(-50%);
|
|
591
|
-
--z-index: 1; /* 다른 요소 위에 표시되도록 Z-index를 높게 설정 */
|
|
592
|
-
display: flex;
|
|
593
|
-
--gap: 5px;
|
|
594
|
-
justify-content: center; /* 버튼 중앙 정렬 */
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/* 병합 버튼 기본 스타일 */
|
|
598
|
-
.cm-merge-button {
|
|
599
|
-
--margin: 2px 0;
|
|
600
|
-
width: 100%;
|
|
601
|
-
border: none;
|
|
602
|
-
border-radius: 3px;
|
|
603
|
-
cursor: pointer;
|
|
604
|
-
opacity: 0.7; /* 기본적으로 약간 투명하게 */
|
|
605
|
-
transition: opacity 0.2s ease-in-out; /* 호버 시 부드러운 전환 */
|
|
606
|
-
background-repeat: no-repeat;
|
|
607
|
-
background-position: center;
|
|
608
|
-
background-size: auto;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/* 호버 시 버튼 불투명도 증가 */
|
|
612
|
-
.cm-merge-button:hover {
|
|
613
|
-
opacity: 1;
|
|
614
|
-
background-color: #e0e0e0;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
/* AI 추천을 현재 소스에 '적용'하는 버튼 (오른쪽 TOBE 에디터에 붙음) */
|
|
618
|
-
.cm-merge-button.accept {
|
|
619
|
-
background-color: #4CAF50; /* 녹색 */
|
|
620
|
-
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-arrow-left-short" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M12 8a.5.5 0 0 1-.5.5H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H11.5a.5.5 0 0 1 .5.5"/></svg>');
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
/* AI의 삭제를 현재 소스 기준으로 '되돌리는' 버튼 (왼쪽 ASIS 에디터에 붙음) */
|
|
624
|
-
.cm-merge-button.revert {
|
|
625
|
-
background-color: #f44336; /* 빨간색 */
|
|
626
|
-
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-x" viewBox="0 0 16 16"><path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/></svg>');
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
/* 삽입된 라인 (AI 추천 소스에 새로 추가된 라인) 배경색 및 경계선 */
|
|
630
|
-
.cm-inserted-line-bg {
|
|
631
|
-
background-color: #e6ffed; /* 연한 녹색 */
|
|
632
|
-
--border-left: 3px solid #66bb6a; /* 진한 녹색 */
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
/* 삭제된 라인 (현재 소스에서 AI가 삭제한 것으로 판단된 라인) 배경색 및 경계선 */
|
|
636
|
-
.cm-deleted-line-bg {
|
|
637
|
-
background-color: #ffebe9; /* 연한 빨간색 */
|
|
638
|
-
--border-left: 3px solid #ef5350; /* 진한 빨간색 */
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
/* CodeMirror 선택 영역 배경색 */
|
|
642
|
-
.cm-selectionBackground {
|
|
643
|
-
background-color: #d7d4f9 !important; /* 보라색 계열 */
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/* 텍스트 선택 시 배경색 (브라우저 기본 선택색 재정의) */
|
|
647
|
-
.cm-editor ::selection {
|
|
648
|
-
background-color: #d7d4f9 !important;
|
|
649
|
-
color: inherit !important; /* 텍스트 색상은 유지 */
|
|
650
|
-
}
|
|
651
|
-
.cm-editor::-moz-selection { /* Firefox를 위한 접두사 */
|
|
652
|
-
background-color: #d7d4f9 !important;
|
|
653
|
-
color: inherit !important;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
352
|
|
|
657
353
|
@keyframes slide {
|
|
658
354
|
0% { left: -40%; }
|
|
@@ -1084,6 +780,7 @@
|
|
|
1084
780
|
font-weight: 700;
|
|
1085
781
|
|
|
1086
782
|
a {
|
|
783
|
+
display: none;
|
|
1087
784
|
position: relative;
|
|
1088
785
|
color: green;
|
|
1089
786
|
text-decoration: none;
|
|
@@ -68,8 +68,6 @@ class AiMessage extends HTMLElement
|
|
|
68
68
|
Object.fromEntries(this.#unique.map(key => [key, item[key]]))
|
|
69
69
|
);
|
|
70
70
|
|
|
71
|
-
console.log(keys);
|
|
72
|
-
|
|
73
71
|
this.dispatchEvent(new CustomEvent("database", { bubbles: true, detail: { key : keys } }));
|
|
74
72
|
});
|
|
75
73
|
|
|
@@ -368,7 +366,8 @@ class ChatMessageBody extends HTMLElement
|
|
|
368
366
|
};
|
|
369
367
|
|
|
370
368
|
#renderer = () => {
|
|
371
|
-
|
|
369
|
+
|
|
370
|
+
const customImport = nine.cssPath ? `@import "${nine.cssPath}/ninePanel.css";` : "";
|
|
372
371
|
|
|
373
372
|
this.shadowRoot.innerHTML = `
|
|
374
373
|
<style>
|
|
@@ -72,7 +72,6 @@ export class NineChat extends HTMLElement {
|
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
this.shadowRoot.querySelector(".make-menu")?.addEventListener("click", this.#makeMenuHandler);
|
|
76
75
|
this.shadowRoot.querySelector(".source-gen")?.addEventListener("click", this.#sourceGenHandler);
|
|
77
76
|
}
|
|
78
77
|
|
|
@@ -112,49 +111,15 @@ export class NineChat extends HTMLElement {
|
|
|
112
111
|
} else {
|
|
113
112
|
trace.log(result);
|
|
114
113
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const parsed = JSON.parse(rawText);
|
|
114
|
+
// 💡 [핵심] MCP 규격의 content[0].text에서 스트링을 추출합니다.
|
|
115
|
+
const rawText = result?.content?.[0]?.text;
|
|
116
|
+
//trace.log(rawText);
|
|
117
|
+
// 텍스트를 JSON 객체로 파싱
|
|
118
|
+
const parsed = JSON.parse(rawText);
|
|
121
119
|
|
|
120
|
+
if (parsed.message) {
|
|
122
121
|
this.#manager.addChatHistory(parsed.message);
|
|
123
122
|
this.#$nineChatMessage.add("ai", parsed.message);
|
|
124
|
-
|
|
125
|
-
//trace.log(parsed.action);
|
|
126
|
-
//"source-missing"
|
|
127
|
-
//trace.log(parsed.data);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const asis = await this.#manager.getRoutes();
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
if (parsed?.selected_tool === "generate-menu") {
|
|
134
|
-
const hasCreated = parsed?.data.some(item => item.action === 'CREATE');
|
|
135
|
-
const hasUpdated = parsed?.data.some(item => item.action === 'UPDATE');
|
|
136
|
-
const hasDeleted = parsed?.data.some(item => item.action === 'DELETE');
|
|
137
|
-
|
|
138
|
-
if (hasUpdated || hasCreated || hasDeleted) {
|
|
139
|
-
// 진짜 메뉴명 변경이나 이동만 요청한 경우
|
|
140
|
-
nine.alert("메뉴 정리를 위한 라우터 정보 저장 화면으로 이동합니다.").then(res => {
|
|
141
|
-
const tobe = (parsed?.data || [])
|
|
142
|
-
.filter(item => item.action !== 'DELETE')
|
|
143
|
-
.map(({ isNew, action, ...rest }) => rest);
|
|
144
|
-
|
|
145
|
-
this.#showDiff(asis, tobe, "json");
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
} */
|
|
149
|
-
|
|
150
|
-
// 💡 만약 intent가 EXECUTE_TOOL이거나 NAVIGATE일 때 프론트에서
|
|
151
|
-
// 화면 이동(Routing)이나 추가 액션을 해야 한다면 여기서 parsedData.target_path 등을 활용하면 됩니다!
|
|
152
|
-
|
|
153
|
-
} catch (err) {
|
|
154
|
-
trace.error(err);
|
|
155
|
-
// 만약 AI가 JSON 형식이 아닌 일반 텍스트로 답장했을 경우를 대비한 예외 처리
|
|
156
|
-
const fallbackMessage = result?.content?.[0]?.text || "응답 데이터를 해석하지 못했습니다.";
|
|
157
|
-
this.#$nineChatMessage.add("ai", fallbackMessage);
|
|
158
123
|
}
|
|
159
124
|
}
|
|
160
125
|
}
|
|
@@ -213,55 +178,11 @@ export class NineChat extends HTMLElement {
|
|
|
213
178
|
this.#$nineChatMessage.add(who, message);
|
|
214
179
|
}
|
|
215
180
|
|
|
216
|
-
#makeMenuHandler = async e => {
|
|
217
|
-
|
|
218
|
-
const prompt = await nine.prompt("메뉴생성시 필요한 AI 프롬프트를 입력하세요.").rgb();
|
|
219
|
-
if (prompt === null || prompt === undefined) return;
|
|
220
|
-
|
|
221
|
-
const res = await api.post(`/nine-mu/source/readFile`, { path: this.#routesPath });
|
|
222
|
-
trace.log(res);
|
|
223
|
-
|
|
224
|
-
if (!res || !res?.contents) return;
|
|
225
|
-
|
|
226
|
-
const jsonRoutes = res?.contents ? JSON.parse(res?.contents) : {};
|
|
227
|
-
trace.log(jsonRoutes);
|
|
228
|
-
|
|
229
|
-
// 1. 미생성 소스 분석 요청
|
|
230
|
-
const res2 = await api.post(`${this.#connectorUrl}/api/source/missing`, {
|
|
231
|
-
routes : jsonRoutes,
|
|
232
|
-
prompt : prompt
|
|
233
|
-
});
|
|
234
|
-
//trace.log("분석 완료. 생성할 태스크:", res2?.tasks);
|
|
235
|
-
|
|
236
|
-
if (res2.success && res2?.tasks) {
|
|
237
|
-
this.#showDiff(jsonRoutes, res2?.tasks, "json");
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
181
|
#sourceGenHandler = async e => {
|
|
242
182
|
const routes = await this.#manager.getRoutes();
|
|
243
183
|
const response = await this.#manager.analyzeUnmappedRoutes(routes);
|
|
244
184
|
trace.log(response);
|
|
245
185
|
}
|
|
246
|
-
|
|
247
|
-
#showDiff = (asis, tobe, lang) => {
|
|
248
|
-
// 1. 혹시 잔상이 남아있을지 모르니 기존에 생성된 팝업이 있다면 강제 제거
|
|
249
|
-
const oldPopup = this.shadowRoot.querySelector('nine-menu-diff-popup');
|
|
250
|
-
if (oldPopup) {
|
|
251
|
-
oldPopup.remove();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// 2. 동적으로 커스텀 엘리먼트 생성
|
|
255
|
-
const $diffPopup = document.createElement('nine-menu-diff-popup');
|
|
256
|
-
|
|
257
|
-
// 3. 래퍼(wrapper) 안이나 shadowRoot 제일 밑바닥에 부착
|
|
258
|
-
const container = this.shadowRoot.querySelector('.wrapper') || this.shadowRoot;
|
|
259
|
-
container.appendChild($diffPopup);
|
|
260
|
-
|
|
261
|
-
// 4. 데이터 주입 및 팝업 실행
|
|
262
|
-
// 💡 팝업이 네이티브 <dialog> 기반이라면 .popup() 내부에서 showModal()이 실행될 겁니다.
|
|
263
|
-
$diffPopup.popup().data(asis, tobe, lang);
|
|
264
|
-
}
|
|
265
186
|
}
|
|
266
187
|
|
|
267
188
|
if (!customElements.get('nine-chat')) {
|
|
@@ -33,33 +33,12 @@ export class NotificationHandler {
|
|
|
33
33
|
this.#owner.addMessage("ing", "");
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.#generateSource(data);
|
|
43
|
-
break;
|
|
44
|
-
|
|
45
|
-
case "modify-source-brain":
|
|
46
|
-
this.#collectModifySource(data);
|
|
47
|
-
break;
|
|
48
|
-
|
|
49
|
-
case "modify-source-brain-completed":
|
|
50
|
-
this.#openDiffPopup();
|
|
51
|
-
break;
|
|
52
|
-
} */
|
|
53
|
-
|
|
54
|
-
// 자바의 -> 처럼 자바스크립트의 => (화살표 함수)를 활용한 매핑
|
|
55
|
-
const runAction = {
|
|
56
|
-
"generate-menu-completed": () => this.#generateMenu(data),
|
|
57
|
-
"generate-source-brain": () => this.#generateSource(data),
|
|
58
|
-
"modify-source-brain": () => this.#collectModifySource(data),
|
|
59
|
-
"modify-source-brain-completed": () => this.#openDiffPopup(),
|
|
60
|
-
}[logger];
|
|
61
|
-
|
|
62
|
-
runAction?.();
|
|
36
|
+
({
|
|
37
|
+
"generate-menu-completed": () => this.#generateMenu(data),
|
|
38
|
+
"generate-source-brain": () => this.#generateSource(data),
|
|
39
|
+
"modify-source-brain": () => this.#collectModifySource(data),
|
|
40
|
+
"modify-source-brain-completed": () => this.#openDiffPopup(),
|
|
41
|
+
}[logger])?.();
|
|
63
42
|
}
|
|
64
43
|
|
|
65
44
|
/**
|