@mongoosejs/studio 0.0.74 → 0.0.75
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/backend/actions/ChatMessage/executeScript.js +74 -0
- package/backend/actions/ChatMessage/index.js +3 -0
- package/backend/actions/ChatThread/createChatMessage.js +253 -0
- package/backend/actions/ChatThread/createChatThread.js +19 -0
- package/backend/actions/ChatThread/getChatThread.js +36 -0
- package/backend/actions/ChatThread/index.js +6 -0
- package/backend/actions/ChatThread/listChatThreads.js +24 -0
- package/backend/actions/index.js +2 -0
- package/backend/db/chatMessageSchema.js +30 -0
- package/backend/db/chatThreadSchema.js +15 -0
- package/backend/index.js +6 -2
- package/express.js +1 -0
- package/frontend/public/app.js +2902 -196
- package/frontend/public/tw.css +146 -0
- package/frontend/src/api.js +38 -3
- package/frontend/src/async-button/async-button.html +12 -2
- package/frontend/src/chat/chat-message/chat-message.html +16 -0
- package/frontend/src/chat/chat-message/chat-message.js +66 -0
- package/frontend/src/chat/chat-message-script/chat-message-script.html +52 -0
- package/frontend/src/chat/chat-message-script/chat-message-script.js +35 -0
- package/frontend/src/chat/chat.html +69 -0
- package/frontend/src/chat/chat.js +89 -0
- package/frontend/src/index.js +22 -37
- package/frontend/src/modal/modal.html +2 -2
- package/frontend/src/modal/modal.js +3 -2
- package/frontend/src/navbar/navbar.html +4 -0
- package/frontend/src/navbar/navbar.js +3 -0
- package/frontend/src/routes.js +19 -3
- package/package.json +2 -1
package/frontend/public/tw.css
CHANGED
|
@@ -614,6 +614,14 @@ video {
|
|
|
614
614
|
right: 0px;
|
|
615
615
|
}
|
|
616
616
|
|
|
617
|
+
.right-1 {
|
|
618
|
+
right: 0.25rem;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.top-1 {
|
|
622
|
+
top: 0.25rem;
|
|
623
|
+
}
|
|
624
|
+
|
|
617
625
|
.top-\[90\%\] {
|
|
618
626
|
top: 90%;
|
|
619
627
|
}
|
|
@@ -648,6 +656,11 @@ video {
|
|
|
648
656
|
margin-bottom: -0.5rem;
|
|
649
657
|
}
|
|
650
658
|
|
|
659
|
+
.mx-4 {
|
|
660
|
+
margin-left: 1rem;
|
|
661
|
+
margin-right: 1rem;
|
|
662
|
+
}
|
|
663
|
+
|
|
651
664
|
.mx-auto {
|
|
652
665
|
margin-left: auto;
|
|
653
666
|
margin-right: auto;
|
|
@@ -694,6 +707,10 @@ video {
|
|
|
694
707
|
margin-left: 0.75rem;
|
|
695
708
|
}
|
|
696
709
|
|
|
710
|
+
.ml-auto {
|
|
711
|
+
margin-left: auto;
|
|
712
|
+
}
|
|
713
|
+
|
|
697
714
|
.mr-1 {
|
|
698
715
|
margin-right: 0.25rem;
|
|
699
716
|
}
|
|
@@ -785,10 +802,18 @@ video {
|
|
|
785
802
|
height: 2rem;
|
|
786
803
|
}
|
|
787
804
|
|
|
805
|
+
.\!h-\[90vh\] {
|
|
806
|
+
height: 90vh !important;
|
|
807
|
+
}
|
|
808
|
+
|
|
788
809
|
.h-16 {
|
|
789
810
|
height: 4rem;
|
|
790
811
|
}
|
|
791
812
|
|
|
813
|
+
.h-3 {
|
|
814
|
+
height: 0.75rem;
|
|
815
|
+
}
|
|
816
|
+
|
|
792
817
|
.h-4 {
|
|
793
818
|
height: 1rem;
|
|
794
819
|
}
|
|
@@ -825,14 +850,30 @@ video {
|
|
|
825
850
|
height: 100%;
|
|
826
851
|
}
|
|
827
852
|
|
|
853
|
+
.h-px {
|
|
854
|
+
height: 1px;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
.max-h-\[30vh\] {
|
|
858
|
+
max-height: 30vh;
|
|
859
|
+
}
|
|
860
|
+
|
|
828
861
|
.max-h-\[50vh\] {
|
|
829
862
|
max-height: 50vh;
|
|
830
863
|
}
|
|
831
864
|
|
|
865
|
+
.\!w-\[90vw\] {
|
|
866
|
+
width: 90vw !important;
|
|
867
|
+
}
|
|
868
|
+
|
|
832
869
|
.w-16 {
|
|
833
870
|
width: 4rem;
|
|
834
871
|
}
|
|
835
872
|
|
|
873
|
+
.w-3 {
|
|
874
|
+
width: 0.75rem;
|
|
875
|
+
}
|
|
876
|
+
|
|
836
877
|
.w-4 {
|
|
837
878
|
width: 1rem;
|
|
838
879
|
}
|
|
@@ -873,6 +914,14 @@ video {
|
|
|
873
914
|
max-width: 64rem;
|
|
874
915
|
}
|
|
875
916
|
|
|
917
|
+
.max-w-\[calc\(100\%-6\.5rem\)\] {
|
|
918
|
+
max-width: calc(100% - 6.5rem);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
.max-w-xs {
|
|
922
|
+
max-width: 20rem;
|
|
923
|
+
}
|
|
924
|
+
|
|
876
925
|
.flex-1 {
|
|
877
926
|
flex: 1 1 0%;
|
|
878
927
|
}
|
|
@@ -909,6 +958,10 @@ video {
|
|
|
909
958
|
transform-origin: top right;
|
|
910
959
|
}
|
|
911
960
|
|
|
961
|
+
.transform {
|
|
962
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
963
|
+
}
|
|
964
|
+
|
|
912
965
|
.cursor-not-allowed {
|
|
913
966
|
cursor: not-allowed;
|
|
914
967
|
}
|
|
@@ -943,10 +996,18 @@ video {
|
|
|
943
996
|
flex-direction: column;
|
|
944
997
|
}
|
|
945
998
|
|
|
999
|
+
.items-start {
|
|
1000
|
+
align-items: flex-start;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
946
1003
|
.items-center {
|
|
947
1004
|
align-items: center;
|
|
948
1005
|
}
|
|
949
1006
|
|
|
1007
|
+
.justify-end {
|
|
1008
|
+
justify-content: flex-end;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
950
1011
|
.justify-center {
|
|
951
1012
|
justify-content: center;
|
|
952
1013
|
}
|
|
@@ -1003,6 +1064,12 @@ video {
|
|
|
1003
1064
|
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
|
1004
1065
|
}
|
|
1005
1066
|
|
|
1067
|
+
.space-x-3 > :not([hidden]) ~ :not([hidden]) {
|
|
1068
|
+
--tw-space-x-reverse: 0;
|
|
1069
|
+
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
|
|
1070
|
+
margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1006
1073
|
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
|
|
1007
1074
|
--tw-space-y-reverse: 0;
|
|
1008
1075
|
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
|
|
@@ -1052,10 +1119,18 @@ video {
|
|
|
1052
1119
|
overflow: auto;
|
|
1053
1120
|
}
|
|
1054
1121
|
|
|
1122
|
+
.overflow-hidden {
|
|
1123
|
+
overflow: hidden;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1055
1126
|
.overflow-x-auto {
|
|
1056
1127
|
overflow-x: auto;
|
|
1057
1128
|
}
|
|
1058
1129
|
|
|
1130
|
+
.overflow-y-auto {
|
|
1131
|
+
overflow-y: auto;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1059
1134
|
.truncate {
|
|
1060
1135
|
overflow: hidden;
|
|
1061
1136
|
text-overflow: ellipsis;
|
|
@@ -1066,6 +1141,10 @@ video {
|
|
|
1066
1141
|
white-space: nowrap;
|
|
1067
1142
|
}
|
|
1068
1143
|
|
|
1144
|
+
.whitespace-pre-wrap {
|
|
1145
|
+
white-space: pre-wrap;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1069
1148
|
.rounded {
|
|
1070
1149
|
border-radius: 0.25rem;
|
|
1071
1150
|
}
|
|
@@ -1120,6 +1199,14 @@ video {
|
|
|
1120
1199
|
border-right-width: 1px;
|
|
1121
1200
|
}
|
|
1122
1201
|
|
|
1202
|
+
.border-t {
|
|
1203
|
+
border-top-width: 1px;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
.border-none {
|
|
1207
|
+
border-style: none;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1123
1210
|
.border-gray-100 {
|
|
1124
1211
|
--tw-border-opacity: 1;
|
|
1125
1212
|
border-color: rgb(243 244 246 / var(--tw-border-opacity));
|
|
@@ -1149,6 +1236,11 @@ video {
|
|
|
1149
1236
|
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
|
1150
1237
|
}
|
|
1151
1238
|
|
|
1239
|
+
.bg-blue-600 {
|
|
1240
|
+
--tw-bg-opacity: 1;
|
|
1241
|
+
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1152
1244
|
.bg-forest-green-600 {
|
|
1153
1245
|
--tw-bg-opacity: 1;
|
|
1154
1246
|
background-color: rgb(0 202 44 / var(--tw-bg-opacity));
|
|
@@ -1164,6 +1256,11 @@ video {
|
|
|
1164
1256
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
1165
1257
|
}
|
|
1166
1258
|
|
|
1259
|
+
.bg-gray-300 {
|
|
1260
|
+
--tw-bg-opacity: 1;
|
|
1261
|
+
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1167
1264
|
.bg-gray-400 {
|
|
1168
1265
|
--tw-bg-opacity: 1;
|
|
1169
1266
|
background-color: rgb(156 163 175 / var(--tw-bg-opacity));
|
|
@@ -1189,11 +1286,21 @@ video {
|
|
|
1189
1286
|
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
|
1190
1287
|
}
|
|
1191
1288
|
|
|
1289
|
+
.bg-green-300 {
|
|
1290
|
+
--tw-bg-opacity: 1;
|
|
1291
|
+
background-color: rgb(134 239 172 / var(--tw-bg-opacity));
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1192
1294
|
.bg-green-50 {
|
|
1193
1295
|
--tw-bg-opacity: 1;
|
|
1194
1296
|
background-color: rgb(240 253 244 / var(--tw-bg-opacity));
|
|
1195
1297
|
}
|
|
1196
1298
|
|
|
1299
|
+
.bg-green-500 {
|
|
1300
|
+
--tw-bg-opacity: 1;
|
|
1301
|
+
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1197
1304
|
.bg-green-600 {
|
|
1198
1305
|
--tw-bg-opacity: 1;
|
|
1199
1306
|
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
|
|
@@ -1281,6 +1388,10 @@ video {
|
|
|
1281
1388
|
padding: 0.5rem;
|
|
1282
1389
|
}
|
|
1283
1390
|
|
|
1391
|
+
.p-3 {
|
|
1392
|
+
padding: 0.75rem;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1284
1395
|
.p-4 {
|
|
1285
1396
|
padding: 1rem;
|
|
1286
1397
|
}
|
|
@@ -1398,6 +1509,10 @@ video {
|
|
|
1398
1509
|
padding-top: 0.25rem;
|
|
1399
1510
|
}
|
|
1400
1511
|
|
|
1512
|
+
.pt-\[1px\] {
|
|
1513
|
+
padding-top: 1px;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1401
1516
|
.text-left {
|
|
1402
1517
|
text-align: left;
|
|
1403
1518
|
}
|
|
@@ -1644,6 +1759,12 @@ video {
|
|
|
1644
1759
|
transition-duration: 150ms;
|
|
1645
1760
|
}
|
|
1646
1761
|
|
|
1762
|
+
.transition-colors {
|
|
1763
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
1764
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1765
|
+
transition-duration: 150ms;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1647
1768
|
.placeholder\:text-gray-400::-moz-placeholder {
|
|
1648
1769
|
--tw-text-opacity: 1;
|
|
1649
1770
|
color: rgb(156 163 175 / var(--tw-text-opacity));
|
|
@@ -1679,11 +1800,21 @@ video {
|
|
|
1679
1800
|
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
|
1680
1801
|
}
|
|
1681
1802
|
|
|
1803
|
+
.hover\:bg-blue-700:hover {
|
|
1804
|
+
--tw-bg-opacity: 1;
|
|
1805
|
+
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1682
1808
|
.hover\:bg-forest-green-500:hover {
|
|
1683
1809
|
--tw-bg-opacity: 1;
|
|
1684
1810
|
background-color: rgb(0 242 58 / var(--tw-bg-opacity));
|
|
1685
1811
|
}
|
|
1686
1812
|
|
|
1813
|
+
.hover\:bg-gray-200:hover {
|
|
1814
|
+
--tw-bg-opacity: 1;
|
|
1815
|
+
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1687
1818
|
.hover\:bg-gray-300:hover {
|
|
1688
1819
|
--tw-bg-opacity: 1;
|
|
1689
1820
|
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
|
|
@@ -1704,11 +1835,21 @@ video {
|
|
|
1704
1835
|
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
|
|
1705
1836
|
}
|
|
1706
1837
|
|
|
1838
|
+
.hover\:bg-green-300:hover {
|
|
1839
|
+
--tw-bg-opacity: 1;
|
|
1840
|
+
background-color: rgb(134 239 172 / var(--tw-bg-opacity));
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1707
1843
|
.hover\:bg-green-500:hover {
|
|
1708
1844
|
--tw-bg-opacity: 1;
|
|
1709
1845
|
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
|
|
1710
1846
|
}
|
|
1711
1847
|
|
|
1848
|
+
.hover\:bg-green-600:hover {
|
|
1849
|
+
--tw-bg-opacity: 1;
|
|
1850
|
+
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1712
1853
|
.hover\:bg-red-600:hover {
|
|
1713
1854
|
--tw-bg-opacity: 1;
|
|
1714
1855
|
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
|
@@ -1926,6 +2067,11 @@ video {
|
|
|
1926
2067
|
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
|
|
1927
2068
|
}
|
|
1928
2069
|
|
|
2070
|
+
.disabled\:bg-gray-600:disabled {
|
|
2071
|
+
--tw-bg-opacity: 1;
|
|
2072
|
+
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
|
|
2073
|
+
}
|
|
2074
|
+
|
|
1929
2075
|
.disabled\:text-gray-300:disabled {
|
|
1930
2076
|
--tw-text-opacity: 1;
|
|
1931
2077
|
color: rgb(209 213 219 / var(--tw-text-opacity));
|
package/frontend/src/api.js
CHANGED
|
@@ -46,6 +46,25 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
46
46
|
return client.post('', { action: 'Dashboard.updateDashboard', ...params}).then(res => res.data);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
exports.ChatThread = {
|
|
50
|
+
createChatMessage(params) {
|
|
51
|
+
return client.post('', { action: 'ChatThread.createChatMessage', ...params }).then(res => res.data);
|
|
52
|
+
},
|
|
53
|
+
createChatThread(params) {
|
|
54
|
+
return client.post('', { action: 'ChatThread.createChatThread', ...params }).then(res => res.data);
|
|
55
|
+
},
|
|
56
|
+
getChatThread(params) {
|
|
57
|
+
return client.post('', { action: 'ChatThread.getChatThread', ...params }).then(res => res.data);
|
|
58
|
+
},
|
|
59
|
+
listChatThreads(params) {
|
|
60
|
+
return client.post('', { action: 'ChatThread.listChatThreads', ...params }).then(res => res.data);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.ChatMessage = {
|
|
64
|
+
executeScript(params) {
|
|
65
|
+
return client.post('', { action: 'ChatMessage.executeScript', ...params }).then(res => res.data);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
49
68
|
exports.Model = {
|
|
50
69
|
createChart(params) {
|
|
51
70
|
return client.post('', { action: 'Model.createChart', ...params}).then(res => res.data);
|
|
@@ -117,6 +136,25 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
117
136
|
return client.post('/Dashboard/updateDashboard', params).then(res => res.data);
|
|
118
137
|
}
|
|
119
138
|
}
|
|
139
|
+
exports.ChatThread = {
|
|
140
|
+
createChatMessage: function createChatMessage(params) {
|
|
141
|
+
return client.post('/ChatThread/createChatMessage', params).then(res => res.data);
|
|
142
|
+
},
|
|
143
|
+
createChatThread: function createChatThread(params) {
|
|
144
|
+
return client.post('/ChatThread/createChatThread', params).then(res => res.data);
|
|
145
|
+
},
|
|
146
|
+
getChatThread: function getChatThread(params) {
|
|
147
|
+
return client.post('/ChatThread/getChatThread', params).then(res => res.data);
|
|
148
|
+
},
|
|
149
|
+
listChatThreads: function listChatThreads(params) {
|
|
150
|
+
return client.post('/ChatThread/listChatThreads', params).then(res => res.data);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
exports.ChatMessage = {
|
|
154
|
+
executeScript: function executeScript(params) {
|
|
155
|
+
return client.post('/ChatMessage/executeScript', params).then(res => res.data);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
120
158
|
exports.Model = {
|
|
121
159
|
createChart: function (params) {
|
|
122
160
|
return client.post('/Model/createChart', params).then(res => res.data);
|
|
@@ -170,7 +208,4 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
170
208
|
return client.post('/Model/updateDocument', params).then(res => res.data);
|
|
171
209
|
}
|
|
172
210
|
};
|
|
173
|
-
exports.Script = {
|
|
174
|
-
|
|
175
|
-
};
|
|
176
211
|
}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
<button v-bind="attrsToBind" :disabled="isDisabled" @click="handleClick">
|
|
2
|
-
<
|
|
3
|
-
|
|
2
|
+
<div v-if="status === 'in_progress'" style="text-align: center">
|
|
3
|
+
<svg style="height: 1em" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<g>
|
|
5
|
+
<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2" opacity="0.3" />
|
|
6
|
+
<path d="M12 2a10 10 0 0 1 10 10" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
7
|
+
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite" />
|
|
8
|
+
</path>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
11
|
+
</div>
|
|
12
|
+
<slot v-if="status == 'success' || status == 'init'"></slot>
|
|
13
|
+
</button>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="relative flex items-start space-x-3" :class="{'justify-end': message.role === 'user'}">
|
|
2
|
+
<div
|
|
3
|
+
class="min-w-0 max-w-[calc(100%-6.5rem)]"
|
|
4
|
+
:class="{'text-right': message.role === 'user'}">
|
|
5
|
+
|
|
6
|
+
<div class="text-sm text-gray-900 p-3 rounded-md inline-block" :class="styleForMessage">
|
|
7
|
+
<div v-for="part in contentSplitByScripts">
|
|
8
|
+
<div v-if="part.type === 'text'" v-html="marked(part.content)">
|
|
9
|
+
</div>
|
|
10
|
+
<div v-else-if="part.type === 'code'">
|
|
11
|
+
<chat-message-script :message="message" :script="part.content" :language="part.language"></chat-message-script>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../../api');
|
|
4
|
+
const marked = require('marked').marked;
|
|
5
|
+
const template = require('./chat-message.html');
|
|
6
|
+
|
|
7
|
+
module.exports = app => app.component('chat-message', {
|
|
8
|
+
template: template,
|
|
9
|
+
props: ['message'],
|
|
10
|
+
computed: {
|
|
11
|
+
styleForMessage() {
|
|
12
|
+
return this.message.role === 'user' ? 'bg-gray-100' : '';
|
|
13
|
+
},
|
|
14
|
+
contentSplitByScripts() {
|
|
15
|
+
const content = this.message.content;
|
|
16
|
+
const parts = [];
|
|
17
|
+
let currentIndex = 0;
|
|
18
|
+
let codeBlockMatch;
|
|
19
|
+
|
|
20
|
+
// Regular expression to match markdown code blocks
|
|
21
|
+
const codeBlockRegex = /```(\w*)\n([\s\S]*?)\n```/g;
|
|
22
|
+
|
|
23
|
+
while ((codeBlockMatch = codeBlockRegex.exec(content)) !== null) {
|
|
24
|
+
// Add text before the code block
|
|
25
|
+
if (codeBlockMatch.index > currentIndex) {
|
|
26
|
+
parts.push({
|
|
27
|
+
type: 'text',
|
|
28
|
+
content: content.substring(currentIndex, codeBlockMatch.index)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Add the code block
|
|
33
|
+
parts.push({
|
|
34
|
+
type: 'code',
|
|
35
|
+
language: codeBlockMatch[1] || '',
|
|
36
|
+
content: codeBlockMatch[2]
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
currentIndex = codeBlockMatch.index + codeBlockMatch[0].length;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Add any remaining text after the last code block
|
|
43
|
+
if (currentIndex < content.length) {
|
|
44
|
+
parts.push({
|
|
45
|
+
type: 'text',
|
|
46
|
+
content: content.substring(currentIndex)
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return parts;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
methods: {
|
|
54
|
+
marked(text) {
|
|
55
|
+
return marked(text);
|
|
56
|
+
},
|
|
57
|
+
async executeScript(message, script) {
|
|
58
|
+
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
59
|
+
chatMessageId: message._id,
|
|
60
|
+
script
|
|
61
|
+
});
|
|
62
|
+
message.executionResult = chatMessage.executionResult;
|
|
63
|
+
console.log(message);
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<div class="relative border rounded bg-gray-100 text-black text-sm overflow-hidden">
|
|
2
|
+
<div class="flex border-b pt-[1px] text-xs font-medium bg-gray-200">
|
|
3
|
+
<button
|
|
4
|
+
class="px-3 py-1 border-r border-gray-300 hover:bg-green-300"
|
|
5
|
+
:class="{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}"
|
|
6
|
+
@click="activeTab = 'code'">
|
|
7
|
+
Code
|
|
8
|
+
</button>
|
|
9
|
+
<button
|
|
10
|
+
class="px-3 py-1 hover:bg-green-300"
|
|
11
|
+
:class="{'bg-green-300': activeTab === 'output'}"
|
|
12
|
+
@click="activeTab = 'output'">
|
|
13
|
+
Output
|
|
14
|
+
</button>
|
|
15
|
+
<div class="ml-auto mr-1 flex">
|
|
16
|
+
<button
|
|
17
|
+
v-if="activeTab === 'output'"
|
|
18
|
+
class="px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center"
|
|
19
|
+
@click="openDetailModal">
|
|
20
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
21
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5" />
|
|
22
|
+
</svg>
|
|
23
|
+
</button>
|
|
24
|
+
<async-button
|
|
25
|
+
class="px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400"
|
|
26
|
+
@click="executeScript(message, script)">
|
|
27
|
+
Execute
|
|
28
|
+
</async-button>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<pre class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto" v-show="activeTab === 'code'"><code v-text="script" ref="code" :class="'language-' + language"></code></pre>
|
|
33
|
+
|
|
34
|
+
<pre class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t" v-show="activeTab === 'output'">
|
|
35
|
+
<dashboard-chart v-if="message.executionResult?.output?.$chart" :value="message.executionResult?.output" />
|
|
36
|
+
<div v-else>
|
|
37
|
+
{{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}
|
|
38
|
+
</div>
|
|
39
|
+
</pre>
|
|
40
|
+
|
|
41
|
+
<modal ref="outputModal" v-if="showDetailModal" containerClass="!h-[90vh] !w-[90vw]">
|
|
42
|
+
<template #body>
|
|
43
|
+
<div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showDetailModal = false;">×</div>
|
|
44
|
+
<div class="h-full overflow-auto">
|
|
45
|
+
<dashboard-chart v-if="message.executionResult?.output?.$chart" :value="message.executionResult?.output" />
|
|
46
|
+
<pre v-else class="whitespace-pre-wrap">
|
|
47
|
+
{{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}
|
|
48
|
+
</pre>
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
</modal>
|
|
52
|
+
</div>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../../api');
|
|
4
|
+
const marked = require('marked').marked;
|
|
5
|
+
const template = require('./chat-message-script.html');
|
|
6
|
+
|
|
7
|
+
module.exports = app => app.component('chat-message-script', {
|
|
8
|
+
template: template,
|
|
9
|
+
props: ['message', 'script', 'language'],
|
|
10
|
+
data: () => ({ activeTab: 'code', showDetailModal: false }),
|
|
11
|
+
computed: {
|
|
12
|
+
styleForMessage() {
|
|
13
|
+
return this.message.role === 'user' ? 'bg-gray-100' : '';
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
methods: {
|
|
17
|
+
async executeScript(message, script) {
|
|
18
|
+
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
19
|
+
chatMessageId: message._id,
|
|
20
|
+
script
|
|
21
|
+
});
|
|
22
|
+
message.executionResult = chatMessage.executionResult;
|
|
23
|
+
this.activeTab = 'output';
|
|
24
|
+
},
|
|
25
|
+
openDetailModal() {
|
|
26
|
+
this.showDetailModal = true;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
mounted() {
|
|
30
|
+
Prism.highlightElement(this.$refs.code);
|
|
31
|
+
if (this.message.executionResult?.output) {
|
|
32
|
+
this.activeTab = 'output';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<div class="flex" style="height: calc(100vh - 55px)">
|
|
2
|
+
<!-- Sidebar: Chat Threads -->
|
|
3
|
+
<aside class="w-64 bg-gray-100 border-r overflow-y-auto h-full">
|
|
4
|
+
<div class="p-4 font-bold text-lg border-b">Chat Threads</div>
|
|
5
|
+
<div class="p-4">
|
|
6
|
+
<button
|
|
7
|
+
@click="createNewThread"
|
|
8
|
+
class="w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
|
|
9
|
+
>
|
|
10
|
+
Create New Thread
|
|
11
|
+
</button>
|
|
12
|
+
</div>
|
|
13
|
+
<div v-if="status === 'loaded' && chatThreads.length === 0" class="p-4 text-sm text-gray-700">
|
|
14
|
+
No threads yet
|
|
15
|
+
</div>
|
|
16
|
+
<ul vif="status === 'loaded'">
|
|
17
|
+
<li
|
|
18
|
+
v-for="thread in chatThreads"
|
|
19
|
+
:key="thread._id"
|
|
20
|
+
@click="selectThread(thread._id)"
|
|
21
|
+
class="p-4 hover:bg-gray-200 cursor-pointer"
|
|
22
|
+
:class="{ 'bg-gray-300': thread._id === chatThreadId }"
|
|
23
|
+
>
|
|
24
|
+
{{ thread.title || 'Untitled Thread' }}
|
|
25
|
+
</li>
|
|
26
|
+
</ul>
|
|
27
|
+
</aside>
|
|
28
|
+
|
|
29
|
+
<!-- Main Chat Area -->
|
|
30
|
+
<main class="flex-1 flex flex-col">
|
|
31
|
+
<div class="flex-1 overflow-y-auto p-6 space-y-4" ref="messagesContainer">
|
|
32
|
+
<ul role="list" class="space-y-4">
|
|
33
|
+
<div v-if="true">
|
|
34
|
+
<div class="flex items-center justify-center py-3 mb-4">
|
|
35
|
+
<div class="bg-gray-300 h-px flex-grow max-w-xs"></div>
|
|
36
|
+
<p class="mx-4 text-sm font-medium text-gray-500">This is the beginning of the message thread</p>
|
|
37
|
+
<div class="bg-gray-300 h-px flex-grow max-w-xs"></div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
<li v-for="message in chatMessages" :key="message._id">
|
|
41
|
+
<chat-message :message="message"></chat-message>
|
|
42
|
+
</li>
|
|
43
|
+
</ul>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
<!-- Input Area -->
|
|
48
|
+
<div class="border-t p-4">
|
|
49
|
+
<form @submit.prevent="sendMessage" :disabled="sendingMessage" class="flex gap-2">
|
|
50
|
+
<input
|
|
51
|
+
v-model="newMessage"
|
|
52
|
+
placeholder="Ask something..."
|
|
53
|
+
class="flex-1 border rounded px-4 py-2"
|
|
54
|
+
/>
|
|
55
|
+
<button class="bg-blue-600 text-white px-4 py-2 rounded disabled:bg-gray-600" :disabled="sendingMessage">
|
|
56
|
+
<svg v-if="sendingMessage" style="height: 1em" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
57
|
+
<g>
|
|
58
|
+
<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2" opacity="0.3" />
|
|
59
|
+
<path d="M12 2a10 10 0 0 1 10 10" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
60
|
+
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite" />
|
|
61
|
+
</path>
|
|
62
|
+
</g>
|
|
63
|
+
</svg>
|
|
64
|
+
<span v-else>Send</span>
|
|
65
|
+
</button>
|
|
66
|
+
</form>
|
|
67
|
+
</div>
|
|
68
|
+
</main>
|
|
69
|
+
</div>
|