agentgui 1.0.332 → 1.0.334
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/package.json +1 -1
- package/server.js +65 -65
- package/static/index.html +32 -0
- package/static/js/features.js +22 -0
- package/static/js/streaming-renderer.js +1 -0
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1756,6 +1756,71 @@ const server = http.createServer(async (req, res) => {
|
|
|
1756
1756
|
return;
|
|
1757
1757
|
}
|
|
1758
1758
|
|
|
1759
|
+
if (pathOnly === '/api/agents/auth-status' && req.method === 'GET') {
|
|
1760
|
+
const statuses = discoveredAgents.map(agent => {
|
|
1761
|
+
const status = { id: agent.id, name: agent.name, authenticated: false, detail: '' };
|
|
1762
|
+
try {
|
|
1763
|
+
if (agent.id === 'claude-code') {
|
|
1764
|
+
const credFile = path.join(os.homedir(), '.claude', '.credentials.json');
|
|
1765
|
+
if (fs.existsSync(credFile)) {
|
|
1766
|
+
const creds = JSON.parse(fs.readFileSync(credFile, 'utf-8'));
|
|
1767
|
+
if (creds.claudeAiOauth && creds.claudeAiOauth.expiresAt > Date.now()) {
|
|
1768
|
+
status.authenticated = true;
|
|
1769
|
+
status.detail = creds.claudeAiOauth.subscriptionType || 'authenticated';
|
|
1770
|
+
} else {
|
|
1771
|
+
status.detail = 'expired';
|
|
1772
|
+
}
|
|
1773
|
+
} else {
|
|
1774
|
+
status.detail = 'no credentials';
|
|
1775
|
+
}
|
|
1776
|
+
} else if (agent.id === 'gemini') {
|
|
1777
|
+
const oauthFile = path.join(os.homedir(), '.gemini', 'oauth_creds.json');
|
|
1778
|
+
const acctFile = path.join(os.homedir(), '.gemini', 'google_accounts.json');
|
|
1779
|
+
let hasOAuth = false;
|
|
1780
|
+
if (fs.existsSync(oauthFile)) {
|
|
1781
|
+
try {
|
|
1782
|
+
const creds = JSON.parse(fs.readFileSync(oauthFile, 'utf-8'));
|
|
1783
|
+
if (creds.refresh_token || creds.access_token) hasOAuth = true;
|
|
1784
|
+
} catch (_) {}
|
|
1785
|
+
}
|
|
1786
|
+
if (fs.existsSync(acctFile)) {
|
|
1787
|
+
const accts = JSON.parse(fs.readFileSync(acctFile, 'utf-8'));
|
|
1788
|
+
if (accts.active) {
|
|
1789
|
+
status.authenticated = true;
|
|
1790
|
+
status.detail = accts.active;
|
|
1791
|
+
} else if (hasOAuth) {
|
|
1792
|
+
status.authenticated = true;
|
|
1793
|
+
status.detail = 'oauth';
|
|
1794
|
+
} else {
|
|
1795
|
+
status.detail = 'logged out';
|
|
1796
|
+
}
|
|
1797
|
+
} else if (hasOAuth) {
|
|
1798
|
+
status.authenticated = true;
|
|
1799
|
+
status.detail = 'oauth';
|
|
1800
|
+
} else {
|
|
1801
|
+
status.detail = 'no credentials';
|
|
1802
|
+
}
|
|
1803
|
+
} else if (agent.id === 'opencode') {
|
|
1804
|
+
const out = execSync('opencode auth list 2>&1', { encoding: 'utf-8', timeout: 5000 });
|
|
1805
|
+
const countMatch = out.match(/(\d+)\s+credentials?/);
|
|
1806
|
+
if (countMatch && parseInt(countMatch[1], 10) > 0) {
|
|
1807
|
+
status.authenticated = true;
|
|
1808
|
+
status.detail = countMatch[1] + ' credential(s)';
|
|
1809
|
+
} else {
|
|
1810
|
+
status.detail = 'no credentials';
|
|
1811
|
+
}
|
|
1812
|
+
} else {
|
|
1813
|
+
status.detail = 'unknown';
|
|
1814
|
+
}
|
|
1815
|
+
} catch (e) {
|
|
1816
|
+
status.detail = 'check failed';
|
|
1817
|
+
}
|
|
1818
|
+
return status;
|
|
1819
|
+
});
|
|
1820
|
+
sendJSON(req, res, 200, { agents: statuses });
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1759
1824
|
const agentByIdMatch = pathOnly.match(/^\/api\/agents\/([^/]+)$/);
|
|
1760
1825
|
if (agentByIdMatch && req.method === 'GET') {
|
|
1761
1826
|
const agentId = agentByIdMatch[1];
|
|
@@ -1826,71 +1891,6 @@ const server = http.createServer(async (req, res) => {
|
|
|
1826
1891
|
return;
|
|
1827
1892
|
}
|
|
1828
1893
|
|
|
1829
|
-
if (pathOnly === '/api/agents/auth-status' && req.method === 'GET') {
|
|
1830
|
-
const statuses = discoveredAgents.map(agent => {
|
|
1831
|
-
const status = { id: agent.id, name: agent.name, authenticated: false, detail: '' };
|
|
1832
|
-
try {
|
|
1833
|
-
if (agent.id === 'claude-code') {
|
|
1834
|
-
const credFile = path.join(os.homedir(), '.claude', '.credentials.json');
|
|
1835
|
-
if (fs.existsSync(credFile)) {
|
|
1836
|
-
const creds = JSON.parse(fs.readFileSync(credFile, 'utf-8'));
|
|
1837
|
-
if (creds.claudeAiOauth && creds.claudeAiOauth.expiresAt > Date.now()) {
|
|
1838
|
-
status.authenticated = true;
|
|
1839
|
-
status.detail = creds.claudeAiOauth.subscriptionType || 'authenticated';
|
|
1840
|
-
} else {
|
|
1841
|
-
status.detail = 'expired';
|
|
1842
|
-
}
|
|
1843
|
-
} else {
|
|
1844
|
-
status.detail = 'no credentials';
|
|
1845
|
-
}
|
|
1846
|
-
} else if (agent.id === 'gemini') {
|
|
1847
|
-
const oauthFile = path.join(os.homedir(), '.gemini', 'oauth_creds.json');
|
|
1848
|
-
const acctFile = path.join(os.homedir(), '.gemini', 'google_accounts.json');
|
|
1849
|
-
let hasOAuth = false;
|
|
1850
|
-
if (fs.existsSync(oauthFile)) {
|
|
1851
|
-
try {
|
|
1852
|
-
const creds = JSON.parse(fs.readFileSync(oauthFile, 'utf-8'));
|
|
1853
|
-
if (creds.refresh_token || creds.access_token) hasOAuth = true;
|
|
1854
|
-
} catch (_) {}
|
|
1855
|
-
}
|
|
1856
|
-
if (fs.existsSync(acctFile)) {
|
|
1857
|
-
const accts = JSON.parse(fs.readFileSync(acctFile, 'utf-8'));
|
|
1858
|
-
if (accts.active) {
|
|
1859
|
-
status.authenticated = true;
|
|
1860
|
-
status.detail = accts.active;
|
|
1861
|
-
} else if (hasOAuth) {
|
|
1862
|
-
status.authenticated = true;
|
|
1863
|
-
status.detail = 'oauth';
|
|
1864
|
-
} else {
|
|
1865
|
-
status.detail = 'logged out';
|
|
1866
|
-
}
|
|
1867
|
-
} else if (hasOAuth) {
|
|
1868
|
-
status.authenticated = true;
|
|
1869
|
-
status.detail = 'oauth';
|
|
1870
|
-
} else {
|
|
1871
|
-
status.detail = 'no credentials';
|
|
1872
|
-
}
|
|
1873
|
-
} else if (agent.id === 'opencode') {
|
|
1874
|
-
const out = execSync('opencode auth list 2>&1', { encoding: 'utf-8', timeout: 5000 });
|
|
1875
|
-
const countMatch = out.match(/(\d+)\s+credentials?/);
|
|
1876
|
-
if (countMatch && parseInt(countMatch[1], 10) > 0) {
|
|
1877
|
-
status.authenticated = true;
|
|
1878
|
-
status.detail = countMatch[1] + ' credential(s)';
|
|
1879
|
-
} else {
|
|
1880
|
-
status.detail = 'no credentials';
|
|
1881
|
-
}
|
|
1882
|
-
} else {
|
|
1883
|
-
status.detail = 'unknown';
|
|
1884
|
-
}
|
|
1885
|
-
} catch (e) {
|
|
1886
|
-
status.detail = 'check failed';
|
|
1887
|
-
}
|
|
1888
|
-
return status;
|
|
1889
|
-
});
|
|
1890
|
-
sendJSON(req, res, 200, { agents: statuses });
|
|
1891
|
-
return;
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
1894
|
if (pathOnly === '/api/gemini-oauth/start' && req.method === 'POST') {
|
|
1895
1895
|
try {
|
|
1896
1896
|
const result = await startGeminiOAuth(req);
|
package/static/index.html
CHANGED
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
--color-text-primary: #f9fafb;
|
|
47
47
|
--color-text-secondary: #d1d5db;
|
|
48
48
|
--color-border: #374151;
|
|
49
|
+
--color-primary: #6b7280;
|
|
50
|
+
--color-primary-dark: #4b5563;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
html, body {
|
|
@@ -496,6 +498,26 @@
|
|
|
496
498
|
}
|
|
497
499
|
.terminal-output { flex: 1; overflow: hidden; }
|
|
498
500
|
|
|
501
|
+
.models-container {
|
|
502
|
+
flex: 1; display: flex; flex-direction: column; overflow-y: auto;
|
|
503
|
+
align-items: flex-start; padding: 2rem;
|
|
504
|
+
}
|
|
505
|
+
.models-panel {
|
|
506
|
+
display: flex; flex-direction: column; gap: 1rem;
|
|
507
|
+
background: var(--color-bg-secondary); border-radius: 0.5rem;
|
|
508
|
+
padding: 1.5rem; min-width: 280px;
|
|
509
|
+
}
|
|
510
|
+
.models-panel h3 { margin: 0 0 0.5rem; font-size: 1rem; font-weight: 600; }
|
|
511
|
+
.models-panel label {
|
|
512
|
+
display: flex; flex-direction: column; gap: 0.25rem;
|
|
513
|
+
font-size: 0.8rem; color: var(--color-text-secondary); font-weight: 500;
|
|
514
|
+
}
|
|
515
|
+
.models-panel select {
|
|
516
|
+
padding: 0.5rem; border: 1px solid var(--color-border);
|
|
517
|
+
border-radius: 0.375rem; background: var(--color-bg-primary);
|
|
518
|
+
color: var(--color-text-primary); font-size: 0.875rem; cursor: pointer;
|
|
519
|
+
}
|
|
520
|
+
|
|
499
521
|
/* --- View toggle bar --- */
|
|
500
522
|
.view-toggle-bar {
|
|
501
523
|
display: flex;
|
|
@@ -3024,6 +3046,7 @@
|
|
|
3024
3046
|
<button class="view-toggle-btn active" data-view="chat">Chat</button>
|
|
3025
3047
|
<button class="view-toggle-btn" data-view="files">Files</button>
|
|
3026
3048
|
<button class="view-toggle-btn" data-view="voice" style="display:none;">Voice</button>
|
|
3049
|
+
<button class="view-toggle-btn" data-view="models">Models</button>
|
|
3027
3050
|
<button class="view-toggle-btn" data-view="terminal" id="terminalTabBtn" style="display:none;">Terminal</button>
|
|
3028
3051
|
</div>
|
|
3029
3052
|
|
|
@@ -3045,6 +3068,15 @@
|
|
|
3045
3068
|
<iframe id="fileBrowserIframe" class="file-browser-iframe"></iframe>
|
|
3046
3069
|
</div>
|
|
3047
3070
|
|
|
3071
|
+
<!-- Models/Agent selector view -->
|
|
3072
|
+
<div id="modelsContainer" class="models-container" style="display:none;">
|
|
3073
|
+
<div class="models-panel">
|
|
3074
|
+
<h3>Agent & Model</h3>
|
|
3075
|
+
<label>Agent<select class="agent-selector" data-agent-selector-models title="Select agent"></select></label>
|
|
3076
|
+
<label>Model<select class="model-selector" data-model-selector-models title="Select model" data-empty="true"></select></label>
|
|
3077
|
+
</div>
|
|
3078
|
+
</div>
|
|
3079
|
+
|
|
3048
3080
|
<!-- Terminal output view -->
|
|
3049
3081
|
<div id="terminalContainer" class="terminal-container" style="display:none;">
|
|
3050
3082
|
<div id="terminalOutput" class="terminal-output"></div>
|
package/static/js/features.js
CHANGED
|
@@ -346,6 +346,7 @@
|
|
|
346
346
|
var fileIframe = document.getElementById('fileBrowserIframe');
|
|
347
347
|
var voiceContainer = document.getElementById('voiceContainer');
|
|
348
348
|
var terminalContainer = document.getElementById('terminalContainer');
|
|
349
|
+
var modelsContainer = document.getElementById('modelsContainer');
|
|
349
350
|
|
|
350
351
|
if (!bar) return;
|
|
351
352
|
|
|
@@ -358,6 +359,7 @@
|
|
|
358
359
|
if (fileBrowser) fileBrowser.style.display = view === 'files' ? 'flex' : 'none';
|
|
359
360
|
if (voiceContainer) voiceContainer.style.display = view === 'voice' ? 'flex' : 'none';
|
|
360
361
|
if (terminalContainer) terminalContainer.style.display = view === 'terminal' ? 'flex' : 'none';
|
|
362
|
+
if (modelsContainer) modelsContainer.style.display = view === 'models' ? 'flex' : 'none';
|
|
361
363
|
|
|
362
364
|
if (view === 'files' && fileIframe && currentConversation) {
|
|
363
365
|
var src = BASE + '/files/' + currentConversation + '/';
|
|
@@ -372,9 +374,29 @@
|
|
|
372
374
|
window.voiceModule.deactivate();
|
|
373
375
|
}
|
|
374
376
|
|
|
377
|
+
if (view === 'models') syncModelsPanelFromMain();
|
|
378
|
+
|
|
375
379
|
window.dispatchEvent(new CustomEvent('view-switched', { detail: { view: view } }));
|
|
376
380
|
}
|
|
377
381
|
|
|
382
|
+
function syncModelsPanelFromMain() {
|
|
383
|
+
var mainAgent = document.querySelector('[data-agent-selector]');
|
|
384
|
+
var mainModel = document.querySelector('[data-model-selector]');
|
|
385
|
+
var panelAgent = document.querySelector('[data-agent-selector-models]');
|
|
386
|
+
var panelModel = document.querySelector('[data-model-selector-models]');
|
|
387
|
+
if (!panelAgent || !panelModel) return;
|
|
388
|
+
if (mainAgent && panelAgent.innerHTML !== mainAgent.innerHTML) {
|
|
389
|
+
panelAgent.innerHTML = mainAgent.innerHTML;
|
|
390
|
+
panelAgent.value = mainAgent.value;
|
|
391
|
+
}
|
|
392
|
+
if (mainModel && panelModel.innerHTML !== mainModel.innerHTML) {
|
|
393
|
+
panelModel.innerHTML = mainModel.innerHTML;
|
|
394
|
+
panelModel.value = mainModel.value;
|
|
395
|
+
}
|
|
396
|
+
panelAgent.onchange = function() { if (mainAgent) { mainAgent.value = panelAgent.value; mainAgent.dispatchEvent(new Event('change')); } };
|
|
397
|
+
panelModel.onchange = function() { if (mainModel) { mainModel.value = panelModel.value; mainModel.dispatchEvent(new Event('change')); } };
|
|
398
|
+
}
|
|
399
|
+
|
|
378
400
|
function updateViewToggleVisibility() {
|
|
379
401
|
var bar = document.getElementById('viewToggleBar');
|
|
380
402
|
if (!bar) return;
|
|
@@ -1213,6 +1213,7 @@ class StreamingRenderer {
|
|
|
1213
1213
|
const details = document.createElement('details');
|
|
1214
1214
|
details.className = 'folded-tool' + (isError ? ' folded-tool-error' : ' folded-tool-success');
|
|
1215
1215
|
details.dataset.eventType = 'tool_result';
|
|
1216
|
+
if (!isError) details.open = true;
|
|
1216
1217
|
if (block.tool_use_id) details.dataset.toolUseId = block.tool_use_id;
|
|
1217
1218
|
details.classList.add(this._getBlockTypeClass('tool_result'));
|
|
1218
1219
|
|