melchat 0.0.1 → 0.0.2
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/LICENSE +15 -17
- package/README.md +1 -1
- package/dist/index.html +79 -9
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 19 November 2007
|
|
2
3
|
|
|
3
|
-
Copyright (
|
|
4
|
+
Copyright (C) 2024 Melvin Carvalho
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU Affero General Public License as published
|
|
8
|
+
by the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU Affero General Public License for more details.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
16
|
+
You should have received a copy of the GNU Affero General Public License
|
|
17
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
Full license text: https://www.gnu.org/licenses/agpl-3.0.txt
|
package/README.md
CHANGED
package/dist/index.html
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
-
<title>
|
|
8
|
+
<title>MelChat - 100+ AI Models</title>
|
|
9
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💬</text></svg>">
|
|
9
10
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css">
|
|
10
11
|
<style>
|
|
11
12
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
@@ -433,6 +434,38 @@
|
|
|
433
434
|
opacity: 0.5;
|
|
434
435
|
cursor: not-allowed;
|
|
435
436
|
}
|
|
437
|
+
.stop-btn {
|
|
438
|
+
padding: 0.75rem 1.5rem;
|
|
439
|
+
background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
|
|
440
|
+
color: white;
|
|
441
|
+
border: none;
|
|
442
|
+
border-radius: 12px;
|
|
443
|
+
font-size: 1rem;
|
|
444
|
+
cursor: pointer;
|
|
445
|
+
transition: transform 0.2s;
|
|
446
|
+
}
|
|
447
|
+
.stop-btn:hover {
|
|
448
|
+
transform: translateY(-2px);
|
|
449
|
+
}
|
|
450
|
+
.copy-msg-btn {
|
|
451
|
+
background: rgba(102, 126, 234, 0.1);
|
|
452
|
+
border: 1px solid rgba(102, 126, 234, 0.3);
|
|
453
|
+
border-radius: 4px;
|
|
454
|
+
padding: 0.25rem 0.5rem;
|
|
455
|
+
font-size: 0.75rem;
|
|
456
|
+
cursor: pointer;
|
|
457
|
+
transition: all 0.2s;
|
|
458
|
+
margin-top: 0.5rem;
|
|
459
|
+
display: inline-block;
|
|
460
|
+
}
|
|
461
|
+
.copy-msg-btn:hover {
|
|
462
|
+
background: rgba(102, 126, 234, 0.2);
|
|
463
|
+
}
|
|
464
|
+
.copy-msg-btn.copied {
|
|
465
|
+
background: #4caf50;
|
|
466
|
+
color: white;
|
|
467
|
+
border-color: #4caf50;
|
|
468
|
+
}
|
|
436
469
|
.settings-overlay {
|
|
437
470
|
position: fixed;
|
|
438
471
|
top: 0;
|
|
@@ -833,6 +866,7 @@
|
|
|
833
866
|
<div class="input-wrapper">
|
|
834
867
|
<textarea id="input" placeholder="Type your message... (Enter to send, Shift+Enter for new line)" rows="1"></textarea>
|
|
835
868
|
<button class="send-btn" id="sendBtn" onclick="app.sendMessage()">Send</button>
|
|
869
|
+
<button class="stop-btn hidden" id="stopBtn" onclick="app.stopGeneration()">Stop</button>
|
|
836
870
|
</div>
|
|
837
871
|
</div>
|
|
838
872
|
</div>
|
|
@@ -947,6 +981,7 @@
|
|
|
947
981
|
streamingElement: null,
|
|
948
982
|
streamThrottleTimeout: null,
|
|
949
983
|
pendingStreamUpdate: false,
|
|
984
|
+
abortController: null,
|
|
950
985
|
|
|
951
986
|
init() {
|
|
952
987
|
const saved = localStorage.getItem('conversations');
|
|
@@ -989,13 +1024,20 @@
|
|
|
989
1024
|
this.render(true); // Initial full render
|
|
990
1025
|
this.updateTokenCounter();
|
|
991
1026
|
|
|
992
|
-
document.getElementById('input')
|
|
1027
|
+
const inputEl = document.getElementById('input');
|
|
1028
|
+
inputEl.addEventListener('keypress', (e) => {
|
|
993
1029
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
994
1030
|
e.preventDefault();
|
|
995
1031
|
this.sendMessage();
|
|
996
1032
|
}
|
|
997
1033
|
});
|
|
998
1034
|
|
|
1035
|
+
// Auto-resize textarea
|
|
1036
|
+
inputEl.addEventListener('input', () => {
|
|
1037
|
+
inputEl.style.height = 'auto';
|
|
1038
|
+
inputEl.style.height = Math.min(inputEl.scrollHeight, 150) + 'px';
|
|
1039
|
+
});
|
|
1040
|
+
|
|
999
1041
|
document.getElementById('modelSelect').addEventListener('change', (e) => {
|
|
1000
1042
|
this.model = e.target.value;
|
|
1001
1043
|
localStorage.setItem('current_model', this.model);
|
|
@@ -1260,6 +1302,7 @@
|
|
|
1260
1302
|
} else {
|
|
1261
1303
|
actions = `
|
|
1262
1304
|
<div class="message-actions">
|
|
1305
|
+
<button class="message-action-btn" onclick="app.copyMessage(app.getCurrentConversation().messages[${index}].content)">📋 Copy</button>
|
|
1263
1306
|
<button class="message-action-btn" onclick="app.regenerateMessage(${index})">🔄 Regenerate</button>
|
|
1264
1307
|
<button class="message-action-btn" onclick="app.deleteMessage(${index})">🗑️</button>
|
|
1265
1308
|
</div>
|
|
@@ -1380,6 +1423,25 @@
|
|
|
1380
1423
|
this.pendingStreamUpdate = false;
|
|
1381
1424
|
},
|
|
1382
1425
|
|
|
1426
|
+
stopGeneration() {
|
|
1427
|
+
if (this.abortController) {
|
|
1428
|
+
this.abortController.abort();
|
|
1429
|
+
this.abortController = null;
|
|
1430
|
+
this.showNotification('Generation stopped');
|
|
1431
|
+
}
|
|
1432
|
+
},
|
|
1433
|
+
|
|
1434
|
+
showStopButton(show) {
|
|
1435
|
+
document.getElementById('sendBtn').classList.toggle('hidden', show);
|
|
1436
|
+
document.getElementById('stopBtn').classList.toggle('hidden', !show);
|
|
1437
|
+
},
|
|
1438
|
+
|
|
1439
|
+
copyMessage(content) {
|
|
1440
|
+
navigator.clipboard.writeText(content).then(() => {
|
|
1441
|
+
this.showNotification('Message copied!');
|
|
1442
|
+
});
|
|
1443
|
+
},
|
|
1444
|
+
|
|
1383
1445
|
render(fullRender = false) {
|
|
1384
1446
|
const conv = this.getCurrentConversation();
|
|
1385
1447
|
if (!conv) return;
|
|
@@ -1699,7 +1761,7 @@
|
|
|
1699
1761
|
this.saveConversations();
|
|
1700
1762
|
} finally {
|
|
1701
1763
|
this.isLoading = false;
|
|
1702
|
-
|
|
1764
|
+
this.showStopButton(false);
|
|
1703
1765
|
}
|
|
1704
1766
|
},
|
|
1705
1767
|
|
|
@@ -1782,7 +1844,7 @@
|
|
|
1782
1844
|
this.saveConversations();
|
|
1783
1845
|
} finally {
|
|
1784
1846
|
this.isLoading = false;
|
|
1785
|
-
|
|
1847
|
+
this.showStopButton(false);
|
|
1786
1848
|
}
|
|
1787
1849
|
},
|
|
1788
1850
|
|
|
@@ -1910,7 +1972,7 @@
|
|
|
1910
1972
|
this.saveConversations();
|
|
1911
1973
|
} finally {
|
|
1912
1974
|
this.isLoading = false;
|
|
1913
|
-
|
|
1975
|
+
this.showStopButton(false);
|
|
1914
1976
|
}
|
|
1915
1977
|
},
|
|
1916
1978
|
|
|
@@ -1955,7 +2017,7 @@
|
|
|
1955
2017
|
this.updateTokenCounter();
|
|
1956
2018
|
|
|
1957
2019
|
this.isLoading = true;
|
|
1958
|
-
|
|
2020
|
+
this.showStopButton(true);
|
|
1959
2021
|
|
|
1960
2022
|
// Check if using image/video generation model
|
|
1961
2023
|
const isFluxModel = this.model.startsWith('black-forest-labs/flux');
|
|
@@ -2023,6 +2085,12 @@
|
|
|
2023
2085
|
model = this.customModel;
|
|
2024
2086
|
}
|
|
2025
2087
|
|
|
2088
|
+
// Show thinking indicator
|
|
2089
|
+
this.updateStreamingMessage('*Thinking...*');
|
|
2090
|
+
|
|
2091
|
+
// Create abort controller for stop button
|
|
2092
|
+
this.abortController = new AbortController();
|
|
2093
|
+
|
|
2026
2094
|
const response = await fetch(endpoint, {
|
|
2027
2095
|
method: 'POST',
|
|
2028
2096
|
headers: headers,
|
|
@@ -2030,7 +2098,8 @@
|
|
|
2030
2098
|
model: model,
|
|
2031
2099
|
messages: apiMessages,
|
|
2032
2100
|
stream: true
|
|
2033
|
-
})
|
|
2101
|
+
}),
|
|
2102
|
+
signal: this.abortController.signal
|
|
2034
2103
|
});
|
|
2035
2104
|
|
|
2036
2105
|
if (!response.ok) {
|
|
@@ -2092,8 +2161,9 @@
|
|
|
2092
2161
|
this.saveConversations();
|
|
2093
2162
|
} finally {
|
|
2094
2163
|
this.isLoading = false;
|
|
2095
|
-
|
|
2096
|
-
this.
|
|
2164
|
+
this.abortController = null;
|
|
2165
|
+
this.showStopButton(false);
|
|
2166
|
+
this.finalizeStreamingMessage();
|
|
2097
2167
|
}
|
|
2098
2168
|
}
|
|
2099
2169
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "melchat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "100+ AI models in one lightweight chat interface. GPT-4, Claude, Gemini, Llama, Qwen, and more - all in a single 69KB file.",
|
|
5
5
|
"main": "dist/index.html",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"cli"
|
|
35
35
|
],
|
|
36
36
|
"author": "Melvin Carvalho",
|
|
37
|
-
"license": "
|
|
37
|
+
"license": "AGPL-3.0",
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
|
40
40
|
"url": "git+https://github.com/melvincarvalho/melchat.git"
|