@mongoosejs/studio 0.2.5 → 0.2.7
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 +2 -1
- package/backend/actions/Model/createChatMessage.js +54 -0
- package/backend/actions/Model/index.js +2 -0
- package/backend/actions/Model/streamChatMessage.js +58 -0
- package/backend/authorize.js +1 -0
- package/backend/helpers/getModelDescriptions.js +8 -0
- package/backend/integrations/callLLM.js +1 -1
- package/backend/integrations/streamLLM.js +1 -1
- package/docs/user_stories.md +13 -0
- package/frontend/public/app.js +20149 -16871
- package/frontend/public/tw.css +95 -0
- package/frontend/src/api.js +60 -0
- package/frontend/src/chat/chat.js +6 -2
- package/frontend/src/create-document/create-document.html +36 -1
- package/frontend/src/create-document/create-document.js +51 -1
- package/frontend/src/detail-default/detail-default.html +15 -2
- package/frontend/src/detail-default/detail-default.js +1066 -2
- package/frontend/src/document-details/document-property/document-property.html +71 -3
- package/frontend/src/document-details/document-property/document-property.js +67 -1
- package/frontend/src/models/models.html +41 -3
- package/frontend/src/models/models.js +252 -3
- package/package.json +3 -2
package/frontend/public/tw.css
CHANGED
|
@@ -594,6 +594,10 @@ video {
|
|
|
594
594
|
pointer-events: none;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
.visible {
|
|
598
|
+
visibility: visible;
|
|
599
|
+
}
|
|
600
|
+
|
|
597
601
|
.invisible {
|
|
598
602
|
visibility: hidden;
|
|
599
603
|
}
|
|
@@ -631,6 +635,10 @@ video {
|
|
|
631
635
|
bottom: 0px;
|
|
632
636
|
}
|
|
633
637
|
|
|
638
|
+
.-left-1 {
|
|
639
|
+
left: -0.25rem;
|
|
640
|
+
}
|
|
641
|
+
|
|
634
642
|
.-left-2 {
|
|
635
643
|
left: -0.5rem;
|
|
636
644
|
}
|
|
@@ -643,6 +651,10 @@ video {
|
|
|
643
651
|
left: 0px;
|
|
644
652
|
}
|
|
645
653
|
|
|
654
|
+
.left-full {
|
|
655
|
+
left: 100%;
|
|
656
|
+
}
|
|
657
|
+
|
|
646
658
|
.right-0 {
|
|
647
659
|
right: 0px;
|
|
648
660
|
}
|
|
@@ -934,6 +946,10 @@ video {
|
|
|
934
946
|
height: 90vh !important;
|
|
935
947
|
}
|
|
936
948
|
|
|
949
|
+
.h-0 {
|
|
950
|
+
height: 0px;
|
|
951
|
+
}
|
|
952
|
+
|
|
937
953
|
.h-10 {
|
|
938
954
|
height: 2.5rem;
|
|
939
955
|
}
|
|
@@ -966,6 +982,10 @@ video {
|
|
|
966
982
|
height: 1.5rem;
|
|
967
983
|
}
|
|
968
984
|
|
|
985
|
+
.h-64 {
|
|
986
|
+
height: 16rem;
|
|
987
|
+
}
|
|
988
|
+
|
|
969
989
|
.h-8 {
|
|
970
990
|
height: 2rem;
|
|
971
991
|
}
|
|
@@ -1018,6 +1038,10 @@ video {
|
|
|
1018
1038
|
min-height: 200px;
|
|
1019
1039
|
}
|
|
1020
1040
|
|
|
1041
|
+
.min-h-\[400px\] {
|
|
1042
|
+
min-height: 400px;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1021
1045
|
.\!w-0 {
|
|
1022
1046
|
width: 0px !important;
|
|
1023
1047
|
}
|
|
@@ -1206,6 +1230,10 @@ video {
|
|
|
1206
1230
|
cursor: auto;
|
|
1207
1231
|
}
|
|
1208
1232
|
|
|
1233
|
+
.cursor-help {
|
|
1234
|
+
cursor: help;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1209
1237
|
.cursor-not-allowed {
|
|
1210
1238
|
cursor: not-allowed;
|
|
1211
1239
|
}
|
|
@@ -1497,6 +1525,10 @@ video {
|
|
|
1497
1525
|
border-bottom-width: 2px;
|
|
1498
1526
|
}
|
|
1499
1527
|
|
|
1528
|
+
.border-b-4 {
|
|
1529
|
+
border-bottom-width: 4px;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1500
1532
|
.border-l-\[3px\] {
|
|
1501
1533
|
border-left-width: 3px;
|
|
1502
1534
|
}
|
|
@@ -1509,10 +1541,18 @@ video {
|
|
|
1509
1541
|
border-right-width: 0px;
|
|
1510
1542
|
}
|
|
1511
1543
|
|
|
1544
|
+
.border-r-4 {
|
|
1545
|
+
border-right-width: 4px;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1512
1548
|
.border-t {
|
|
1513
1549
|
border-top-width: 1px;
|
|
1514
1550
|
}
|
|
1515
1551
|
|
|
1552
|
+
.border-t-4 {
|
|
1553
|
+
border-top-width: 4px;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1516
1556
|
.border-none {
|
|
1517
1557
|
border-style: none;
|
|
1518
1558
|
}
|
|
@@ -1566,6 +1606,11 @@ video {
|
|
|
1566
1606
|
border-left-color: rgb(59 130 246 / var(--tw-border-opacity));
|
|
1567
1607
|
}
|
|
1568
1608
|
|
|
1609
|
+
.border-r-gray-900 {
|
|
1610
|
+
--tw-border-opacity: 1;
|
|
1611
|
+
border-right-color: rgb(17 24 39 / var(--tw-border-opacity));
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1569
1614
|
.\!bg-zinc-50 {
|
|
1570
1615
|
--tw-bg-opacity: 1 !important;
|
|
1571
1616
|
background-color: rgb(250 250 250 / var(--tw-bg-opacity)) !important;
|
|
@@ -1611,6 +1656,11 @@ video {
|
|
|
1611
1656
|
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
|
1612
1657
|
}
|
|
1613
1658
|
|
|
1659
|
+
.bg-emerald-600 {
|
|
1660
|
+
--tw-bg-opacity: 1;
|
|
1661
|
+
background-color: rgb(5 150 105 / var(--tw-bg-opacity));
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1614
1664
|
.bg-forest-green-600 {
|
|
1615
1665
|
--tw-bg-opacity: 1;
|
|
1616
1666
|
background-color: rgb(0 202 44 / var(--tw-bg-opacity));
|
|
@@ -1772,6 +1822,10 @@ video {
|
|
|
1772
1822
|
padding: 0px;
|
|
1773
1823
|
}
|
|
1774
1824
|
|
|
1825
|
+
.p-0\.5 {
|
|
1826
|
+
padding: 0.125rem;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1775
1829
|
.p-1 {
|
|
1776
1830
|
padding: 0.25rem;
|
|
1777
1831
|
}
|
|
@@ -2244,6 +2298,12 @@ video {
|
|
|
2244
2298
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
2245
2299
|
}
|
|
2246
2300
|
|
|
2301
|
+
.shadow-xl {
|
|
2302
|
+
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
2303
|
+
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
|
|
2304
|
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2247
2307
|
.outline-none {
|
|
2248
2308
|
outline: 2px solid transparent;
|
|
2249
2309
|
outline-offset: 2px;
|
|
@@ -2269,6 +2329,12 @@ video {
|
|
|
2269
2329
|
outline-color: #d1d5db;
|
|
2270
2330
|
}
|
|
2271
2331
|
|
|
2332
|
+
.ring {
|
|
2333
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2334
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
2335
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2272
2338
|
.ring-1 {
|
|
2273
2339
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2274
2340
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
@@ -2446,6 +2512,11 @@ video {
|
|
|
2446
2512
|
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
|
|
2447
2513
|
}
|
|
2448
2514
|
|
|
2515
|
+
.hover\:bg-emerald-500:hover {
|
|
2516
|
+
--tw-bg-opacity: 1;
|
|
2517
|
+
background-color: rgb(16 185 129 / var(--tw-bg-opacity));
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2449
2520
|
.hover\:bg-forest-green-500:hover {
|
|
2450
2521
|
--tw-bg-opacity: 1;
|
|
2451
2522
|
background-color: rgb(0 242 58 / var(--tw-bg-opacity));
|
|
@@ -2486,6 +2557,11 @@ video {
|
|
|
2486
2557
|
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
|
|
2487
2558
|
}
|
|
2488
2559
|
|
|
2560
|
+
.hover\:bg-gray-700:hover {
|
|
2561
|
+
--tw-bg-opacity: 1;
|
|
2562
|
+
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2489
2565
|
.hover\:bg-green-100:hover {
|
|
2490
2566
|
--tw-bg-opacity: 1;
|
|
2491
2567
|
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
|
|
@@ -2576,6 +2652,11 @@ video {
|
|
|
2576
2652
|
color: rgb(30 64 175 / var(--tw-text-opacity));
|
|
2577
2653
|
}
|
|
2578
2654
|
|
|
2655
|
+
.hover\:text-gray-600:hover {
|
|
2656
|
+
--tw-text-opacity: 1;
|
|
2657
|
+
color: rgb(75 85 99 / var(--tw-text-opacity));
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2579
2660
|
.hover\:text-gray-700:hover {
|
|
2580
2661
|
--tw-text-opacity: 1;
|
|
2581
2662
|
color: rgb(55 65 81 / var(--tw-text-opacity));
|
|
@@ -2586,6 +2667,11 @@ video {
|
|
|
2586
2667
|
color: rgb(31 41 55 / var(--tw-text-opacity));
|
|
2587
2668
|
}
|
|
2588
2669
|
|
|
2670
|
+
.hover\:text-gray-900:hover {
|
|
2671
|
+
--tw-text-opacity: 1;
|
|
2672
|
+
color: rgb(17 24 39 / var(--tw-text-opacity));
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2589
2675
|
.hover\:text-slate-700:hover {
|
|
2590
2676
|
--tw-text-opacity: 1;
|
|
2591
2677
|
color: rgb(51 65 85 / var(--tw-text-opacity));
|
|
@@ -2620,6 +2706,11 @@ video {
|
|
|
2620
2706
|
border-color: transparent;
|
|
2621
2707
|
}
|
|
2622
2708
|
|
|
2709
|
+
.focus\:border-ultramarine-500:focus {
|
|
2710
|
+
--tw-border-opacity: 1;
|
|
2711
|
+
border-color: rgb(63 83 255 / var(--tw-border-opacity));
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2623
2714
|
.focus\:opacity-100:focus {
|
|
2624
2715
|
opacity: 1;
|
|
2625
2716
|
}
|
|
@@ -2871,6 +2962,10 @@ video {
|
|
|
2871
2962
|
flex: none;
|
|
2872
2963
|
}
|
|
2873
2964
|
|
|
2965
|
+
.sm\:flex-row {
|
|
2966
|
+
flex-direction: row;
|
|
2967
|
+
}
|
|
2968
|
+
|
|
2874
2969
|
.sm\:flex-col {
|
|
2875
2970
|
flex-direction: column;
|
|
2876
2971
|
}
|
package/frontend/src/api.js
CHANGED
|
@@ -147,6 +147,14 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
147
147
|
updateDocument: function updateDocument(params) {
|
|
148
148
|
return client.post('', { action: 'Model.updateDocument', ...params }).then(res => res.data);
|
|
149
149
|
},
|
|
150
|
+
createChatMessage(params) {
|
|
151
|
+
return client.post('', { action: 'Model.createChatMessage', ...params }).then(res => res.data);
|
|
152
|
+
},
|
|
153
|
+
streamChatMessage: async function* streamChatMessage(params) {
|
|
154
|
+
// Don't stream on Next.js or Netlify for now.
|
|
155
|
+
const data = await client.post('', { action: 'Model.createChatMessage', ...params }).then(res => res.data);
|
|
156
|
+
yield { textPart: data.text };
|
|
157
|
+
},
|
|
150
158
|
updateDocuments: function updateDocuments(params) {
|
|
151
159
|
return client.post('', { action: 'Model.updateDocuments', ...params }).then(res => res.data);
|
|
152
160
|
}
|
|
@@ -250,6 +258,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
250
258
|
createChart: function(params) {
|
|
251
259
|
return client.post('/Model/createChart', params).then(res => res.data);
|
|
252
260
|
},
|
|
261
|
+
createChatMessage: function(params) {
|
|
262
|
+
return client.post('/Model/createChatMessage', params).then(res => res.data);
|
|
263
|
+
},
|
|
253
264
|
createDocument: function(params) {
|
|
254
265
|
return client.post('/Model/createDocument', params).then(res => res.data);
|
|
255
266
|
},
|
|
@@ -356,6 +367,55 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
356
367
|
updateDocument: function updateDocument(params) {
|
|
357
368
|
return client.post('/Model/updateDocument', params).then(res => res.data);
|
|
358
369
|
},
|
|
370
|
+
streamChatMessage: async function* streamChatMessage(params) {
|
|
371
|
+
const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
|
|
372
|
+
const url = window.MONGOOSE_STUDIO_CONFIG.baseURL + '/Model/streamChatMessage?' + new URLSearchParams(params).toString();
|
|
373
|
+
|
|
374
|
+
const response = await fetch(url, {
|
|
375
|
+
method: 'GET',
|
|
376
|
+
headers: {
|
|
377
|
+
Authorization: `${accessToken}`,
|
|
378
|
+
Accept: 'text/event-stream'
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
if (!response.ok) {
|
|
383
|
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const reader = response.body.getReader();
|
|
387
|
+
const decoder = new TextDecoder('utf-8');
|
|
388
|
+
let buffer = '';
|
|
389
|
+
|
|
390
|
+
while (true) {
|
|
391
|
+
const { done, value } = await reader.read();
|
|
392
|
+
if (done) break;
|
|
393
|
+
buffer += decoder.decode(value, { stream: true });
|
|
394
|
+
|
|
395
|
+
let eventEnd;
|
|
396
|
+
while ((eventEnd = buffer.indexOf('\n\n')) !== -1) {
|
|
397
|
+
const eventStr = buffer.slice(0, eventEnd);
|
|
398
|
+
buffer = buffer.slice(eventEnd + 2);
|
|
399
|
+
|
|
400
|
+
// Parse SSE event
|
|
401
|
+
const lines = eventStr.split('\n');
|
|
402
|
+
let data = '';
|
|
403
|
+
for (const line of lines) {
|
|
404
|
+
if (line.startsWith('data:')) {
|
|
405
|
+
data += line.slice(5).trim();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (data) {
|
|
409
|
+
try {
|
|
410
|
+
yield JSON.parse(data);
|
|
411
|
+
} catch (err) {
|
|
412
|
+
// If not JSON, yield as string
|
|
413
|
+
yield data;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
},
|
|
359
419
|
updateDocuments: function updateDocument(params) {
|
|
360
420
|
return client.post('/Model/updateDocuments', params).then(res => res.data);
|
|
361
421
|
}
|
|
@@ -30,7 +30,9 @@ module.exports = {
|
|
|
30
30
|
this.$toast.success('Chat thread created!');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const userChatMessageIndex = this.chatMessages.length;
|
|
33
34
|
this.chatMessages.push({
|
|
35
|
+
_id: Math.random().toString(36).substr(2, 9),
|
|
34
36
|
content,
|
|
35
37
|
role: 'user'
|
|
36
38
|
});
|
|
@@ -48,11 +50,12 @@ module.exports = {
|
|
|
48
50
|
if (event.chatMessage) {
|
|
49
51
|
if (!userChatMessage) {
|
|
50
52
|
userChatMessage = event.chatMessage;
|
|
51
|
-
|
|
53
|
+
this.chatMessages.splice(userChatMessageIndex, 1, userChatMessage);
|
|
54
|
+
} else {
|
|
52
55
|
const assistantChatMessageIndex = this.chatMessages.indexOf(assistantChatMessage);
|
|
53
56
|
assistantChatMessage = event.chatMessage;
|
|
54
57
|
if (assistantChatMessageIndex !== -1) {
|
|
55
|
-
this.chatMessages
|
|
58
|
+
this.chatMessages.splice(assistantChatMessageIndex, 1, assistantChatMessage);
|
|
56
59
|
} else {
|
|
57
60
|
this.chatMessages.push(assistantChatMessage);
|
|
58
61
|
}
|
|
@@ -66,6 +69,7 @@ module.exports = {
|
|
|
66
69
|
} else if (event.textPart) {
|
|
67
70
|
if (!assistantChatMessage) {
|
|
68
71
|
assistantChatMessage = {
|
|
72
|
+
_id: Math.random().toString(36).substr(2, 9),
|
|
69
73
|
content: event.textPart,
|
|
70
74
|
role: 'assistant'
|
|
71
75
|
};
|
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
<div>
|
|
2
|
+
<div class="mb-4">
|
|
3
|
+
<label class="block text-sm font-bold text-gray-900">AI Mode</label>
|
|
4
|
+
<div class="mt-2 flex flex-col gap-2 sm:flex-row sm:items-center">
|
|
5
|
+
<input
|
|
6
|
+
v-model="aiPrompt"
|
|
7
|
+
type="text"
|
|
8
|
+
placeholder="Describe the document you'd like to create..."
|
|
9
|
+
@keydown.enter.prevent="requestAiSuggestion()"
|
|
10
|
+
class="w-full rounded-md border border-gray-300 px-3 py-2 text-sm shadow-sm focus:border-ultramarine-500 focus:outline-none focus:ring-1 focus:ring-ultramarine-500"
|
|
11
|
+
/>
|
|
12
|
+
<button
|
|
13
|
+
@click="requestAiSuggestion()"
|
|
14
|
+
:disabled="aiStreaming || !aiPrompt.trim()"
|
|
15
|
+
class="inline-flex items-center justify-center rounded-md bg-ultramarine-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 disabled:cursor-not-allowed disabled:opacity-50"
|
|
16
|
+
>
|
|
17
|
+
{{ aiStreaming ? 'Generating...' : 'Generate' }}
|
|
18
|
+
</button>
|
|
19
|
+
</div>
|
|
20
|
+
<p class="mt-2 text-xs text-gray-500">Use AI to draft the document. You can accept or reject the suggestion once it finishes.</p>
|
|
21
|
+
<div v-if="aiSuggestionReady" class="mt-3 flex flex-wrap gap-2">
|
|
22
|
+
<button
|
|
23
|
+
@click="acceptAiSuggestion()"
|
|
24
|
+
class="rounded-md bg-emerald-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-emerald-500"
|
|
25
|
+
>
|
|
26
|
+
Accept suggestion
|
|
27
|
+
</button>
|
|
28
|
+
<button
|
|
29
|
+
@click="rejectAiSuggestion()"
|
|
30
|
+
class="rounded-md bg-gray-100 px-2.5 py-1.5 text-sm font-semibold text-gray-700 shadow-sm hover:bg-gray-200"
|
|
31
|
+
>
|
|
32
|
+
Reject suggestion
|
|
33
|
+
</button>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
2
36
|
<div class="mb-2">
|
|
3
|
-
<
|
|
37
|
+
<label class="block text-sm font-bold text-gray-900">Document to Create</label>
|
|
38
|
+
<textarea class="border border-gray-200 p-2 h-[300px] w-full mt-2" ref="codeEditor"></textarea>
|
|
4
39
|
</div>
|
|
5
40
|
<button @click="createDocument()" class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Submit</button>
|
|
6
41
|
<div v-if="errors.length > 0" class="rounded-md bg-red-50 p-4 mt-1">
|
|
@@ -23,10 +23,60 @@ module.exports = app => app.component('create-document', {
|
|
|
23
23
|
return {
|
|
24
24
|
documentData: '',
|
|
25
25
|
editor: null,
|
|
26
|
-
errors: []
|
|
26
|
+
errors: [],
|
|
27
|
+
aiPrompt: '',
|
|
28
|
+
aiSuggestion: '',
|
|
29
|
+
aiOriginalDocument: '',
|
|
30
|
+
aiStreaming: false,
|
|
31
|
+
aiSuggestionReady: false
|
|
27
32
|
};
|
|
28
33
|
},
|
|
29
34
|
methods: {
|
|
35
|
+
async requestAiSuggestion() {
|
|
36
|
+
if (this.aiStreaming) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const prompt = this.aiPrompt.trim();
|
|
40
|
+
if (!prompt) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.aiOriginalDocument = this.editor.getValue();
|
|
45
|
+
this.aiSuggestion = '';
|
|
46
|
+
this.aiSuggestionReady = false;
|
|
47
|
+
this.aiStreaming = true;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
for await (const event of api.Model.streamChatMessage({
|
|
51
|
+
model: this.currentModel,
|
|
52
|
+
content: prompt,
|
|
53
|
+
documentData: this.aiOriginalDocument
|
|
54
|
+
})) {
|
|
55
|
+
if (event?.textPart) {
|
|
56
|
+
this.aiSuggestion += event.textPart;
|
|
57
|
+
this.editor.setValue(this.aiSuggestion);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
this.aiSuggestionReady = true;
|
|
61
|
+
} catch (err) {
|
|
62
|
+
this.editor.setValue(this.aiOriginalDocument);
|
|
63
|
+
this.$toast.error('Failed to generate a document suggestion.');
|
|
64
|
+
throw err;
|
|
65
|
+
} finally {
|
|
66
|
+
this.aiStreaming = false;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
acceptAiSuggestion() {
|
|
70
|
+
this.aiSuggestionReady = false;
|
|
71
|
+
this.aiSuggestion = '';
|
|
72
|
+
this.aiOriginalDocument = '';
|
|
73
|
+
},
|
|
74
|
+
rejectAiSuggestion() {
|
|
75
|
+
this.editor.setValue(this.aiOriginalDocument);
|
|
76
|
+
this.aiSuggestionReady = false;
|
|
77
|
+
this.aiSuggestion = '';
|
|
78
|
+
this.aiOriginalDocument = '';
|
|
79
|
+
},
|
|
30
80
|
async createDocument() {
|
|
31
81
|
const data = EJSON.serialize(eval(`(${this.editor.getValue()})`));
|
|
32
82
|
try {
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
<div class="w-full">
|
|
2
|
-
<pre class="w-full whitespace-pre-wrap break-words font-mono text-sm text-gray-700 m-0">{{displayValue}}</pre>
|
|
3
|
-
|
|
2
|
+
<pre v-if="!isGeoJsonGeometry || !mapVisible" class="w-full whitespace-pre-wrap break-words font-mono text-sm text-gray-700 m-0">{{displayValue}}</pre>
|
|
3
|
+
<div v-show="isGeoJsonGeometry && mapVisible" class="mt-2 border border-gray-200 rounded relative">
|
|
4
|
+
<div ref="map" class="h-64 w-full" style="min-height: 256px; height: 256px;"></div>
|
|
5
|
+
<!-- Undo button below map -->
|
|
6
|
+
<div v-if="isEditable && canUndo" class="mt-2 flex justify-end">
|
|
7
|
+
<button
|
|
8
|
+
@click="undoDelete"
|
|
9
|
+
class="text-xs px-3 py-1.5 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
|
|
10
|
+
title="Undo all changes"
|
|
11
|
+
>
|
|
12
|
+
Undo
|
|
13
|
+
</button>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|