@mongoosejs/studio 0.3.11 → 0.4.0
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 +15 -3
- package/backend/actions/ChatThread/createChatThread.js +8 -1
- package/backend/actions/ChatThread/index.js +1 -0
- package/backend/actions/ChatThread/streamChatMessage.js +49 -14
- package/backend/actions/ChatThread/toggleAgentMode.js +37 -0
- package/backend/actions/Model/streamChatMessage.js +15 -4
- package/backend/authorize.js +1 -0
- package/backend/chatAgent/agentSystemPrompt.js +45 -0
- package/backend/chatAgent/agentToolMetadata.js +20 -0
- package/backend/chatAgent/getAgentTools.js +140 -0
- package/backend/db/chatMessageSchema.js +5 -0
- package/backend/db/chatThreadSchema.js +4 -0
- package/backend/integrations/callLLM.js +4 -2
- package/backend/integrations/streamLLM.js +12 -4
- package/eslint.config.js +2 -1
- package/frontend/public/app.js +171 -23
- package/frontend/public/tw.css +34 -8
- package/frontend/src/api.js +6 -0
- package/frontend/src/chat/chat-message/chat-message.html +12 -1
- package/frontend/src/chat/chat-message/chat-message.js +8 -0
- package/frontend/src/chat/chat-message-script/chat-message-script.html +1 -1
- package/frontend/src/chat/chat.html +91 -44
- package/frontend/src/chat/chat.js +119 -19
- package/frontend/src/create-document/create-document.js +3 -0
- package/package.json +3 -2
package/frontend/public/app.js
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
/******/ (() => { // webpackBootstrap
|
|
2
2
|
/******/ var __webpack_modules__ = ({
|
|
3
3
|
|
|
4
|
+
/***/ "./backend/chatAgent/agentToolMetadata.js"
|
|
5
|
+
/*!************************************************!*\
|
|
6
|
+
!*** ./backend/chatAgent/agentToolMetadata.js ***!
|
|
7
|
+
\************************************************/
|
|
8
|
+
(module) {
|
|
9
|
+
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
module.exports = [
|
|
14
|
+
{
|
|
15
|
+
name: 'estimatedDocumentCount',
|
|
16
|
+
description: 'Count the estimated number of documents in a collection. Times out after 5 seconds.'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'find',
|
|
20
|
+
description: 'Run a find() query on a Mongoose model and return an array of documents. Times out after 5 seconds.'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'findOne',
|
|
24
|
+
description: 'Run a findOne() query on a Mongoose model and return a single document or null. Times out after 5 seconds.'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'typeCheck',
|
|
28
|
+
description: 'Type-checks the script and validates syntax using TypeScript and node --check'
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/***/ },
|
|
34
|
+
|
|
4
35
|
/***/ "./frontend/src/_util/baseComponent.js"
|
|
5
36
|
/*!*********************************************!*\
|
|
6
37
|
!*** ./frontend/src/_util/baseComponent.js ***!
|
|
@@ -685,6 +716,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
685
716
|
shareChatThread(params) {
|
|
686
717
|
return client.post('', { action: 'ChatThread.shareChatThread', ...params }).then(res => res.data);
|
|
687
718
|
},
|
|
719
|
+
toggleAgentMode(params) {
|
|
720
|
+
return client.post('', { action: 'ChatThread.toggleAgentMode', ...params }).then(res => res.data);
|
|
721
|
+
},
|
|
688
722
|
streamChatMessage: async function* streamChatMessage(params) {
|
|
689
723
|
// Don't stream on Next.js or Netlify for now.
|
|
690
724
|
const data = await client.post('', { action: 'ChatThread.createChatMessage', ...params }).then(res => res.data);
|
|
@@ -861,6 +895,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
861
895
|
shareChatThread: function shareChatThread(params) {
|
|
862
896
|
return client.post('/ChatThread/shareChatThread', params).then(res => res.data);
|
|
863
897
|
},
|
|
898
|
+
toggleAgentMode: function toggleAgentMode(params) {
|
|
899
|
+
return client.post('/ChatThread/toggleAgentMode', params).then(res => res.data);
|
|
900
|
+
},
|
|
864
901
|
streamChatMessage: async function* streamChatMessage(params) {
|
|
865
902
|
const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
|
|
866
903
|
const url = window.MONGOOSE_STUDIO_CONFIG.baseURL + '/ChatThread/streamChatMessage?' + new URLSearchParams(params).toString();
|
|
@@ -1593,6 +1630,14 @@ module.exports = app => app.component('chat-message', {
|
|
|
1593
1630
|
marked(text) {
|
|
1594
1631
|
return marked(text);
|
|
1595
1632
|
},
|
|
1633
|
+
formatToolInput(input) {
|
|
1634
|
+
if (!input) return '';
|
|
1635
|
+
const parts = [];
|
|
1636
|
+
if (input.modelName) parts.push(input.modelName);
|
|
1637
|
+
if (input.filter && Object.keys(input.filter).length) parts.push(JSON.stringify(input.filter));
|
|
1638
|
+
if (input.limit && input.limit !== 10) parts.push('limit=' + input.limit);
|
|
1639
|
+
return parts.length ? '(' + parts.join(', ') + ')' : '';
|
|
1640
|
+
},
|
|
1596
1641
|
async executeScript(message, script) {
|
|
1597
1642
|
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
1598
1643
|
chatMessageId: message._id,
|
|
@@ -1643,9 +1688,12 @@ module.exports = app => app.component('chat-message', {
|
|
|
1643
1688
|
|
|
1644
1689
|
|
|
1645
1690
|
const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
|
|
1691
|
+
const agentToolMetadata = __webpack_require__(/*! ../../../backend/chatAgent/agentToolMetadata */ "./backend/chatAgent/agentToolMetadata.js");
|
|
1646
1692
|
const getCurrentDateTimeContext = __webpack_require__(/*! ../getCurrentDateTimeContext */ "./frontend/src/getCurrentDateTimeContext.js");
|
|
1647
1693
|
const template = __webpack_require__(/*! ./chat.html */ "./frontend/src/chat/chat.html");
|
|
1648
1694
|
|
|
1695
|
+
const AGENT_MODE_STORAGE_KEY = '_mongooseStudioAgentMode';
|
|
1696
|
+
|
|
1649
1697
|
module.exports = {
|
|
1650
1698
|
template: template,
|
|
1651
1699
|
props: ['threadId'],
|
|
@@ -1654,12 +1702,15 @@ module.exports = {
|
|
|
1654
1702
|
sendingMessage: false,
|
|
1655
1703
|
newMessage: '',
|
|
1656
1704
|
chatThreadId: null,
|
|
1705
|
+
draftAgentMode: false,
|
|
1657
1706
|
chatThreads: [],
|
|
1658
1707
|
chatMessages: [],
|
|
1659
1708
|
hideSidebar: null,
|
|
1709
|
+
showAgentSidebar: false,
|
|
1660
1710
|
sharingThread: false,
|
|
1661
1711
|
threadSearch: '',
|
|
1662
|
-
showProUpgradeModal: false
|
|
1712
|
+
showProUpgradeModal: false,
|
|
1713
|
+
agentTools: agentToolMetadata
|
|
1663
1714
|
}),
|
|
1664
1715
|
methods: {
|
|
1665
1716
|
async sendMessage() {
|
|
@@ -1668,7 +1719,9 @@ module.exports = {
|
|
|
1668
1719
|
const content = this.newMessage;
|
|
1669
1720
|
this.newMessage = '';
|
|
1670
1721
|
if (!this.chatThreadId) {
|
|
1671
|
-
const { chatThread } = await api.ChatThread.createChatThread(
|
|
1722
|
+
const { chatThread } = await api.ChatThread.createChatThread({
|
|
1723
|
+
agentMode: this.draftAgentMode
|
|
1724
|
+
});
|
|
1672
1725
|
this.chatThreads.unshift(chatThread);
|
|
1673
1726
|
this.chatThreadId = chatThread._id;
|
|
1674
1727
|
this.chatMessages = [];
|
|
@@ -1682,11 +1735,7 @@ module.exports = {
|
|
|
1682
1735
|
role: 'user'
|
|
1683
1736
|
});
|
|
1684
1737
|
|
|
1685
|
-
this
|
|
1686
|
-
if (this.$refs.messagesContainer) {
|
|
1687
|
-
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
|
|
1688
|
-
}
|
|
1689
|
-
});
|
|
1738
|
+
this.scrollToBottom();
|
|
1690
1739
|
|
|
1691
1740
|
const params = {
|
|
1692
1741
|
chatThreadId: this.chatThreadId,
|
|
@@ -1695,6 +1744,7 @@ module.exports = {
|
|
|
1695
1744
|
};
|
|
1696
1745
|
let userChatMessage = null;
|
|
1697
1746
|
let assistantChatMessage = null;
|
|
1747
|
+
const toolCalls = [];
|
|
1698
1748
|
for await (const event of api.ChatThread.streamChatMessage(params)) {
|
|
1699
1749
|
if (event.chatMessage) {
|
|
1700
1750
|
if (!userChatMessage) {
|
|
@@ -1703,6 +1753,7 @@ module.exports = {
|
|
|
1703
1753
|
} else {
|
|
1704
1754
|
const assistantChatMessageIndex = this.chatMessages.indexOf(assistantChatMessage);
|
|
1705
1755
|
assistantChatMessage = event.chatMessage;
|
|
1756
|
+
assistantChatMessage.toolCalls = toolCalls;
|
|
1706
1757
|
if (assistantChatMessageIndex !== -1) {
|
|
1707
1758
|
this.chatMessages.splice(assistantChatMessageIndex, 1, assistantChatMessage);
|
|
1708
1759
|
} else {
|
|
@@ -1715,27 +1766,44 @@ module.exports = {
|
|
|
1715
1766
|
thread.title = event.chatThread.title;
|
|
1716
1767
|
}
|
|
1717
1768
|
}
|
|
1769
|
+
} else if (event.toolCall) {
|
|
1770
|
+
toolCalls.push({ toolName: event.toolCall.toolName, input: event.toolCall.input, status: 'running' });
|
|
1771
|
+
if (!assistantChatMessage) {
|
|
1772
|
+
assistantChatMessage = {
|
|
1773
|
+
_id: Math.random().toString(36).substr(2, 9),
|
|
1774
|
+
content: '',
|
|
1775
|
+
role: 'assistant',
|
|
1776
|
+
toolCalls: [...toolCalls]
|
|
1777
|
+
};
|
|
1778
|
+
this.chatMessages.push(assistantChatMessage);
|
|
1779
|
+
assistantChatMessage = this.chatMessages[this.chatMessages.length - 1];
|
|
1780
|
+
} else {
|
|
1781
|
+
assistantChatMessage.toolCalls = [...toolCalls];
|
|
1782
|
+
}
|
|
1783
|
+
this.scrollToBottom();
|
|
1784
|
+
} else if (event.toolResult) {
|
|
1785
|
+
const tc = toolCalls.find(t => t.toolName === event.toolResult.toolName && t.status === 'running');
|
|
1786
|
+
if (tc) {
|
|
1787
|
+
tc.status = 'done';
|
|
1788
|
+
}
|
|
1789
|
+
if (assistantChatMessage) {
|
|
1790
|
+
assistantChatMessage.toolCalls = [...toolCalls];
|
|
1791
|
+
}
|
|
1792
|
+
this.scrollToBottom();
|
|
1718
1793
|
} else if (event.textPart) {
|
|
1719
1794
|
if (!assistantChatMessage) {
|
|
1720
1795
|
assistantChatMessage = {
|
|
1721
1796
|
_id: Math.random().toString(36).substr(2, 9),
|
|
1722
1797
|
content: event.textPart,
|
|
1723
|
-
role: 'assistant'
|
|
1798
|
+
role: 'assistant',
|
|
1799
|
+
toolCalls: [...toolCalls]
|
|
1724
1800
|
};
|
|
1725
1801
|
this.chatMessages.push(assistantChatMessage);
|
|
1726
1802
|
assistantChatMessage = this.chatMessages[this.chatMessages.length - 1];
|
|
1727
|
-
this
|
|
1728
|
-
if (this.$refs.messagesContainer) {
|
|
1729
|
-
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
|
|
1730
|
-
}
|
|
1731
|
-
});
|
|
1803
|
+
this.scrollToBottom();
|
|
1732
1804
|
} else {
|
|
1733
1805
|
assistantChatMessage.content += event.textPart;
|
|
1734
|
-
this
|
|
1735
|
-
if (this.$refs.messagesContainer) {
|
|
1736
|
-
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
|
|
1737
|
-
}
|
|
1738
|
-
});
|
|
1806
|
+
this.scrollToBottom();
|
|
1739
1807
|
}
|
|
1740
1808
|
} else if (event.message) {
|
|
1741
1809
|
throw new Error(event.message);
|
|
@@ -1754,10 +1822,38 @@ module.exports = {
|
|
|
1754
1822
|
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
|
|
1755
1823
|
}
|
|
1756
1824
|
});
|
|
1825
|
+
} catch (err) {
|
|
1826
|
+
this.$toast.error(err?.message || 'Failed to send message.');
|
|
1757
1827
|
} finally {
|
|
1758
1828
|
this.sendingMessage = false;
|
|
1759
1829
|
}
|
|
1760
1830
|
},
|
|
1831
|
+
async toggleAgentMode() {
|
|
1832
|
+
const wasEnabled = this.isAgentModeEnabled;
|
|
1833
|
+
const newValue = !this.isAgentModeEnabled;
|
|
1834
|
+
this.draftAgentMode = newValue;
|
|
1835
|
+
this.persistAgentModePreference(newValue);
|
|
1836
|
+
if (!this.chatThreadId) {
|
|
1837
|
+
this.maybeOpenAgentSidebar({ wasEnabled, isEnabled: newValue });
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
const { chatThread } = await api.ChatThread.toggleAgentMode({
|
|
1841
|
+
chatThreadId: this.chatThreadId,
|
|
1842
|
+
agentMode: newValue
|
|
1843
|
+
});
|
|
1844
|
+
const idx = this.chatThreads.findIndex(t => t._id === chatThread._id);
|
|
1845
|
+
if (idx !== -1) {
|
|
1846
|
+
this.chatThreads.splice(idx, 1, chatThread);
|
|
1847
|
+
}
|
|
1848
|
+
this.maybeOpenAgentSidebar({ wasEnabled, isEnabled: newValue });
|
|
1849
|
+
},
|
|
1850
|
+
scrollToBottom() {
|
|
1851
|
+
this.$nextTick(() => {
|
|
1852
|
+
if (this.$refs.messagesContainer) {
|
|
1853
|
+
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
|
|
1854
|
+
}
|
|
1855
|
+
});
|
|
1856
|
+
},
|
|
1761
1857
|
handleEnter(ev) {
|
|
1762
1858
|
if (!ev.shiftKey) {
|
|
1763
1859
|
this.sendMessage();
|
|
@@ -1777,7 +1873,9 @@ module.exports = {
|
|
|
1777
1873
|
return message.role === 'user' ? 'bg-muted' : '';
|
|
1778
1874
|
},
|
|
1779
1875
|
async createNewThread() {
|
|
1780
|
-
const { chatThread } = await api.ChatThread.createChatThread(
|
|
1876
|
+
const { chatThread } = await api.ChatThread.createChatThread({
|
|
1877
|
+
agentMode: this.draftAgentMode
|
|
1878
|
+
});
|
|
1781
1879
|
this.$toast.success('Chat thread created!');
|
|
1782
1880
|
this.$router.push('/chat/' + chatThread._id);
|
|
1783
1881
|
},
|
|
@@ -1819,12 +1917,57 @@ module.exports = {
|
|
|
1819
1917
|
} finally {
|
|
1820
1918
|
this.sharingThread = false;
|
|
1821
1919
|
}
|
|
1920
|
+
},
|
|
1921
|
+
isDesktopViewport() {
|
|
1922
|
+
return typeof window !== 'undefined' &&
|
|
1923
|
+
typeof window.matchMedia === 'function' &&
|
|
1924
|
+
window.matchMedia('(min-width: 1024px)').matches;
|
|
1925
|
+
},
|
|
1926
|
+
getAgentModePreference() {
|
|
1927
|
+
if (typeof window === 'undefined') {
|
|
1928
|
+
return false;
|
|
1929
|
+
}
|
|
1930
|
+
return window.localStorage?.getItem(AGENT_MODE_STORAGE_KEY) === 'true';
|
|
1931
|
+
},
|
|
1932
|
+
persistAgentModePreference(agentMode) {
|
|
1933
|
+
if (typeof window !== 'undefined') {
|
|
1934
|
+
window.localStorage?.setItem(AGENT_MODE_STORAGE_KEY, String(agentMode));
|
|
1935
|
+
}
|
|
1936
|
+
},
|
|
1937
|
+
async syncCurrentThreadAgentMode() {
|
|
1938
|
+
if (!this.chatThreadId || !this.currentThread || !this.draftAgentMode || this.currentThread.agentMode) {
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
const { chatThread } = await api.ChatThread.toggleAgentMode({
|
|
1942
|
+
chatThreadId: this.chatThreadId,
|
|
1943
|
+
agentMode: true
|
|
1944
|
+
});
|
|
1945
|
+
const idx = this.chatThreads.findIndex(t => t._id === chatThread._id);
|
|
1946
|
+
if (idx !== -1) {
|
|
1947
|
+
this.chatThreads.splice(idx, 1, chatThread);
|
|
1948
|
+
}
|
|
1949
|
+
},
|
|
1950
|
+
maybeOpenAgentSidebar({ wasEnabled, isEnabled }) {
|
|
1951
|
+
if (!isEnabled) {
|
|
1952
|
+
this.showAgentSidebar = false;
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
if (wasEnabled || !this.isDesktopViewport()) {
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
this.showAgentSidebar = true;
|
|
1959
|
+
},
|
|
1960
|
+
closeAgentSidebar() {
|
|
1961
|
+
this.showAgentSidebar = false;
|
|
1822
1962
|
}
|
|
1823
1963
|
},
|
|
1824
1964
|
computed: {
|
|
1825
1965
|
currentThread() {
|
|
1826
1966
|
return this.chatThreads.find(t => t._id === this.chatThreadId);
|
|
1827
1967
|
},
|
|
1968
|
+
isAgentModeEnabled() {
|
|
1969
|
+
return this.currentThread?.agentMode ?? this.draftAgentMode;
|
|
1970
|
+
},
|
|
1828
1971
|
hasWorkspace() {
|
|
1829
1972
|
return !!window.MONGOOSE_STUDIO_CONFIG.workspace?._id;
|
|
1830
1973
|
},
|
|
@@ -1842,10 +1985,12 @@ module.exports = {
|
|
|
1842
1985
|
async mounted() {
|
|
1843
1986
|
window.pageState = this;
|
|
1844
1987
|
|
|
1988
|
+
this.draftAgentMode = this.getAgentModePreference();
|
|
1845
1989
|
this.chatThreadId = this.threadId;
|
|
1846
1990
|
const { chatThreads } = await api.ChatThread.listChatThreads();
|
|
1847
1991
|
this.chatThreads = chatThreads;
|
|
1848
1992
|
if (this.chatThreadId) {
|
|
1993
|
+
await this.syncCurrentThreadAgentMode();
|
|
1849
1994
|
const { chatMessages } = await api.ChatThread.getChatThread({ chatThreadId: this.chatThreadId });
|
|
1850
1995
|
this.chatMessages = chatMessages;
|
|
1851
1996
|
}
|
|
@@ -2055,6 +2200,9 @@ module.exports = app => app.component('create-document', {
|
|
|
2055
2200
|
documentData: this.aiOriginalDocument,
|
|
2056
2201
|
currentDateTime: getCurrentDateTimeContext()
|
|
2057
2202
|
})) {
|
|
2203
|
+
if (event?.message) {
|
|
2204
|
+
throw new Error(event.message);
|
|
2205
|
+
}
|
|
2058
2206
|
if (event?.textPart) {
|
|
2059
2207
|
this.aiSuggestion += event.textPart;
|
|
2060
2208
|
}
|
|
@@ -50814,7 +50962,7 @@ module.exports = "<button v-bind=\"attrsToBind\" :disabled=\"isDisabled\" @click
|
|
|
50814
50962
|
(module) {
|
|
50815
50963
|
|
|
50816
50964
|
"use strict";
|
|
50817
|
-
module.exports = "<div class=\"chat-message-script relative border rounded bg-surface my-1 text-content text-sm overflow-hidden\">\n <div class=\"flex border-b py-1 pl-1 text-xs font-medium bg-surface\">\n <button\n class=\"px-4 py-1 border-r border-edge-strong text-content-secondary font-semibold transition-colors duration-200 focus:outline-none\"\n :class=\"[\n 'rounded-l-md',\n activeTab === 'code'\n ? 'bg-gray-700 text-white shadow'\n : 'bg-muted hover:bg-muted text-gray-600'\n ]\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-4 py-1 text-content-secondary font-semibold transition-colors duration-200 focus:outline-none\"\n :class=\"[\n 'rounded-r-md',\n activeTab === 'output'\n ? 'bg-gray-700 text-white shadow'\n : 'bg-muted hover:bg-muted text-gray-600'\n ]\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex items-center\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-primary-hover transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"height: 1.2em;\" 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 <button\n v-if=\"activeTab === 'code' && !isEditing\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click.stop=\"startEditing\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM4 13.5V16h2.5l7.086-7.086-2.828-2.828L4 13.5z\" />\n </svg>\n </button>\n <async-button\n v-if=\"!isEditing\"\n class=\"px-2 py-1 text-xs bg-primary hover:bg-primary-hover text-primary-text border-none rounded cursor-pointer transition-colors disabled:bg-gray-400\"\n @click=\"executeScript\">\n Run\n </async-button>\n <div class=\"relative ml-1\" ref=\"dropdown\">\n <button\n @click.stop=\"toggleDropdown\"\n class=\"px-1 py-1 text-xs hover:bg-gray-300 rounded flex items-center\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 6a2 2 0 110-4 2 2 0 010 4zm0 6a2 2 0 110-4 2 2 0 010 4zm0 6a2 2 0 110-4 2 2 0 010 4z\" />\n </svg>\n </button>\n <div\n v-if=\"showDropdown\"\n class=\"absolute right-0 z-10 mt-1 w-64 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5\">\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"openCreateDashboardModal(); showDropdown = false\">\n Create Dashboard\n </button>\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"copyOutput(); showDropdown = false\">\n Copy Output As Text\n </button>\n <button\n v-if=\"canOverwriteDashboard\"\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"openOverwriteDashboardConfirmation(); showDropdown = false\">\n Overwrite Dashboard\n </button>\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"$emit('copyMessage'); showDropdown = false\">\n Copy Full Message\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"p-0 max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\">\n <div v-if=\"isEditing\" class=\"flex flex-col space-y-2 chat-script-editor-wrap\">\n <div class=\"border border-edge\">\n <ace-editor\n v-model=\"editedScript\"\n mode=\"javascript\"\n :line-numbers=\"true\"\n class=\"w-full h-[45vh] min-h-[200px]\"\n />\n </div>\n <div class=\"flex justify-end gap-2 pb-2\">\n <button\n class=\"px-2 py-1 text-xs bg-gray-300 text-gray-800 border-none rounded cursor-pointer hover:bg-gray-400 transition-colors\"\n @click.stop=\"cancelEditing\">\n Cancel\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-blue-600 text-white border-none rounded cursor-pointer hover:bg-blue-700 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript\">\n Execute\n </async-button>\n </div>\n </div>\n <pre v-else class=\"whitespace-pre-wrap !my-0 bg-muted\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n </div>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-surface border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-result\n v-if=\"message.executionResult?.output != null\"\n :result=\"message.executionResult.output\">\n </dashboard-result>\n <pre v-else>No output</pre>\n\n <div v-if=\"message.executionResult?.logs?.length\" class=\"mt-3 pt-3 border-t border-edge\">\n <div class=\"text-xs font-semibold text-gray-600 uppercase tracking-wide\">Console</div>\n <pre class=\"mt-1 bg-muted text-content p-3 rounded whitespace-pre-wrap overflow-x-auto max-h-[280px]\">{{ message.executionResult.logs }}</pre>\n </div>\n </div>\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-result\n v-if=\"message.executionResult?.output != null\"\n :result=\"message.executionResult.output\"\n :fullscreen=\"true\">\n </dashboard-result>\n <pre v-else class=\"whitespace-pre-wrap\">No output</pre>\n </div>\n </template>\n </modal>\n <modal v-if=\"showCreateDashboardModal\">\n <template #body>\n <div class=\"modal-exit\" @click=\"showCreateDashboardModal = false\">×</div>\n <div>\n <div class=\"mt-4 text-content font-semibold\">Create Dashboard</div>\n <div class=\"mt-4\">\n <label class=\"block text-sm font-medium leading-6 text-content\">Title</label>\n <div class=\"mt-2\">\n <div class=\"w-full flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-teal-600\">\n <input type=\"text\" v-model=\"newDashboardTitle\" class=\"outline-none block flex-1 border-0 bg-transparent py-1.5 pl-1 text-content placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6\" placeholder=\"My Dashboard\">\n </div>\n </div>\n </div>\n <div class=\"my-4\">\n <label class=\"block text-sm font-medium leading-6 text-content\">Code</label>\n <div class=\"border border-edge\">\n <ace-editor\n v-model=\"dashboardCode\"\n mode=\"javascript\"\n :line-numbers=\"true\"\n class=\"h-[300px] w-full\"\n />\n </div>\n </div>\n <async-button\n @click=\"createDashboardFromScript\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n Submit\n </async-button>\n <div v-if=\"createError\" class=\"rounded-md bg-red-50 p-4 mt-1\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">Error</h3>\n <div class=\"mt-2 text-sm text-red-700\">\n {{createError}}\n </div>\n </div>\n </div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"showOverwriteDashboardConfirmationModal\">\n <template #body>\n <div class=\"modal-exit\" @click=\"showOverwriteDashboardConfirmationModal = false\">×</div>\n <div>\n <div class=\"mt-4 text-content font-semibold\">Overwrite Dashboard</div>\n <p class=\"mt-2 text-sm text-content-secondary\">\n This will replace the linked dashboard's code with the script below.\n </p>\n <p class=\"mt-1 text-xs text-gray-600 break-all\" v-if=\"targetDashboardId\">\n Dashboard ID: {{ targetDashboardId }}\n </p>\n <div class=\"my-4 border border-edge bg-page rounded\">\n <pre class=\"p-2 h-[300px] overflow-auto whitespace-pre-wrap text-xs\">{{ overwriteDashboardCode }}</pre>\n </div>\n <div class=\"flex items-center gap-2\">\n <async-button\n @click=\"confirmOverwriteDashboard\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n Confirm Overwrite\n </async-button>\n <button\n class=\"px-2.5 py-1.5 rounded-md text-sm font-semibold text-content-secondary bg-gray-200 hover:bg-gray-300\"\n @click=\"showOverwriteDashboardConfirmationModal = false\">\n Cancel\n </button>\n </div>\n <div v-if=\"overwriteError\" class=\"rounded-md bg-red-50 p-4 mt-3\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">Error</h3>\n <div class=\"mt-2 text-sm text-red-700\">\n {{overwriteError}}\n </div>\n </div>\n </div>\n </div>\n </div>\n </template>\n </modal>\n</div>\n";
|
|
50965
|
+
module.exports = "<div class=\"chat-message-script relative border rounded bg-surface my-1 text-content text-sm overflow-hidden\">\n <div class=\"flex border-b py-1 pl-1 text-xs font-medium bg-surface\">\n <button\n class=\"px-4 py-1 border-r border-edge-strong text-content-secondary font-semibold transition-colors duration-200 focus:outline-none\"\n :class=\"[\n 'rounded-l-md',\n activeTab === 'code'\n ? 'bg-gray-700 text-white shadow'\n : 'bg-muted hover:bg-muted text-gray-600'\n ]\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-4 py-1 text-content-secondary font-semibold transition-colors duration-200 focus:outline-none\"\n :class=\"[\n 'rounded-r-md',\n activeTab === 'output'\n ? 'bg-gray-700 text-white shadow'\n : 'bg-muted hover:bg-muted text-gray-600'\n ]\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex items-center\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-primary-hover transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"height: 1.2em;\" 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 <button\n v-if=\"activeTab === 'code' && !isEditing\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-700 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click.stop=\"startEditing\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM4 13.5V16h2.5l7.086-7.086-2.828-2.828L4 13.5z\" />\n </svg>\n </button>\n <async-button\n v-if=\"!isEditing\"\n class=\"px-2 py-1 text-xs bg-primary hover:bg-primary-hover text-primary-text border-none rounded cursor-pointer transition-colors disabled:bg-gray-400\"\n @click=\"executeScript\">\n Run\n </async-button>\n <div class=\"relative ml-1\" ref=\"dropdown\">\n <button\n @click.stop=\"toggleDropdown\"\n class=\"px-1 py-1 text-xs hover:bg-gray-300 rounded flex items-center\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 6a2 2 0 110-4 2 2 0 010 4zm0 6a2 2 0 110-4 2 2 0 010 4zm0 6a2 2 0 110-4 2 2 0 010 4z\" />\n </svg>\n </button>\n <div\n v-if=\"showDropdown\"\n class=\"absolute right-0 z-10 mt-1 w-64 origin-top-right rounded-md bg-surface py-1 shadow-lg ring-1 ring-black/5\">\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"openCreateDashboardModal(); showDropdown = false\">\n Create Dashboard\n </button>\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"copyOutput(); showDropdown = false\">\n Copy Output As Text\n </button>\n <button\n v-if=\"canOverwriteDashboard\"\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"openOverwriteDashboardConfirmation(); showDropdown = false\">\n Overwrite Dashboard\n </button>\n <button\n class=\"block w-full text-left px-4 py-2 text-xs text-content-secondary hover:bg-muted\"\n @click=\"$emit('copyMessage'); showDropdown = false\">\n Copy Full Message\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"p-0 max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\">\n <div v-if=\"isEditing\" class=\"flex flex-col space-y-2 chat-script-editor-wrap\">\n <div class=\"border border-edge\">\n <ace-editor\n v-model=\"editedScript\"\n mode=\"javascript\"\n :line-numbers=\"true\"\n class=\"w-full h-[45vh] min-h-[200px]\"\n />\n </div>\n <div class=\"flex justify-end gap-2 pb-2\">\n <button\n class=\"px-2 py-1 text-xs bg-gray-300 text-gray-800 border-none rounded cursor-pointer hover:bg-gray-400 transition-colors\"\n @click.stop=\"cancelEditing\">\n Cancel\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-blue-600 text-white border-none rounded cursor-pointer hover:bg-blue-700 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript\">\n Execute\n </async-button>\n </div>\n </div>\n <pre v-else class=\"whitespace-pre-wrap !my-0 bg-muted\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n </div>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[50vh] overflow-y-auto bg-surface border-t max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-result\n v-if=\"message.executionResult?.output != null\"\n :result=\"message.executionResult.output\">\n </dashboard-result>\n <pre v-else>No output</pre>\n\n <div v-if=\"message.executionResult?.logs?.length\" class=\"mt-3 pt-3 border-t border-edge\">\n <div class=\"text-xs font-semibold text-gray-600 uppercase tracking-wide\">Console</div>\n <pre class=\"mt-1 bg-muted text-content p-3 rounded whitespace-pre-wrap overflow-x-auto max-h-[280px]\">{{ message.executionResult.logs }}</pre>\n </div>\n </div>\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-result\n v-if=\"message.executionResult?.output != null\"\n :result=\"message.executionResult.output\"\n :fullscreen=\"true\">\n </dashboard-result>\n <pre v-else class=\"whitespace-pre-wrap\">No output</pre>\n </div>\n </template>\n </modal>\n <modal v-if=\"showCreateDashboardModal\">\n <template #body>\n <div class=\"modal-exit\" @click=\"showCreateDashboardModal = false\">×</div>\n <div>\n <div class=\"mt-4 text-content font-semibold\">Create Dashboard</div>\n <div class=\"mt-4\">\n <label class=\"block text-sm font-medium leading-6 text-content\">Title</label>\n <div class=\"mt-2\">\n <div class=\"w-full flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-teal-600\">\n <input type=\"text\" v-model=\"newDashboardTitle\" class=\"outline-none block flex-1 border-0 bg-transparent py-1.5 pl-1 text-content placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6\" placeholder=\"My Dashboard\">\n </div>\n </div>\n </div>\n <div class=\"my-4\">\n <label class=\"block text-sm font-medium leading-6 text-content\">Code</label>\n <div class=\"border border-edge\">\n <ace-editor\n v-model=\"dashboardCode\"\n mode=\"javascript\"\n :line-numbers=\"true\"\n class=\"h-[300px] w-full\"\n />\n </div>\n </div>\n <async-button\n @click=\"createDashboardFromScript\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n Submit\n </async-button>\n <div v-if=\"createError\" class=\"rounded-md bg-red-50 p-4 mt-1\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">Error</h3>\n <div class=\"mt-2 text-sm text-red-700\">\n {{createError}}\n </div>\n </div>\n </div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"showOverwriteDashboardConfirmationModal\">\n <template #body>\n <div class=\"modal-exit\" @click=\"showOverwriteDashboardConfirmationModal = false\">×</div>\n <div>\n <div class=\"mt-4 text-content font-semibold\">Overwrite Dashboard</div>\n <p class=\"mt-2 text-sm text-content-secondary\">\n This will replace the linked dashboard's code with the script below.\n </p>\n <p class=\"mt-1 text-xs text-gray-600 break-all\" v-if=\"targetDashboardId\">\n Dashboard ID: {{ targetDashboardId }}\n </p>\n <div class=\"my-4 border border-edge bg-page rounded\">\n <pre class=\"p-2 h-[300px] overflow-auto whitespace-pre-wrap text-xs\">{{ overwriteDashboardCode }}</pre>\n </div>\n <div class=\"flex items-center gap-2\">\n <async-button\n @click=\"confirmOverwriteDashboard\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n Confirm Overwrite\n </async-button>\n <button\n class=\"px-2.5 py-1.5 rounded-md text-sm font-semibold text-content-secondary bg-gray-200 hover:bg-gray-300\"\n @click=\"showOverwriteDashboardConfirmationModal = false\">\n Cancel\n </button>\n </div>\n <div v-if=\"overwriteError\" class=\"rounded-md bg-red-50 p-4 mt-3\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">Error</h3>\n <div class=\"mt-2 text-sm text-red-700\">\n {{overwriteError}}\n </div>\n </div>\n </div>\n </div>\n </div>\n </template>\n </modal>\n</div>\n";
|
|
50818
50966
|
|
|
50819
50967
|
/***/ },
|
|
50820
50968
|
|
|
@@ -50825,7 +50973,7 @@ module.exports = "<div class=\"chat-message-script relative border rounded bg-su
|
|
|
50825
50973
|
(module) {
|
|
50826
50974
|
|
|
50827
50975
|
"use strict";
|
|
50828
|
-
module.exports = "<div class=\"relative flex items-start\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-
|
|
50976
|
+
module.exports = "<div class=\"relative flex items-start\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-full\"\n :class=\"{'text-right': message.role === 'user'}\">\n\n <div v-if=\"message.toolCalls && message.toolCalls.length\" class=\"mb-2 text-xs text-gray-500 dark:text-gray-400\">\n <div\n v-for=\"(tc, i) in message.toolCalls\"\n :key=\"i\"\n class=\"flex items-center gap-1.5 py-0.5 font-mono\">\n <svg :class=\"['w-3.5 h-3.5 shrink-0', tc.status === 'running' ? 'animate-spin text-gray-400 dark:text-gray-500' : 'text-gray-500 dark:text-gray-400']\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21.75 6.75a4.5 4.5 0 0 1-4.884 4.484c-1.076-.091-2.264.071-2.95.904l-7.152 8.684a2.548 2.548 0 1 1-3.586-3.586l8.684-7.152c.833-.686.995-1.874.904-2.95a4.5 4.5 0 0 1 6.336-4.486l-3.276 3.276a3.004 3.004 0 0 0 2.25 2.25l3.276-3.276c.256.565.398 1.192.398 1.852Z\" /><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.867 19.125h.008v.008h-.008v-.008Z\" /></svg>\n <span>{{ tc.toolName }}</span>\n <span v-if=\"tc.toolName !== 'typeCheck'\" class=\"text-gray-400 dark:text-gray-500\">{{ formatToolInput(tc.input) }}</span>\n </div>\n </div>\n\n <div class=\"text-sm text-content rounded-md inline-block relative\" :class=\"styleForMessage\">\n <div v-for=\"part in contentSplitByScripts\">\n <div v-if=\"part.type === 'text'\" v-html=\"marked(part.content)\">\n </div>\n <div v-else-if=\"part.type === 'code'\">\n <chat-message-script\n :message=\"message\"\n :script=\"part.content\"\n :language=\"part.language\"\n :target-dashboard-id=\"targetDashboardId\"\n @copyMessage=\"copyMessage\"></chat-message-script>\n </div>\n </div>\n </div>\n </div>\n</div>\n";
|
|
50829
50977
|
|
|
50830
50978
|
/***/ },
|
|
50831
50979
|
|
|
@@ -50836,7 +50984,7 @@ module.exports = "<div class=\"relative flex items-start\" :class=\"{'justify-en
|
|
|
50836
50984
|
(module) {
|
|
50837
50985
|
|
|
50838
50986
|
"use strict";
|
|
50839
|
-
module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <button\n type=\"button\"\n class=\"fixed top-[65px] left-0 cursor-pointer bg-muted rounded-r-md p-1\"\n :class=\"hideSidebar === true ? 'z-[10001]' : hideSidebar === false ? 'z-10' : 'z-30 lg:hidden'\"\n @click=\"hideSidebar = hideSidebar === false ? true : false\"\n aria-label=\"Toggle chat history\"\n title=\"Toggle chat history\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5 text-content-tertiary\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <!-- Sidebar: Chat Threads -->\n <aside\n class=\"bg-page border-r overflow-hidden h-full transition-all duration-300 ease-in-out z-20 w-64 fixed lg:relative shrink-0 flex flex-col\"\n :class=\"hideSidebar === false ? 'translate-x-0' : hideSidebar === true ? '-translate-x-full lg:translate-x-0 lg:!w-0 lg:!border-r-0' : '-translate-x-full lg:translate-x-0'\"\n style=\"z-index: 1000\">\n <!-- Search + New Thread -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative flex items-center gap-2\">\n <div class=\"relative flex-1\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"threadSearch\"\n type=\"text\"\n placeholder=\"Search threads...\"\n @keydown.esc=\"threadSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n <async-button\n @click=\"createNewThread\"\n class=\"shrink-0 rounded-md border border-edge bg-surface p-1.5 text-content-tertiary hover:bg-muted hover:text-content-secondary\"\n title=\"New thread\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n </async-button>\n </div>\n </div>\n <!-- Thread list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Threads</div>\n <div v-if=\"status === 'loaded' && filteredThreads.length === 0\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n <template v-if=\"threadSearch.trim()\">No threads match \"{{threadSearch}}\"</template>\n <template v-else>No threads yet</template>\n </div>\n <ul role=\"list\">\n <li\n v-for=\"thread in filteredThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"rounded-md py-2 px-2 cursor-pointer mb-0.5\"\n :class=\"thread._id === chatThreadId ? 'bg-gray-200 text-content' : 'hover:bg-muted text-content-secondary'\"\n >\n <div class=\"text-sm font-medium truncate\">{{ thread.title || 'Untitled Thread' }}</div>\n <div class=\"text-xs text-gray-400 mt-0.5\">{{ formatThreadDate(thread.updatedAt || thread.createdAt) }}</div>\n </li>\n </ul>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"hasWorkspace ? toggleShareThread() : (showProUpgradeModal = true)\"\n class=\"rounded p-1.5\"\n :class=\"hasWorkspace && chatThreadId ? 'text-gray-400 hover:text-gray-600 hover:bg-muted' : !hasWorkspace ? 'text-gray-400 hover:text-gray-600 hover:bg-muted' : 'text-gray-300 cursor-not-allowed'\"\n :disabled=\"hasWorkspace && !chatThreadId\"\n aria-label=\"Share thread with workspace\"\n :title=\"'Share thread with workspace' + (!hasWorkspace ? ' (requires a pro workspace)' : !chatThreadId ? ': Open a thread first!' : '')\"\n >\n <svg v-if=\"hasWorkspace\" xmlns=\"http://www.w3.org/2000/svg\" class=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7a2.48 2.48 0 0 0 0-1.39l7.02-4.11a2.5 2.5 0 1 0-.87-1.37L8.04 9.94a2.5 2.5 0 1 0 0 4.12l7.12 4.16a2.5 2.5 0 1 0 .84-1.34l-7.05-4.12c-.04-.02-.08-.05-.11-.07a2.48 2.48 0 0 0 0-1.39c.03-.02.07-.04.11-.07l7.11-4.16c.52.47 1.2.76 1.94.76a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0-1.94.94L7.97 8.43a2.5 2.5 0 1 0 0 7.14l9.09 5.3c.52-.47 1.2-.76 1.94-.76a2.5 2.5 0 1 0 0-5z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M12 1a5 5 0 00-5 5v3H6a2 2 0 00-2 2v9a2 2 0 002 2h12a2 2 0 002-2v-9a2 2 0 00-2-2h-1V6a5 5 0 00-5-5zm-3 8V6a3 3 0 016 0v3H9zm9 2v9H6v-9h12z\"/></svg>\n </button>\n </div>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col bg-slate-50\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <div v-if=\"chatMessages?.length === 0\">\n <div class=\"flex items-center w-full h-full justify-center py-3 mb-4\">\n <p class=\"mx-4 font-bold text-content\">\n Ask Mongoose Studio to analyze your data or generate a script\n </p>\n </div>\n </div>\n <ul role=\"list\" class=\"space-y-4\" v-else>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\" :target-dashboard-id=\"currentThread?.dashboardId\"></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 items-end justify-end\">\n <textarea\n v-model=\"newMessage\"\n :placeholder=\"sendingMessage ? 'Sending...' : 'Ask about your data, generate a query, or build a chart…'\"\n class=\"flex-1 border rounded px-4 py-2 resize-none overflow-y-auto shadow-sm\"\n :disabled=\"sendingMessage\"\n rows=\"2\"\n ref=\"messageInput\"\n @input=\"adjustTextareaHeight\"\n @keydown.enter.exact.prevent=\"handleEnter\"\n ></textarea>\n <button class=\"bg-primary hover:bg-primary-hover text-white px-4 h-[42px] 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\n <pro-upgrade-modal\n :show=\"showProUpgradeModal\"\n feature-description=\"Sharing threads lets you collaborate with your team by sharing chat threads within your workspace.\"\n @close=\"showProUpgradeModal = false\"\n ></pro-upgrade-modal>\n</div>\n";
|
|
50987
|
+
module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <button\n type=\"button\"\n class=\"fixed top-[65px] left-0 cursor-pointer bg-muted rounded-r-md p-1\"\n :class=\"hideSidebar === true ? 'z-[10001]' : hideSidebar === false ? 'z-10' : 'z-30 lg:hidden'\"\n @click=\"hideSidebar = hideSidebar === false ? true : false\"\n aria-label=\"Toggle chat history\"\n title=\"Toggle chat history\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5 text-content-tertiary\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <!-- Sidebar: Chat Threads -->\n <aside\n class=\"bg-page border-r overflow-hidden h-full transition-all duration-300 ease-in-out z-20 w-64 fixed lg:relative shrink-0 flex flex-col\"\n :class=\"hideSidebar === false ? 'translate-x-0' : hideSidebar === true ? '-translate-x-full lg:translate-x-0 lg:!w-0 lg:!border-r-0' : '-translate-x-full lg:translate-x-0'\"\n style=\"z-index: 1000\">\n <!-- Search + New Thread -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative flex items-center gap-2\">\n <div class=\"relative flex-1\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"threadSearch\"\n type=\"text\"\n placeholder=\"Search threads...\"\n @keydown.esc=\"threadSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n <async-button\n @click=\"createNewThread\"\n class=\"shrink-0 rounded-md border border-edge bg-surface p-1.5 text-content-tertiary hover:bg-muted hover:text-content-secondary\"\n title=\"New thread\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" />\n </svg>\n </async-button>\n </div>\n </div>\n <!-- Thread list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Threads</div>\n <div v-if=\"status === 'loaded' && filteredThreads.length === 0\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n <template v-if=\"threadSearch.trim()\">No threads match \"{{threadSearch}}\"</template>\n <template v-else>No threads yet</template>\n </div>\n <ul role=\"list\">\n <li\n v-for=\"thread in filteredThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"rounded-md py-2 px-2 cursor-pointer mb-0.5\"\n :class=\"thread._id === chatThreadId ? 'bg-gray-200 text-content' : 'hover:bg-muted text-content-secondary'\"\n >\n <div class=\"text-sm font-medium truncate\">{{ thread.title || 'Untitled Thread' }}</div>\n <div class=\"text-xs text-gray-400 mt-0.5\">{{ formatThreadDate(thread.updatedAt || thread.createdAt) }}</div>\n </li>\n </ul>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"hasWorkspace ? toggleShareThread() : (showProUpgradeModal = true)\"\n class=\"rounded p-1.5\"\n :class=\"hasWorkspace && chatThreadId ? 'text-gray-400 hover:text-gray-600 hover:bg-muted' : !hasWorkspace ? 'text-gray-400 hover:text-gray-600 hover:bg-muted' : 'text-gray-300 cursor-not-allowed'\"\n :disabled=\"hasWorkspace && !chatThreadId\"\n aria-label=\"Share thread with workspace\"\n :title=\"'Share thread with workspace' + (!hasWorkspace ? ' (requires a pro workspace)' : !chatThreadId ? ': Open a thread first!' : '')\"\n >\n <svg v-if=\"hasWorkspace\" xmlns=\"http://www.w3.org/2000/svg\" class=\"w-6 h-6\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7a2.48 2.48 0 0 0 0-1.39l7.02-4.11a2.5 2.5 0 1 0-.87-1.37L8.04 9.94a2.5 2.5 0 1 0 0 4.12l7.12 4.16a2.5 2.5 0 1 0 .84-1.34l-7.05-4.12c-.04-.02-.08-.05-.11-.07a2.48 2.48 0 0 0 0-1.39c.03-.02.07-.04.11-.07l7.11-4.16c.52.47 1.2.76 1.94.76a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0-1.94.94L7.97 8.43a2.5 2.5 0 1 0 0 7.14l9.09 5.3c.52-.47 1.2-.76 1.94-.76a2.5 2.5 0 1 0 0-5z\"/></svg>\n <svg v-else xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M12 1a5 5 0 00-5 5v3H6a2 2 0 00-2 2v9a2 2 0 002 2h12a2 2 0 002-2v-9a2 2 0 00-2-2h-1V6a5 5 0 00-5-5zm-3 8V6a3 3 0 016 0v3H9zm9 2v9H6v-9h12z\"/></svg>\n </button>\n <button\n type=\"button\"\n @click=\"toggleAgentMode\"\n class=\"rounded p-1.5 transition-colors\"\n :class=\"isAgentModeEnabled ? 'text-primary bg-primary/10' : 'text-gray-400 hover:text-gray-600 hover:bg-muted'\"\n :aria-label=\"isAgentModeEnabled ? 'Turn agent mode off' : 'Turn agent mode on'\"\n :aria-pressed=\"isAgentModeEnabled\"\n :title=\"isAgentModeEnabled ? 'Agent mode on' : 'Agent mode off'\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 200 200\"><path d=\"m187 170.9-38.72-13.73-0.55-0.25-11.24-12.18v-9.98c6.3-6.82 6.43-11.03 8.3-23.22 7.34-1.41 10.2-7.7 12.28-18.9 0.97-5.02 2.72-9.88 0.14-13.92-1.38-2.35-3.49-3.08-5.62-3.38 1.65-11.57 5.47-27.07-2.68-42.38-5.47-9.94-14-14.18-21.8-14.92-3.5-9.15-12.32-13.06-27.11-13.06h-1.06c-27.2 0-48.53 17.96-52.18 39.74-2.05 11.38-0.41 20.41 0.74 30.03-2.23 0.19-4.38 1.02-5.84 3.42-2.21 3.83-1.27 8.84 0.06 14.19 2 8.28 2.26 16.18 12.9 18.96 1.47 6.52 0.58 14.07 8.3 22.84v10.77l-12.54 12.83-38.38 12.85v24.18h57.31c-3.11-14.37-6.53-23.75-5.45-42.72l0.44-0.34c5.71 9.04 16.02 15.97 29.22 25.91l-12.68 17.15h38.07l-13.16-17.2c11.44-9.29 22.31-16.55 29.2-25.38 4.68 9.53-1.48 26.7-4.72 42.58h56.77v-23.89zm-49.56-49.09c-1.43 5.43-2.53 6.16-9.69 14.68l-11.68 13.11c-3.48 3.27-4.8 3.27-11.11 3.27h-10.39c-6.25 0-7.45-0.78-11.01-4.46-6.78-7.7-11.76-13.37-15.09-17.32-5.39-6.33-5.85-7.2-7.16-18.89-0.73-4.86-3.02-14.25-2.94-14.91 3.94 3.43 13.59 3.35 16.89 3.35 12.76 0 15.79-2.74 19.92-17.12 0.68-2.98 1.71-3.53 4-3.53 2.04 0 3.04 0.98 3.86 3.71 3.9 13.69 5.2 16.52 16.15 16.76h2.99c8.1 0 15.01-1.52 18.58-2.93-0.5 5.06-2.28 16.7-3.32 24.28zm4.72-39.02c-1.97 10.98-2.94 12.3-17.69 12.91-9.05 0.38-11.35-0.71-14.17-8.69-3.69-11.25-2.17-13 5.55-13.83 6.36-0.83 11.74-0.79 15.92-0.79 10.01 0 12.11 0.27 10.39 10.4zm-84.38-32c0-11.99 9.26-21.63 15.54-23.52 4.46-1.14 7.99 3.61 15.25 5.74 5.06 1.54 10.71 1.32 11.84 1.32 11.49 0 16.71-2.62 21.55-6.91 1.66-1.28 3.22-1.57 4.86-0.67 10.89 6.36 15.34 16.28 14.74 26.07-0.36 5.5-2.18 9.03-1.38 12.23l1.14 3.62c-3.83-0.82-6.2-0.92-10.69-0.92-9.44 0-17.61 1.24-22.14 2.5-3.66 1.24-5.2 1.44-8.35 1.44-2.98 0-4.92-0.2-7.56-1.44-4.97-1.54-14.49-2.5-21.47-2.5-3.69 0-7 0.01-10.9 0.62l-1.84 0.3 0.42-3.07c0.82-3.01-1.01-7.56-1.01-14.81z\"/><path d=\"m116.6 125.4-12.18-2.58c-2.29-0.68-3.7 0.76-5.4 0.76-1.66 0-2.79-1.35-5.4-0.66l-10.88 2.36c-1.35 0.12-1.55 1.44-0.79 3.32 0.38 1.02 1.26 0.7 3.07 0.36 3.25-0.46 4.65-0.84 8.11-1.04 1.85-0.17 2.59 0.41 5.06 0.41h1.14c1.72 0 2.62-0.55 4.15-0.31 3.81 0.31 5.64 0.72 11.64 1.22 2.08 0.38 2.4-1.15 2.21-2.52-0.07-0.65-0.24-1.1-0.73-1.32z\"/><path d=\"m94.08 133.5c-1.96 0-2.49 1.23-2.4 2.39 0.06 1.38 0.93 2.27 2.57 2.27h10.06c2.13 0 2.7-1.25 2.7-2.56 0-1.13-0.65-2.1-2.53-2.1h-10.4z\"/><path d=\"m91.31 106.6c-2.13 0-2.51 3.32-1.24 4.55 1.11 1.08 7.39 3.76 9.34 3.76s8.38-3.24 9.4-3.87c1.9-1.2 0.85-4.82-1.7-4.44-1.84 0.3-6.01 3.39-7.96 3.01-1.53-0.32-6.08-3.01-7.84-3.01z\"/><path d=\"m85.62 73.71c-5.3-1.1-10.53-1.15-14.51-1.15-10.96 0-14.08-0.44-14.33 5.26-0.47 11.15 1.82 15.96 6.69 17.19 4.7 1.26 6.84 1.08 11.71 1.08 8.88 0 10.9-1.18 14.23-10.67 2.38-6.81 1.87-10.59-3.79-11.71z\"/><path d=\"m114.5 73.51c-7.72 0.83-7.35 2.71-6.39 9.73 1.78 7.47 3.64 11.94 10.97 12.49 3.07 0.14 4.97-0.05 8-0.32 10.72-0.96 12.6-2.48 14.45-12.22 1.88-10.29-0.54-10.77-9.79-10.77-4.18 0-10.45 0.26-17.24 1.09z\"/></svg>\n </button>\n </div>\n </aside>\n\n <div class=\"flex-1 min-w-0 flex\">\n <!-- Main Chat Area -->\n <main class=\"flex-1 min-w-0 flex flex-col bg-slate-50\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <div v-if=\"chatMessages?.length === 0\">\n <div class=\"flex items-center w-full h-full justify-center py-3 mb-4\">\n <p class=\"mx-4 font-bold text-content\">\n Ask Mongoose Studio to analyze your data or generate a script\n </p>\n </div>\n </div>\n <ul role=\"list\" class=\"space-y-4\" v-else>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\" :target-dashboard-id=\"currentThread?.dashboardId\"></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 items-end justify-end\">\n <textarea\n v-model=\"newMessage\"\n :placeholder=\"sendingMessage ? 'Sending...' : 'Ask about your data, generate a query, or build a chart…'\"\n class=\"flex-1 border rounded px-4 py-2 resize-none overflow-y-auto shadow-sm\"\n :disabled=\"sendingMessage\"\n rows=\"2\"\n ref=\"messageInput\"\n @input=\"adjustTextareaHeight\"\n @keydown.enter.exact.prevent=\"handleEnter\"\n ></textarea>\n <button class=\"bg-primary hover:bg-primary-hover text-white px-4 h-[42px] 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\n <aside\n v-if=\"isAgentModeEnabled\"\n class=\"hidden lg:flex shrink-0 border-l border-edge bg-page transition-all duration-300 ease-in-out overflow-hidden\"\n :class=\"showAgentSidebar ? 'w-80' : 'w-0 border-l-0'\"\n >\n <div v-if=\"showAgentSidebar\" class=\"flex h-full w-80 flex-col\">\n <div class=\"flex items-center justify-between border-b border-edge px-4 py-3\">\n <div>\n <h2 class=\"text-sm font-semibold text-content\">Agent Mode</h2>\n <p class=\"mt-1 text-xs text-content-tertiary\">Agent mode lets Mongoose Studio inspect your data and validate scripts before it responds.</p>\n </div>\n <button\n type=\"button\"\n @click=\"closeAgentSidebar\"\n class=\"rounded p-1.5 text-gray-400 hover:bg-muted hover:text-gray-600\"\n title=\"Hide agent sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <div class=\"flex-1 overflow-y-auto px-4 py-4\">\n <div class=\"mb-3 text-xs font-semibold uppercase tracking-wider text-gray-400\">Available Tools</div>\n <ul role=\"list\" class=\"space-y-3\">\n <li v-for=\"tool in agentTools\" :key=\"tool.name\" class=\"rounded-md border border-edge bg-surface px-3 py-3\">\n <div class=\"text-sm font-medium text-content\">{{ tool.name }}</div>\n <div class=\"mt-1 text-sm text-content-secondary\">{{ tool.description }}</div>\n </li>\n </ul>\n </div>\n </div>\n </aside>\n </div>\n\n <pro-upgrade-modal\n :show=\"showProUpgradeModal\"\n feature-description=\"Sharing threads lets you collaborate with your team by sharing chat threads within your workspace.\"\n @close=\"showProUpgradeModal = false\"\n ></pro-upgrade-modal>\n</div>\n";
|
|
50840
50988
|
|
|
50841
50989
|
/***/ },
|
|
50842
50990
|
|
|
@@ -62887,7 +63035,7 @@ var src_default = VueToastificationPlugin;
|
|
|
62887
63035
|
(module) {
|
|
62888
63036
|
|
|
62889
63037
|
"use strict";
|
|
62890
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.
|
|
63038
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.4.0","description":"A Mongoose-native MongoDB UI with schema-aware autocomplete, AI-assisted queries, and dashboards that understand your models - not just your data.","homepage":"https://mongoosestudio.app/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/anthropic":"2.x","@ai-sdk/google":"2.x","@ai-sdk/openai":"2.x","ace-builds":"^1.43.6","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.0","marked":"15.0.12","node-inspect-extracted":"3.x","regexp.escape":"^2.0.1","tailwindcss":"3.4.0","time-commando":"1.0.1","typescript":"^6.0.2","vue":"3.x","vue-toastification":"^2.0.0-rc.5","webpack":"5.x","xss":"^1.0.15"},"peerDependencies":{"mongoose":"7.x || 8.x || ^9.0.0"},"optionalPeerDependencies":{"@mongoosejs/task":"0.5.x || 0.6.x"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","express":"4.x","mocha":"10.2.0","mongodb-memory-server":"^11.0.1","mongoose":"9.x","sinon":"^21.0.1"},"scripts":{"lint":"eslint .","seed":"node seed/index.js","start":"node ./local.js","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js","test:frontend":"mocha test/frontend/*.test.js"}}');
|
|
62891
63039
|
|
|
62892
63040
|
/***/ }
|
|
62893
63041
|
|
package/frontend/public/tw.css
CHANGED
|
@@ -1072,6 +1072,10 @@ video {
|
|
|
1072
1072
|
height: 0.75rem;
|
|
1073
1073
|
}
|
|
1074
1074
|
|
|
1075
|
+
.h-3\.5 {
|
|
1076
|
+
height: 0.875rem;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1075
1079
|
.h-4 {
|
|
1076
1080
|
height: 1rem;
|
|
1077
1081
|
}
|
|
@@ -1212,6 +1216,10 @@ video {
|
|
|
1212
1216
|
width: 0.75rem;
|
|
1213
1217
|
}
|
|
1214
1218
|
|
|
1219
|
+
.w-3\.5 {
|
|
1220
|
+
width: 0.875rem;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1215
1223
|
.w-36 {
|
|
1216
1224
|
width: 9rem;
|
|
1217
1225
|
}
|
|
@@ -1256,6 +1264,10 @@ video {
|
|
|
1256
1264
|
width: 2rem;
|
|
1257
1265
|
}
|
|
1258
1266
|
|
|
1267
|
+
.w-80 {
|
|
1268
|
+
width: 20rem;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1259
1271
|
.w-\[240px\] {
|
|
1260
1272
|
width: 240px;
|
|
1261
1273
|
}
|
|
@@ -1320,14 +1332,14 @@ video {
|
|
|
1320
1332
|
max-width: 280px;
|
|
1321
1333
|
}
|
|
1322
1334
|
|
|
1323
|
-
.max-w-\[calc\(100vw-3rem\)\] {
|
|
1324
|
-
max-width: calc(100vw - 3rem);
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
1335
|
.max-w-\[calc\(100vw-4rem\)\] {
|
|
1328
1336
|
max-width: calc(100vw - 4rem);
|
|
1329
1337
|
}
|
|
1330
1338
|
|
|
1339
|
+
.max-w-full {
|
|
1340
|
+
max-width: 100%;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1331
1343
|
.max-w-lg {
|
|
1332
1344
|
max-width: 32rem;
|
|
1333
1345
|
}
|
|
@@ -1774,6 +1786,10 @@ video {
|
|
|
1774
1786
|
border-bottom-width: 4px;
|
|
1775
1787
|
}
|
|
1776
1788
|
|
|
1789
|
+
.border-l {
|
|
1790
|
+
border-left-width: 1px;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1777
1793
|
.border-l-0 {
|
|
1778
1794
|
border-left-width: 0px;
|
|
1779
1795
|
}
|
|
@@ -3757,6 +3773,10 @@ video {
|
|
|
3757
3773
|
margin-right: -2rem;
|
|
3758
3774
|
}
|
|
3759
3775
|
|
|
3776
|
+
.lg\:flex {
|
|
3777
|
+
display: flex;
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3760
3780
|
.lg\:hidden {
|
|
3761
3781
|
display: none;
|
|
3762
3782
|
}
|
|
@@ -3773,10 +3793,6 @@ video {
|
|
|
3773
3793
|
width: 16rem;
|
|
3774
3794
|
}
|
|
3775
3795
|
|
|
3776
|
-
.lg\:max-w-\[calc\(100vw-15rem\)\] {
|
|
3777
|
-
max-width: calc(100vw - 15rem);
|
|
3778
|
-
}
|
|
3779
|
-
|
|
3780
3796
|
.lg\:max-w-\[calc\(100vw-20rem\)\] {
|
|
3781
3797
|
max-width: calc(100vw - 20rem);
|
|
3782
3798
|
}
|
|
@@ -3813,4 +3829,14 @@ video {
|
|
|
3813
3829
|
|
|
3814
3830
|
:is(:where(.dark) .dark\:bg-shark-800\/80) {
|
|
3815
3831
|
background-color: rgb(33 37 41 / 0.8);
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
:is(:where(.dark) .dark\:text-gray-400) {
|
|
3835
|
+
--tw-text-opacity: 1;
|
|
3836
|
+
color: rgb(156 163 175 / var(--tw-text-opacity));
|
|
3837
|
+
}
|
|
3838
|
+
|
|
3839
|
+
:is(:where(.dark) .dark\:text-gray-500) {
|
|
3840
|
+
--tw-text-opacity: 1;
|
|
3841
|
+
color: rgb(107 114 128 / var(--tw-text-opacity));
|
|
3816
3842
|
}
|
package/frontend/src/api.js
CHANGED
|
@@ -62,6 +62,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
62
62
|
shareChatThread(params) {
|
|
63
63
|
return client.post('', { action: 'ChatThread.shareChatThread', ...params }).then(res => res.data);
|
|
64
64
|
},
|
|
65
|
+
toggleAgentMode(params) {
|
|
66
|
+
return client.post('', { action: 'ChatThread.toggleAgentMode', ...params }).then(res => res.data);
|
|
67
|
+
},
|
|
65
68
|
streamChatMessage: async function* streamChatMessage(params) {
|
|
66
69
|
// Don't stream on Next.js or Netlify for now.
|
|
67
70
|
const data = await client.post('', { action: 'ChatThread.createChatMessage', ...params }).then(res => res.data);
|
|
@@ -238,6 +241,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
238
241
|
shareChatThread: function shareChatThread(params) {
|
|
239
242
|
return client.post('/ChatThread/shareChatThread', params).then(res => res.data);
|
|
240
243
|
},
|
|
244
|
+
toggleAgentMode: function toggleAgentMode(params) {
|
|
245
|
+
return client.post('/ChatThread/toggleAgentMode', params).then(res => res.data);
|
|
246
|
+
},
|
|
241
247
|
streamChatMessage: async function* streamChatMessage(params) {
|
|
242
248
|
const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
|
|
243
249
|
const url = window.MONGOOSE_STUDIO_CONFIG.baseURL + '/ChatThread/streamChatMessage?' + new URLSearchParams(params).toString();
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
<div class="relative flex items-start" :class="{'justify-end': message.role === 'user'}">
|
|
2
2
|
<div
|
|
3
|
-
class="min-w-0 max-w-
|
|
3
|
+
class="min-w-0 max-w-full"
|
|
4
4
|
:class="{'text-right': message.role === 'user'}">
|
|
5
5
|
|
|
6
|
+
<div v-if="message.toolCalls && message.toolCalls.length" class="mb-2 text-xs text-gray-500 dark:text-gray-400">
|
|
7
|
+
<div
|
|
8
|
+
v-for="(tc, i) in message.toolCalls"
|
|
9
|
+
:key="i"
|
|
10
|
+
class="flex items-center gap-1.5 py-0.5 font-mono">
|
|
11
|
+
<svg :class="['w-3.5 h-3.5 shrink-0', tc.status === 'running' ? 'animate-spin text-gray-400 dark:text-gray-500' : 'text-gray-500 dark:text-gray-400']" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75a4.5 4.5 0 0 1-4.884 4.484c-1.076-.091-2.264.071-2.95.904l-7.152 8.684a2.548 2.548 0 1 1-3.586-3.586l8.684-7.152c.833-.686.995-1.874.904-2.95a4.5 4.5 0 0 1 6.336-4.486l-3.276 3.276a3.004 3.004 0 0 0 2.25 2.25l3.276-3.276c.256.565.398 1.192.398 1.852Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M4.867 19.125h.008v.008h-.008v-.008Z" /></svg>
|
|
12
|
+
<span>{{ tc.toolName }}</span>
|
|
13
|
+
<span v-if="tc.toolName !== 'typeCheck'" class="text-gray-400 dark:text-gray-500">{{ formatToolInput(tc.input) }}</span>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
6
17
|
<div class="text-sm text-content rounded-md inline-block relative" :class="styleForMessage">
|
|
7
18
|
<div v-for="part in contentSplitByScripts">
|
|
8
19
|
<div v-if="part.type === 'text'" v-html="marked(part.content)">
|
|
@@ -54,6 +54,14 @@ module.exports = app => app.component('chat-message', {
|
|
|
54
54
|
marked(text) {
|
|
55
55
|
return marked(text);
|
|
56
56
|
},
|
|
57
|
+
formatToolInput(input) {
|
|
58
|
+
if (!input) return '';
|
|
59
|
+
const parts = [];
|
|
60
|
+
if (input.modelName) parts.push(input.modelName);
|
|
61
|
+
if (input.filter && Object.keys(input.filter).length) parts.push(JSON.stringify(input.filter));
|
|
62
|
+
if (input.limit && input.limit !== 10) parts.push('limit=' + input.limit);
|
|
63
|
+
return parts.length ? '(' + parts.join(', ') + ')' : '';
|
|
64
|
+
},
|
|
57
65
|
async executeScript(message, script) {
|
|
58
66
|
const { chatMessage } = await api.ChatMessage.executeScript({
|
|
59
67
|
chatMessageId: message._id,
|