@mongoosejs/studio 0.5.2 → 0.5.4
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/streamChatMessage.js +12 -12
- package/backend/chatAgent/agentSystemPrompt.js +22 -10
- package/backend/chatAgent/getAgentTools.js +19 -8
- package/backend/chatAgent/runChatAgent.js +17 -0
- package/backend/index.js +3 -0
- package/debugging.js +11 -0
- package/eval/agent/cases.js +168 -0
- package/eval/agent/fixtures/carsharing.js +147 -0
- package/eval/agent/fixtures/ecommerce.js +152 -0
- package/eval/agent/run.js +323 -0
- package/frontend/index.js +1 -2
- package/frontend/public/app.js +395 -23
- package/frontend/public/tw.css +52 -0
- package/frontend/src/_util/recent-pages-history.js +116 -0
- package/frontend/src/chat/chat-message-script/chat-message-script.html +1 -6
- package/frontend/src/chat/chat.js +2 -2
- package/frontend/src/document/document.html +2 -2
- package/frontend/src/index.js +188 -10
- package/frontend/src/modal/modal.css +26 -1
- package/frontend/src/modal/modal.html +2 -2
- package/frontend/src/modal/modal.js +5 -1
- package/frontend/src/navbar/navbar.html +77 -6
- package/frontend/src/navbar/navbar.js +65 -4
- package/index.js +2 -1
- package/package.json +3 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<div>
|
|
1
2
|
<div class="navbar w-full bg-page border-b border-edge !h-[55px] hidden md:grid grid-cols-[1fr_auto_1fr] items-stretch px-4">
|
|
2
3
|
<!-- Left: Logo + Brand -->
|
|
3
4
|
<div class="flex items-center gap-2 self-center">
|
|
@@ -31,11 +32,11 @@
|
|
|
31
32
|
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
32
33
|
</svg>
|
|
33
34
|
</span>
|
|
34
|
-
<a v-if="hasAccess(roles, 'chat') &&
|
|
35
|
+
<a v-if="hasAccess(roles, 'chat') && supportsAI"
|
|
35
36
|
href="#/chat"
|
|
36
37
|
class="inline-flex items-center px-1 border-b-2 text-sm font-medium"
|
|
37
38
|
:class="chatView ? 'text-content border-primary' : 'border-transparent text-content-tertiary hover:text-content'">Chat</a>
|
|
38
|
-
<span v-else-if="hasAccess(roles, 'chat') && !
|
|
39
|
+
<span v-else-if="hasAccess(roles, 'chat') && !supportsAI"
|
|
39
40
|
class="inline-flex items-center px-1 border-b-2 border-transparent text-sm font-medium text-gray-300 cursor-not-allowed"
|
|
40
41
|
:title="chatDisabledReason">
|
|
41
42
|
Chat
|
|
@@ -67,6 +68,19 @@
|
|
|
67
68
|
</nav>
|
|
68
69
|
<!-- Right: Env Badge + User -->
|
|
69
70
|
<div class="flex items-center justify-end gap-3 self-center">
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
class="inline-flex items-center justify-center rounded-md p-2 text-content-tertiary hover:bg-muted hover:text-content-secondary"
|
|
74
|
+
title="Recent pages"
|
|
75
|
+
aria-label="Recent pages"
|
|
76
|
+
aria-haspopup="dialog"
|
|
77
|
+
:aria-expanded="showRecentPagesModal ? 'true' : 'false'"
|
|
78
|
+
@click="openRecentPagesModal"
|
|
79
|
+
>
|
|
80
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-5 w-5" aria-hidden="true">
|
|
81
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
82
|
+
</svg>
|
|
83
|
+
</button>
|
|
70
84
|
<div
|
|
71
85
|
v-if="!!state.nodeEnv"
|
|
72
86
|
title="NODE_ENV"
|
|
@@ -149,9 +163,22 @@
|
|
|
149
163
|
<span class="text-base font-semibold text-content">Mongoose Studio</span>
|
|
150
164
|
</router-link>
|
|
151
165
|
</div>
|
|
152
|
-
<div class="flex items-center">
|
|
166
|
+
<div class="flex items-center gap-1 pr-2">
|
|
167
|
+
<button
|
|
168
|
+
type="button"
|
|
169
|
+
class="rounded-md p-2 text-content-tertiary hover:bg-muted hover:text-content-secondary md:hidden"
|
|
170
|
+
title="Recent pages"
|
|
171
|
+
aria-label="Recent pages"
|
|
172
|
+
aria-haspopup="dialog"
|
|
173
|
+
:aria-expanded="showRecentPagesModal ? 'true' : 'false'"
|
|
174
|
+
@click="openRecentPagesModal"
|
|
175
|
+
>
|
|
176
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-6 w-6" aria-hidden="true">
|
|
177
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
178
|
+
</svg>
|
|
179
|
+
</button>
|
|
153
180
|
<!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->
|
|
154
|
-
<button type="button" id="open-mobile-menu" class="-ml-2 rounded-md p-2
|
|
181
|
+
<button type="button" id="open-mobile-menu" class="-ml-2 rounded-md p-2 text-gray-400">
|
|
155
182
|
<span class="sr-only">Open menu</span>
|
|
156
183
|
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
|
157
184
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
|
@@ -209,11 +236,11 @@
|
|
|
209
236
|
<path fill-rule="evenodd" d="M10 2a4 4 0 00-4 4v2H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-1V6a4 4 0 00-4-4zm-3 6V6a3 3 0 116 0v2H7z" clip-rule="evenodd" />
|
|
210
237
|
</svg>
|
|
211
238
|
</span>
|
|
212
|
-
<a v-if="hasAccess(roles, 'chat') &&
|
|
239
|
+
<a v-if="hasAccess(roles, 'chat') && supportsAI"
|
|
213
240
|
href="#/chat"
|
|
214
241
|
class="block px-3 py-2 rounded-md text-base font-medium"
|
|
215
242
|
:class="chatView ? 'text-content bg-primary-subtle' : 'text-content-secondary hover:bg-muted'">Chat</a>
|
|
216
|
-
<span v-else-if="hasAccess(roles, 'chat') && !
|
|
243
|
+
<span v-else-if="hasAccess(roles, 'chat') && !supportsAI"
|
|
217
244
|
class="block px-3 py-2 rounded-md text-base font-medium text-gray-300 cursor-not-allowed"
|
|
218
245
|
:title="chatDisabledReason">
|
|
219
246
|
Chat
|
|
@@ -266,3 +293,47 @@
|
|
|
266
293
|
</nav>
|
|
267
294
|
</div>
|
|
268
295
|
</div>
|
|
296
|
+
|
|
297
|
+
<modal
|
|
298
|
+
v-if="showRecentPagesModal"
|
|
299
|
+
flush-container
|
|
300
|
+
containerClass="!max-w-md !w-[min(94vw,28rem)] !overflow-hidden !rounded-lg !border !border-edge !bg-surface !shadow-xl dark:!bg-shark-900 text-content"
|
|
301
|
+
bodyClass="modal-recent-pages-body !p-0"
|
|
302
|
+
>
|
|
303
|
+
<template v-slot:body>
|
|
304
|
+
<div class="modal-exit" @click="closeRecentPagesModal" role="button" aria-label="Close recent pages">×</div>
|
|
305
|
+
<div
|
|
306
|
+
class="shrink-0 flex items-center gap-3 border-b border-edge bg-surface px-4 py-4 pr-12 dark:bg-shark-900"
|
|
307
|
+
>
|
|
308
|
+
<h2 class="m-0 text-lg font-semibold text-content">Recent pages</h2>
|
|
309
|
+
<button
|
|
310
|
+
type="button"
|
|
311
|
+
class="rounded px-2 py-1 text-sm font-medium text-content-secondary hover:bg-muted disabled:opacity-50"
|
|
312
|
+
@click="clearRecentPagesHistory"
|
|
313
|
+
:disabled="recentPagesList.length === 0"
|
|
314
|
+
>
|
|
315
|
+
Clear
|
|
316
|
+
</button>
|
|
317
|
+
</div>
|
|
318
|
+
<div class="modal-recent-pages-scroll">
|
|
319
|
+
<div
|
|
320
|
+
v-if="recentPagesList.length === 0"
|
|
321
|
+
class="m-4 rounded border border-dashed border-edge px-3 py-6 text-center text-sm text-content-tertiary"
|
|
322
|
+
>
|
|
323
|
+
No recent pages yet.
|
|
324
|
+
</div>
|
|
325
|
+
<button
|
|
326
|
+
v-for="entry in recentPagesList"
|
|
327
|
+
:key="entry.path + '-' + entry.visitedAt"
|
|
328
|
+
type="button"
|
|
329
|
+
class="w-full px-4 py-2.5 text-left hover:bg-muted"
|
|
330
|
+
:class="entry.path === $route.fullPath ? 'bg-primary-subtle' : ''"
|
|
331
|
+
@click="goToRecentPage(entry)"
|
|
332
|
+
>
|
|
333
|
+
<div class="truncate text-sm font-medium text-content">{{ entry.label }}</div>
|
|
334
|
+
<div class="truncate font-mono text-xs text-content-tertiary">{{ entry.path }}</div>
|
|
335
|
+
</button>
|
|
336
|
+
</div>
|
|
337
|
+
</template>
|
|
338
|
+
</modal>
|
|
339
|
+
</div>
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const api = require('../api');
|
|
4
3
|
const mothership = require('../mothership');
|
|
5
4
|
const template = require('./navbar.html');
|
|
6
5
|
const { routes, hasAccess } = require('../routes');
|
|
6
|
+
const {
|
|
7
|
+
RECENT_PAGES_STORAGE_KEY,
|
|
8
|
+
RECENT_PAGES_CHANGED_EVENT,
|
|
9
|
+
safeReadRecentPages,
|
|
10
|
+
saveRecentPages,
|
|
11
|
+
withRecentPagesStorageLock
|
|
12
|
+
} = require('../_util/recent-pages-history');
|
|
7
13
|
|
|
8
14
|
const appendCSS = require('../appendCSS');
|
|
9
15
|
|
|
@@ -15,7 +21,9 @@ module.exports = app => app.component('navbar', {
|
|
|
15
21
|
inject: ['state'],
|
|
16
22
|
data: () => ({
|
|
17
23
|
showFlyout: false,
|
|
18
|
-
darkMode: typeof localStorage !== 'undefined' && localStorage.getItem('studio-theme') === 'dark'
|
|
24
|
+
darkMode: typeof localStorage !== 'undefined' && localStorage.getItem('studio-theme') === 'dark',
|
|
25
|
+
showRecentPagesModal: false,
|
|
26
|
+
localRecentPages: []
|
|
19
27
|
}),
|
|
20
28
|
mounted: function() {
|
|
21
29
|
window.navbar = this;
|
|
@@ -37,6 +45,32 @@ module.exports = app => app.component('navbar', {
|
|
|
37
45
|
mobileMenu.classList.add('translate-x-full');
|
|
38
46
|
});
|
|
39
47
|
}
|
|
48
|
+
|
|
49
|
+
this.localRecentPages = safeReadRecentPages();
|
|
50
|
+
|
|
51
|
+
this._syncRecentPagesFromOtherTab = ev => {
|
|
52
|
+
if (ev.storageArea !== window.localStorage || ev.key !== RECENT_PAGES_STORAGE_KEY) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.refreshRecentPagesFromStorage();
|
|
56
|
+
};
|
|
57
|
+
this._syncRecentPagesFromBroadcast = () => this.refreshRecentPagesFromStorage();
|
|
58
|
+
|
|
59
|
+
window.addEventListener('storage', this._syncRecentPagesFromOtherTab);
|
|
60
|
+
window.addEventListener(RECENT_PAGES_CHANGED_EVENT, this._syncRecentPagesFromBroadcast);
|
|
61
|
+
},
|
|
62
|
+
beforeUnmount() {
|
|
63
|
+
if (this._syncRecentPagesFromOtherTab) {
|
|
64
|
+
window.removeEventListener('storage', this._syncRecentPagesFromOtherTab);
|
|
65
|
+
}
|
|
66
|
+
if (this._syncRecentPagesFromBroadcast) {
|
|
67
|
+
window.removeEventListener(RECENT_PAGES_CHANGED_EVENT, this._syncRecentPagesFromBroadcast);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
watch: {
|
|
71
|
+
'$route.fullPath'() {
|
|
72
|
+
this.refreshRecentPagesFromStorage();
|
|
73
|
+
}
|
|
40
74
|
},
|
|
41
75
|
computed: {
|
|
42
76
|
dashboardView() {
|
|
@@ -69,8 +103,11 @@ module.exports = app => app.component('navbar', {
|
|
|
69
103
|
hasTaskVisualizer() {
|
|
70
104
|
return !!window.MONGOOSE_STUDIO_CONFIG.enableTaskVisualizer;
|
|
71
105
|
},
|
|
72
|
-
|
|
73
|
-
return
|
|
106
|
+
recentPagesList() {
|
|
107
|
+
return this.localRecentPages;
|
|
108
|
+
},
|
|
109
|
+
supportsAI() {
|
|
110
|
+
return this.state.capabilities == null || this.state.capabilities.supportsAI !== false;
|
|
74
111
|
},
|
|
75
112
|
chatDisabledReason() {
|
|
76
113
|
return 'Chat requires an Anthropic, Gemini, or OpenAI API key.';
|
|
@@ -103,6 +140,30 @@ module.exports = app => app.component('navbar', {
|
|
|
103
140
|
const meta = document.querySelector('meta[name="theme-color"]');
|
|
104
141
|
if (meta) meta.setAttribute('content', this.darkMode ? '#0f0f0f' : '#ffffff');
|
|
105
142
|
document.documentElement.dispatchEvent(new CustomEvent('studio-theme-changed', { detail: { dark: this.darkMode } }));
|
|
143
|
+
},
|
|
144
|
+
refreshRecentPagesFromStorage() {
|
|
145
|
+
this.localRecentPages = safeReadRecentPages();
|
|
146
|
+
},
|
|
147
|
+
openRecentPagesModal() {
|
|
148
|
+
this.showRecentPagesModal = true;
|
|
149
|
+
this.refreshRecentPagesFromStorage();
|
|
150
|
+
},
|
|
151
|
+
closeRecentPagesModal() {
|
|
152
|
+
this.showRecentPagesModal = false;
|
|
153
|
+
},
|
|
154
|
+
clearRecentPagesHistory() {
|
|
155
|
+
this.localRecentPages = [];
|
|
156
|
+
void withRecentPagesStorageLock(() => saveRecentPages([]));
|
|
157
|
+
},
|
|
158
|
+
goToRecentPage(entry) {
|
|
159
|
+
if (!entry || !entry.path) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.showRecentPagesModal = false;
|
|
163
|
+
if (entry.path === this.$route.fullPath) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.$router.push(entry.path);
|
|
106
167
|
}
|
|
107
168
|
},
|
|
108
169
|
directives: {
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mongoosejs/studio",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "AI-Powered Data Workspace for MongoDB: Turn your MongoDB data into dashboards, maps, and interactive workflows - powered by your Mongoose models and AI.",
|
|
5
5
|
"homepage": "https://mongoosestudio.app/",
|
|
6
6
|
"repository": {
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"tailwind": "tailwindcss -o ./frontend/public/tw.css",
|
|
54
54
|
"tailwind:watch": "tailwindcss -o ./frontend/public/tw.css --watch",
|
|
55
55
|
"test": "mocha test/*.test.js",
|
|
56
|
-
"test:frontend": "mocha test/frontend/*.test.js"
|
|
56
|
+
"test:frontend": "mocha test/frontend/*.test.js",
|
|
57
|
+
"eval:agent": "node eval/agent/run.js"
|
|
57
58
|
}
|
|
58
59
|
}
|