agentgui 1.0.131 → 1.0.138
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/CLAUDE.md +46 -0
- package/bin/gmgui.cjs +1 -1
- package/database.js +10 -1
- package/package.json +2 -1
- package/server.js +75 -9
- package/setup-npm-token.sh +68 -0
- package/static/app.js +5 -3
- package/static/index.html +225 -3
- package/static/js/client.js +7 -3
- package/static/js/conversations.js +12 -5
- package/static/js/features.js +17 -17
- package/static/js/streaming-renderer.js +48 -24
- package/static/js/syntax-highlighter.js +1 -1
- package/static/js/voice.js +430 -0
- package/static/styles.css +86 -0
package/static/js/client.js
CHANGED
|
@@ -192,6 +192,7 @@ class AgentGUIClient {
|
|
|
192
192
|
*/
|
|
193
193
|
updateUrlForConversation(conversationId, sessionId) {
|
|
194
194
|
if (!this.isValidId(conversationId)) return;
|
|
195
|
+
if (!this.routerState) return;
|
|
195
196
|
|
|
196
197
|
this.routerState.currentConversationId = conversationId;
|
|
197
198
|
if (sessionId && this.isValidId(sessionId)) {
|
|
@@ -689,7 +690,8 @@ class AgentGUIClient {
|
|
|
689
690
|
</div>
|
|
690
691
|
`;
|
|
691
692
|
} else {
|
|
692
|
-
|
|
693
|
+
const lineCount = code.split('\n').length;
|
|
694
|
+
return `<div class="message-code"><details class="collapsible-code"><summary class="collapsible-code-summary">${this.escapeHtml(language)} - ${lineCount} line${lineCount !== 1 ? 's' : ''}</summary><pre style="margin:0;border-radius:0 0 0.375rem 0.375rem">${this.escapeHtml(code)}</pre></details></div>`;
|
|
693
695
|
}
|
|
694
696
|
}
|
|
695
697
|
|
|
@@ -731,7 +733,8 @@ class AgentGUIClient {
|
|
|
731
733
|
</div>
|
|
732
734
|
`;
|
|
733
735
|
} else {
|
|
734
|
-
|
|
736
|
+
const blkLineCount = block.code.split('\n').length;
|
|
737
|
+
html += `<div class="message-code"><details class="collapsible-code"><summary class="collapsible-code-summary">${this.escapeHtml(block.language || 'code')} - ${blkLineCount} line${blkLineCount !== 1 ? 's' : ''}</summary><pre style="margin:0;border-radius:0 0 0.375rem 0.375rem">${this.escapeHtml(block.code)}</pre></details></div>`;
|
|
735
738
|
}
|
|
736
739
|
} else if (block.type === 'tool_use') {
|
|
737
740
|
let inputHtml = '';
|
|
@@ -1354,7 +1357,8 @@ class AgentGUIClient {
|
|
|
1354
1357
|
</div>
|
|
1355
1358
|
`;
|
|
1356
1359
|
} else {
|
|
1357
|
-
|
|
1360
|
+
const cBlkLineCount = block.code.split('\n').length;
|
|
1361
|
+
contentHtml += `<div class="message-code"><details class="collapsible-code"><summary class="collapsible-code-summary">${this.escapeHtml(block.language || 'code')} - ${cBlkLineCount} line${cBlkLineCount !== 1 ? 's' : ''}</summary><pre style="margin:0;border-radius:0 0 0.375rem 0.375rem">${this.escapeHtml(block.code)}</pre></details></div>`;
|
|
1358
1362
|
}
|
|
1359
1363
|
} else if (block.type === 'tool_use') {
|
|
1360
1364
|
let inputHtml = '';
|
|
@@ -19,7 +19,9 @@ class ConversationManager {
|
|
|
19
19
|
listEl: null,
|
|
20
20
|
breadcrumbEl: null,
|
|
21
21
|
currentPath: '~',
|
|
22
|
-
homePath: '~'
|
|
22
|
+
homePath: '~',
|
|
23
|
+
cwdPath: null,
|
|
24
|
+
homePathReady: null
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
if (!this.listEl) return;
|
|
@@ -55,7 +57,7 @@ class ConversationManager {
|
|
|
55
57
|
if (e.target === this.folderBrowser.modal) this.closeFolderBrowser();
|
|
56
58
|
});
|
|
57
59
|
|
|
58
|
-
this.fetchHomePath();
|
|
60
|
+
this.folderBrowser.homePathReady = this.fetchHomePath();
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
async fetchHomePath() {
|
|
@@ -64,20 +66,25 @@ class ConversationManager {
|
|
|
64
66
|
if (res.ok) {
|
|
65
67
|
const data = await res.json();
|
|
66
68
|
this.folderBrowser.homePath = data.home || '~';
|
|
69
|
+
this.folderBrowser.cwdPath = data.cwd || null;
|
|
67
70
|
}
|
|
68
71
|
} catch (e) {
|
|
69
72
|
console.error('Failed to fetch home path:', e);
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
openFolderBrowser() {
|
|
76
|
+
async openFolderBrowser() {
|
|
74
77
|
if (!this.folderBrowser.modal) {
|
|
75
78
|
this.createNew();
|
|
76
79
|
return;
|
|
77
80
|
}
|
|
78
|
-
this.folderBrowser.
|
|
81
|
+
if (this.folderBrowser.homePathReady) {
|
|
82
|
+
await this.folderBrowser.homePathReady;
|
|
83
|
+
}
|
|
84
|
+
const startPath = this.folderBrowser.cwdPath || '~';
|
|
85
|
+
this.folderBrowser.currentPath = startPath;
|
|
79
86
|
this.folderBrowser.modal.classList.add('visible');
|
|
80
|
-
this.loadFolders(
|
|
87
|
+
this.loadFolders(startPath);
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
closeFolderBrowser() {
|
package/static/js/features.js
CHANGED
|
@@ -195,31 +195,31 @@
|
|
|
195
195
|
var chatArea = document.getElementById('output-scroll');
|
|
196
196
|
var execPanel = document.querySelector('.input-section');
|
|
197
197
|
var fileBrowser = document.getElementById('fileBrowserContainer');
|
|
198
|
-
var
|
|
198
|
+
var fileIframe = document.getElementById('fileBrowserIframe');
|
|
199
|
+
var voiceContainer = document.getElementById('voiceContainer');
|
|
199
200
|
|
|
200
201
|
if (!bar) return;
|
|
201
202
|
|
|
202
|
-
// Update active button
|
|
203
203
|
bar.querySelectorAll('.view-toggle-btn').forEach(function(btn) {
|
|
204
204
|
btn.classList.toggle('active', btn.dataset.view === view);
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
-
if (view === '
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
}
|
|
207
|
+
if (chatArea) chatArea.style.display = view === 'chat' ? '' : 'none';
|
|
208
|
+
if (execPanel) execPanel.style.display = view === 'chat' ? '' : 'none';
|
|
209
|
+
if (fileBrowser) fileBrowser.style.display = view === 'files' ? 'flex' : 'none';
|
|
210
|
+
if (voiceContainer) voiceContainer.style.display = view === 'voice' ? 'flex' : 'none';
|
|
211
|
+
|
|
212
|
+
if (view === 'files' && fileIframe && currentConversation) {
|
|
213
|
+
var src = BASE + '/files/' + currentConversation + '/';
|
|
214
|
+
if (fileIframe.src !== location.origin + src) {
|
|
215
|
+
fileIframe.src = src;
|
|
218
216
|
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (view === 'voice' && window.voiceModule) {
|
|
220
|
+
window.voiceModule.activate();
|
|
221
|
+
} else if (view !== 'voice' && window.voiceModule) {
|
|
222
|
+
window.voiceModule.deactivate();
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
@@ -432,18 +432,24 @@ class StreamingRenderer {
|
|
|
432
432
|
|
|
433
433
|
const code = block.code || '';
|
|
434
434
|
const language = (block.language || 'plaintext').toLowerCase();
|
|
435
|
+
const lineCount = code.split('\n').length;
|
|
435
436
|
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
437
|
+
const details = document.createElement('details');
|
|
438
|
+
details.className = 'collapsible-code';
|
|
439
|
+
|
|
440
|
+
const summary = document.createElement('summary');
|
|
441
|
+
summary.className = 'collapsible-code-summary';
|
|
442
|
+
summary.innerHTML = `
|
|
443
|
+
<span class="collapsible-code-label">${this.escapeHtml(language)} - ${lineCount} line${lineCount !== 1 ? 's' : ''}</span>
|
|
440
444
|
<button class="copy-code-btn" title="Copy code">
|
|
441
445
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
|
|
442
446
|
</button>
|
|
443
447
|
`;
|
|
444
448
|
|
|
445
|
-
const copyBtn =
|
|
446
|
-
copyBtn.addEventListener('click', () => {
|
|
449
|
+
const copyBtn = summary.querySelector('.copy-code-btn');
|
|
450
|
+
copyBtn.addEventListener('click', (e) => {
|
|
451
|
+
e.preventDefault();
|
|
452
|
+
e.stopPropagation();
|
|
447
453
|
navigator.clipboard.writeText(code).then(() => {
|
|
448
454
|
const orig = copyBtn.innerHTML;
|
|
449
455
|
copyBtn.innerHTML = '<svg viewBox="0 0 20 20" fill="#34d399"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>';
|
|
@@ -451,13 +457,18 @@ class StreamingRenderer {
|
|
|
451
457
|
});
|
|
452
458
|
});
|
|
453
459
|
|
|
454
|
-
|
|
455
|
-
const highlightedHTML = StreamingRenderer.renderCodeWithHighlight(code, this.escapeHtml.bind(this));
|
|
460
|
+
const preStyle = "background:#1e293b;padding:1rem;border-radius:0 0 0.375rem 0.375rem;overflow-x:auto;font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.875rem;line-height:1.6;color:#e2e8f0;border:1px solid #334155;border-top:none;margin:0";
|
|
456
461
|
const codeContainer = document.createElement('div');
|
|
457
|
-
|
|
462
|
+
if (typeof hljs !== 'undefined') {
|
|
463
|
+
const result = hljs.highlightAuto(code);
|
|
464
|
+
codeContainer.innerHTML = `<pre style="${preStyle}"><code class="hljs">${result.value}</code></pre>`;
|
|
465
|
+
} else {
|
|
466
|
+
codeContainer.innerHTML = `<pre style="${preStyle}"><code>${this.escapeHtml(code)}</code></pre>`;
|
|
467
|
+
}
|
|
458
468
|
|
|
459
|
-
|
|
460
|
-
|
|
469
|
+
details.appendChild(summary);
|
|
470
|
+
details.appendChild(codeContainer);
|
|
471
|
+
div.appendChild(details);
|
|
461
472
|
|
|
462
473
|
return div;
|
|
463
474
|
}
|
|
@@ -991,12 +1002,18 @@ class StreamingRenderer {
|
|
|
991
1002
|
* Render code with basic syntax highlighting
|
|
992
1003
|
*/
|
|
993
1004
|
static renderCodeWithHighlight(code, esc) {
|
|
994
|
-
const preStyle = "background:#1e293b;padding:1rem;border-radius:0.375rem;overflow-x:auto;font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.875rem;line-height:1.6;color:#e2e8f0;border:1px solid #334155";
|
|
1005
|
+
const preStyle = "background:#1e293b;padding:1rem;border-radius:0 0 0.375rem 0.375rem;overflow-x:auto;font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.875rem;line-height:1.6;color:#e2e8f0;border:1px solid #334155;border-top:none;margin:0";
|
|
1006
|
+
const lineCount = code.split('\n').length;
|
|
1007
|
+
const lang = (typeof hljs !== 'undefined') ? (hljs.highlightAuto(code).language || 'code') : 'code';
|
|
1008
|
+
const summaryLabel = `${lang} - ${lineCount} line${lineCount !== 1 ? 's' : ''}`;
|
|
1009
|
+
let codeHtml;
|
|
995
1010
|
if (typeof hljs !== 'undefined') {
|
|
996
1011
|
const result = hljs.highlightAuto(code);
|
|
997
|
-
|
|
1012
|
+
codeHtml = `<pre style="${preStyle}"><code class="hljs">${result.value}</code></pre>`;
|
|
1013
|
+
} else {
|
|
1014
|
+
codeHtml = `<pre style="${preStyle}">${esc(code)}</pre>`;
|
|
998
1015
|
}
|
|
999
|
-
return `<
|
|
1016
|
+
return `<details class="collapsible-code"><summary class="collapsible-code-summary">${summaryLabel}</summary>${codeHtml}</details>`;
|
|
1000
1017
|
}
|
|
1001
1018
|
|
|
1002
1019
|
/**
|
|
@@ -1521,16 +1538,19 @@ class StreamingRenderer {
|
|
|
1521
1538
|
<div class="html-content bg-white dark:bg-gray-800 p-4 overflow-x-auto">${part.code}</div>
|
|
1522
1539
|
</div>`;
|
|
1523
1540
|
} else {
|
|
1541
|
+
const partLineCount = part.code.split('\n').length;
|
|
1524
1542
|
html += `<div class="mb-3 rounded-lg overflow-hidden border border-gray-200 dark:border-gray-800">
|
|
1525
|
-
<
|
|
1526
|
-
<
|
|
1527
|
-
|
|
1528
|
-
<
|
|
1529
|
-
<
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1543
|
+
<details class="collapsible-code">
|
|
1544
|
+
<summary class="collapsible-code-summary">
|
|
1545
|
+
<span>${this.escapeHtml(part.language)} - ${partLineCount} line${partLineCount !== 1 ? 's' : ''}</span>
|
|
1546
|
+
<button class="copy-code-btn text-gray-400 hover:text-gray-200 transition-colors p-1 rounded hover:bg-gray-800" title="Copy code" onclick="event.preventDefault();event.stopPropagation();navigator.clipboard.writeText(this.closest('.collapsible-code').querySelector('code').textContent)">
|
|
1547
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1548
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
|
|
1549
|
+
</svg>
|
|
1550
|
+
</button>
|
|
1551
|
+
</summary>
|
|
1552
|
+
<pre class="bg-gray-900 text-gray-100 p-4 overflow-x-auto" style="margin:0;border-radius:0 0 0.375rem 0.375rem"><code class="language-${this.escapeHtml(part.language)}">${this.escapeHtml(part.code)}</code></pre>
|
|
1553
|
+
</details>
|
|
1534
1554
|
</div>`;
|
|
1535
1555
|
}
|
|
1536
1556
|
}
|
|
@@ -1578,8 +1598,12 @@ class StreamingRenderer {
|
|
|
1578
1598
|
</div>
|
|
1579
1599
|
`;
|
|
1580
1600
|
} else {
|
|
1601
|
+
const codeLineCount = code.split('\n').length;
|
|
1581
1602
|
div.innerHTML = `
|
|
1582
|
-
<
|
|
1603
|
+
<details class="collapsible-code">
|
|
1604
|
+
<summary class="collapsible-code-summary">${this.escapeHtml(language)} - ${codeLineCount} line${codeLineCount !== 1 ? 's' : ''}</summary>
|
|
1605
|
+
<pre class="bg-gray-900 text-gray-100 p-4 overflow-x-auto" style="margin:0;border-radius:0 0 0.375rem 0.375rem"><code class="language-${this.escapeHtml(language)}">${this.escapeHtml(code)}</code></pre>
|
|
1606
|
+
</details>
|
|
1583
1607
|
`;
|
|
1584
1608
|
}
|
|
1585
1609
|
return div;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
class SyntaxHighlighter {
|
|
7
7
|
constructor(config = {}) {
|
|
8
8
|
this.config = {
|
|
9
|
-
cdnUrl: config.cdnUrl || 'https://
|
|
9
|
+
cdnUrl: config.cdnUrl || 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0',
|
|
10
10
|
lazyLoad: config.lazyLoad !== false,
|
|
11
11
|
enableCache: config.enableCache !== false,
|
|
12
12
|
maxCacheSize: config.maxCacheSize || 500,
|