@mongoosejs/studio 0.0.75 → 0.0.76
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/ChatThread/createChatMessage.js +8 -133
- package/backend/helpers/getModelDescriptions.js +18 -0
- package/backend/index.js +3 -0
- package/frontend/public/app.js +4 -3
- package/frontend/src/chat/chat-message-script/chat-message-script.html +1 -3
- package/frontend/src/chat/chat.html +2 -2
- package/frontend/src/chat/chat.js +2 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Archetype = require('archetype');
|
|
4
|
+
const getModelDescriptions = require('../../helpers/getModelDescriptions');
|
|
4
5
|
const mongoose = require('mongoose');
|
|
5
6
|
|
|
6
7
|
const CreateChatMessageParams = new Archetype({
|
|
@@ -18,17 +19,21 @@ const CreateChatMessageParams = new Archetype({
|
|
|
18
19
|
const systemPrompt = `
|
|
19
20
|
You are a data querying assistant who writes scripts for users accessing MongoDB data using Node.js and Mongoose.
|
|
20
21
|
|
|
21
|
-
Keep scripts concise. Avoid unnecessary comments
|
|
22
|
+
Keep scripts concise. Avoid unnecessary comments, error handling, and temporary variables.
|
|
23
|
+
|
|
24
|
+
Do not write any imports or require() statements, that will cause the script to break.
|
|
22
25
|
|
|
23
26
|
Assume the user has pre-defined schemas and models. Do not define any new schemas or models for the user.
|
|
24
27
|
|
|
25
28
|
Use async/await where possible. Assume top-level await is allowed.
|
|
26
29
|
|
|
30
|
+
Think carefully about the user's input and identify the models referred to by the user's query.
|
|
31
|
+
|
|
27
32
|
Format output as Markdown, including code fences for any scripts the user requested.
|
|
28
33
|
|
|
29
34
|
Add a brief text description of what the script does.
|
|
30
35
|
|
|
31
|
-
If the user's query is best answered with a chart, return a Chart.js 4 configuration as \`return { $chart: chartJSConfig }
|
|
36
|
+
If the user's query is best answered with a chart, return a Chart.js 4 configuration as \`return { $chart: chartJSConfig };\`. Disable ChartJS animation by default unless user asks for it.
|
|
32
37
|
|
|
33
38
|
Example output:
|
|
34
39
|
|
|
@@ -42,136 +47,6 @@ return { numUsers: users.length };
|
|
|
42
47
|
-----------
|
|
43
48
|
|
|
44
49
|
Here is a description of the user's models. Assume these are the only models available in the system unless explicitly instructed otherwise by the user.
|
|
45
|
-
|
|
46
|
-
Vehicle (collection name: Vehicle)
|
|
47
|
-
- _id: ObjectId
|
|
48
|
-
- userId: ObjectId (ref User)
|
|
49
|
-
- authorizedUsers: Array
|
|
50
|
-
- status: String
|
|
51
|
-
- _previousStatus: String
|
|
52
|
-
- make: String
|
|
53
|
-
- model: String
|
|
54
|
-
- year: Number
|
|
55
|
-
- color: String
|
|
56
|
-
- nickName: String
|
|
57
|
-
- tollTagId: String
|
|
58
|
-
- availabilityDate: String
|
|
59
|
-
- vehicleFeatures: Array
|
|
60
|
-
- vehicleIdentityId: ObjectId (ref VehicleIdentity)
|
|
61
|
-
- images: Object
|
|
62
|
-
- thumbnail: String
|
|
63
|
-
- photos: Array
|
|
64
|
-
- registrationPhoto: String
|
|
65
|
-
- smartcarId: String
|
|
66
|
-
- smartcarPermissions: Array
|
|
67
|
-
- percentRemaining: Number
|
|
68
|
-
- range: Number
|
|
69
|
-
- location: Object
|
|
70
|
-
- locationTimestamp: Date
|
|
71
|
-
- pricePerMonth: Number
|
|
72
|
-
- pricePerWeek: Number
|
|
73
|
-
- returnAddress: String
|
|
74
|
-
- returnLocation: Object
|
|
75
|
-
- description: String
|
|
76
|
-
- maxUnlockRadiusMiles: Number
|
|
77
|
-
- returnRadiusKM: Number
|
|
78
|
-
- numReviews: Number
|
|
79
|
-
- numCompletedTrips: Number
|
|
80
|
-
- totalReviewScore: Number
|
|
81
|
-
- totalRevenueGenerated: Number
|
|
82
|
-
- bookingsCount: Number
|
|
83
|
-
- odometer: Number
|
|
84
|
-
- pickupInstructions: String
|
|
85
|
-
- returnInstructions: String
|
|
86
|
-
- unlockInstructions: String
|
|
87
|
-
- chargingState: String
|
|
88
|
-
- isPluggedIn: Boolean
|
|
89
|
-
- currentBookingId: ObjectId (ref Booking)
|
|
90
|
-
- maxTripLengthDays: Number
|
|
91
|
-
- smartcarWebhookIds: Array
|
|
92
|
-
- lastErrorMessage: String
|
|
93
|
-
- vinNumber: String
|
|
94
|
-
- licensePlate: String
|
|
95
|
-
- licensePlateState: String
|
|
96
|
-
- registrationExpirationDate: String
|
|
97
|
-
- style: Object
|
|
98
|
-
- driveUnit: Object
|
|
99
|
-
- efficiencyPackage: String
|
|
100
|
-
- performancePackage: String
|
|
101
|
-
- connectivityProvider: String
|
|
102
|
-
- abiId: String
|
|
103
|
-
- platformFeePercentage: Number
|
|
104
|
-
- promotionsEnabled: Boolean
|
|
105
|
-
- modelDescription: String
|
|
106
|
-
- isConcierge: Boolean
|
|
107
|
-
- lastLoadedSuperchargerInvoicesAt: Date
|
|
108
|
-
- privateBookingNotes: String
|
|
109
|
-
- publicMarketingNotes: String
|
|
110
|
-
- fleetKeyState: Object
|
|
111
|
-
- weakBattery: Boolean
|
|
112
|
-
- fleetITconnectionStartDate: Date
|
|
113
|
-
- fleetITId: Number
|
|
114
|
-
- interiorTrim: String
|
|
115
|
-
- skipLoadingSuperchargerInvoices: Boolean
|
|
116
|
-
- chargeKey: Object
|
|
117
|
-
- securityDepositPerUser: Array
|
|
118
|
-
|
|
119
|
-
User (collection name User)
|
|
120
|
-
- _id: ObjectId
|
|
121
|
-
- firstName: String
|
|
122
|
-
- lastName: String
|
|
123
|
-
- email: String (required, lowercase)
|
|
124
|
-
- picture: String
|
|
125
|
-
- zipCode: String
|
|
126
|
-
- telephone: String
|
|
127
|
-
- verifiedTelephone: Boolean
|
|
128
|
-
- verifiedEmail: Boolean
|
|
129
|
-
- googleUserId: String
|
|
130
|
-
- appleUserId: String
|
|
131
|
-
- smartcarUserId: String
|
|
132
|
-
- stripeCustomerId: String
|
|
133
|
-
- roles: Array of String (enum: 'root', 'admin', 'manager', 'host', 'verified-driver', 'internal-tester', 'authorized-payer')
|
|
134
|
-
- accountPreference: String (enum: 'host', 'guest', 'both')
|
|
135
|
-
- defaultPaymentMethodId: ObjectId (ref PaymentMethod)
|
|
136
|
-
- personaInquiryId: String
|
|
137
|
-
- personaAccountId: String
|
|
138
|
-
- personaInquiryStatus: String (enum: 'created', 'approved', 'declined')
|
|
139
|
-
- personaHasDriverLicense: Boolean
|
|
140
|
-
- driverLicenseState: String
|
|
141
|
-
- numReviews: Number
|
|
142
|
-
- totalReviewScore: Number
|
|
143
|
-
- needsSmartcarReconnect: Boolean
|
|
144
|
-
- isFrozen: Boolean
|
|
145
|
-
- instantTransactions: Boolean
|
|
146
|
-
- publicNotes: String
|
|
147
|
-
- bookingNotes: String
|
|
148
|
-
- hostOnboarding: Object
|
|
149
|
-
- guestOnboarding: Object
|
|
150
|
-
- canUseApp: Boolean
|
|
151
|
-
- useWalletForChargeReceipt: Boolean
|
|
152
|
-
- appOnboardingToken: Object
|
|
153
|
-
- addedToLaunchlist: Boolean
|
|
154
|
-
- stripeAccountId: String
|
|
155
|
-
- isStripeConnectedAccountConfirmed: Boolean
|
|
156
|
-
- requestedAccountDeletion: Boolean
|
|
157
|
-
- qrcodeUrl: String
|
|
158
|
-
- checkrCandidateId: String
|
|
159
|
-
- checkrInvitationId: String
|
|
160
|
-
- checkrInvitationUrl: String
|
|
161
|
-
- checkrInvitationStatus: String
|
|
162
|
-
- referralCode: String
|
|
163
|
-
- referralUrl: String
|
|
164
|
-
- referralConversionId: ObjectId (ref ReferralConversion)
|
|
165
|
-
- abiOwnerId: String
|
|
166
|
-
- abiRenterId: String
|
|
167
|
-
- driverLicense: Object
|
|
168
|
-
- securityDeposit: Number
|
|
169
|
-
- tripcityOwnerId: String
|
|
170
|
-
- bannedUserId: ObjectId (ref BannedUser)
|
|
171
|
-
- isConcierge: Boolean
|
|
172
|
-
- lastHostDashboardLoginAt: Date
|
|
173
|
-
- internalSlackChannel: String
|
|
174
|
-
- skipLoadingSuperchargerInvoices: Boolean
|
|
175
50
|
`.trim();
|
|
176
51
|
|
|
177
52
|
module.exports = ({ db }) => async function createChatMessage(params) {
|
|
@@ -208,7 +83,7 @@ module.exports = ({ db }) => async function createChatMessage(params) {
|
|
|
208
83
|
|
|
209
84
|
llmMessages.unshift({
|
|
210
85
|
role: 'system',
|
|
211
|
-
content: systemPrompt
|
|
86
|
+
content: systemPrompt + getModelDescriptions(db)
|
|
212
87
|
});
|
|
213
88
|
|
|
214
89
|
// Create the chat message and get OpenAI response in parallel
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const listModelPaths = Model => [
|
|
4
|
+
...Object.entries(Model.schema.paths).map(
|
|
5
|
+
([path, schemaType]) => `- ${path}: ${schemaType.instance}`
|
|
6
|
+
+ (schemaType.options?.ref ? ' (ref: ' + schemaType.options.ref + ')' : '')
|
|
7
|
+
),
|
|
8
|
+
...Object.entries(Model.schema.virtuals).filter(([path, virtual]) => virtual.options?.ref).map(
|
|
9
|
+
([path, virtual]) => `- ${path}: Virtual (ref: ${virtual.options.ref})`
|
|
10
|
+
)
|
|
11
|
+
].join('\n');
|
|
12
|
+
|
|
13
|
+
const getModelDescriptions = db => Object.values(db.models).filter(Model => !Model.modelName.startsWith('__Studio')).map(Model => `
|
|
14
|
+
${Model.modelName} (collection: ${Model.collection.collectionName})
|
|
15
|
+
${listModelPaths(Model)}
|
|
16
|
+
`.trim()).join('\n\n');
|
|
17
|
+
|
|
18
|
+
module.exports = getModelDescriptions;
|
package/backend/index.js
CHANGED
|
@@ -8,12 +8,15 @@ const chatMessageSchema = require('./db/chatMessageSchema');
|
|
|
8
8
|
const chatThreadSchema = require('./db/chatThreadSchema');
|
|
9
9
|
const dashboardSchema = require('./db/dashboardSchema');
|
|
10
10
|
|
|
11
|
+
const getModelDescriptions = require('./helpers/getModelDescriptions');
|
|
12
|
+
|
|
11
13
|
module.exports = function backend(db) {
|
|
12
14
|
db = db || mongoose.connection;
|
|
13
15
|
|
|
14
16
|
const Dashboard = db.model('__Studio_Dashboard', dashboardSchema, 'studio__dashboards');
|
|
15
17
|
const ChatMessage = db.model('__Studio_ChatMessage', chatMessageSchema, 'studio__chatMessages');
|
|
16
18
|
const ChatThread = db.model('__Studio_ChatThread', chatThreadSchema, 'studio__chatThreads');
|
|
19
|
+
|
|
17
20
|
const actions = applySpec(Actions, { db });
|
|
18
21
|
return actions;
|
|
19
22
|
};
|
package/frontend/public/app.js
CHANGED
|
@@ -485,7 +485,8 @@ module.exports = app => app.component('chat', {
|
|
|
485
485
|
return message.role === 'user' ? 'bg-gray-100' : '';
|
|
486
486
|
},
|
|
487
487
|
async createNewThread() {
|
|
488
|
-
|
|
488
|
+
const { chatThread } = await api.ChatThread.createChatThread();
|
|
489
|
+
this.$router.push('/chat/' + chatThread._id);
|
|
489
490
|
}
|
|
490
491
|
},
|
|
491
492
|
async mounted() {
|
|
@@ -3678,7 +3679,7 @@ module.exports = "<button v-bind=\"attrsToBind\" :disabled=\"isDisabled\" @click
|
|
|
3678
3679
|
/***/ ((module) => {
|
|
3679
3680
|
|
|
3680
3681
|
"use strict";
|
|
3681
|
-
module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n 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\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <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\" />\n </svg>\n </button>\n <async-button\n 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\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <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>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <div v-else
|
|
3682
|
+
module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n 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\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <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\" />\n </svg>\n </button>\n <async-button\n 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\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <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>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <div v-else>{{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}</div>\n </pre>\n\n <modal ref=\"outputModal\" v-if=\"showDetailModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\">×</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else class=\"whitespace-pre-wrap\">\n {{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}\n </pre>\n </div>\n </template>\n </modal>\n</div>\n";
|
|
3682
3683
|
|
|
3683
3684
|
/***/ }),
|
|
3684
3685
|
|
|
@@ -3700,7 +3701,7 @@ module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'
|
|
|
3700
3701
|
/***/ ((module) => {
|
|
3701
3702
|
|
|
3702
3703
|
"use strict";
|
|
3703
|
-
module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <!-- Sidebar: Chat Threads -->\n <aside class=\"w-64 bg-gray-100 border-r overflow-y-auto h-full\">\n <div class=\"p-4 font-bold text-lg border-b\">Chat Threads</div>\n <div class=\"p-4\">\n <button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul vif=\"status === 'loaded'\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2\">\n <input\n v-model=\"newMessage\"\n placeholder=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2\"\n />\n <button class=\"bg-blue-600 text-white px-4 py-2 rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n</div>\n";
|
|
3704
|
+
module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <!-- Sidebar: Chat Threads -->\n <aside class=\"w-64 bg-gray-100 border-r overflow-y-auto h-full\">\n <div class=\"p-4 font-bold text-lg border-b\">Chat Threads</div>\n <div class=\"p-4\">\n <async-button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </async-button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul vif=\"status === 'loaded'\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2\">\n <input\n v-model=\"newMessage\"\n placeholder=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2\"\n />\n <button class=\"bg-blue-600 text-white px-4 py-2 rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n</div>\n";
|
|
3704
3705
|
|
|
3705
3706
|
/***/ }),
|
|
3706
3707
|
|
|
@@ -33,9 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
<pre class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t" v-show="activeTab === 'output'">
|
|
35
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>
|
|
36
|
+
<div v-else>{{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}</div>
|
|
39
37
|
</pre>
|
|
40
38
|
|
|
41
39
|
<modal ref="outputModal" v-if="showDetailModal" containerClass="!h-[90vh] !w-[90vw]">
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
<aside class="w-64 bg-gray-100 border-r overflow-y-auto h-full">
|
|
4
4
|
<div class="p-4 font-bold text-lg border-b">Chat Threads</div>
|
|
5
5
|
<div class="p-4">
|
|
6
|
-
<button
|
|
6
|
+
<async-button
|
|
7
7
|
@click="createNewThread"
|
|
8
8
|
class="w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
|
|
9
9
|
>
|
|
10
10
|
Create New Thread
|
|
11
|
-
</button>
|
|
11
|
+
</async-button>
|
|
12
12
|
</div>
|
|
13
13
|
<div v-if="status === 'loaded' && chatThreads.length === 0" class="p-4 text-sm text-gray-700">
|
|
14
14
|
No threads yet
|
|
@@ -60,7 +60,8 @@ module.exports = app => app.component('chat', {
|
|
|
60
60
|
return message.role === 'user' ? 'bg-gray-100' : '';
|
|
61
61
|
},
|
|
62
62
|
async createNewThread() {
|
|
63
|
-
|
|
63
|
+
const { chatThread } = await api.ChatThread.createChatThread();
|
|
64
|
+
this.$router.push('/chat/' + chatThread._id);
|
|
64
65
|
}
|
|
65
66
|
},
|
|
66
67
|
async mounted() {
|