agentgui 1.0.414 → 1.0.415
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/lib/ws-handlers-session.js +14 -1
- package/package.json +1 -1
- package/server.js +105 -17
- package/static/index.html +41 -30
- package/static/js/client.js +210 -96
|
@@ -97,7 +97,20 @@ export function register(router, deps) {
|
|
|
97
97
|
return data;
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
router.handle('agent.ls', () =>
|
|
100
|
+
router.handle('agent.ls', () => {
|
|
101
|
+
// Get local agents only (avoid external HTTP calls in WebSocket to prevent recursion)
|
|
102
|
+
const localAgents = discoveredAgents.map(agent => ({
|
|
103
|
+
id: agent.id,
|
|
104
|
+
name: agent.name,
|
|
105
|
+
icon: agent.icon,
|
|
106
|
+
path: agent.path,
|
|
107
|
+
protocol: agent.protocol || 'unknown',
|
|
108
|
+
description: agent.description || '',
|
|
109
|
+
status: 'available'
|
|
110
|
+
}));
|
|
111
|
+
|
|
112
|
+
return { agents: localAgents };
|
|
113
|
+
});
|
|
101
114
|
|
|
102
115
|
router.handle('agent.get', (p) => {
|
|
103
116
|
const a = discoveredAgents.find(x => x.id === p.id);
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -342,31 +342,96 @@ function findCommand(cmd) {
|
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
+
async function queryACPServerAgents(baseUrl) {
|
|
346
|
+
try {
|
|
347
|
+
// Ensure correct endpoint format (handle both /api and /api/ cases)
|
|
348
|
+
const endpoint = baseUrl.endsWith('/') ? `${baseUrl}agents/search` : `${baseUrl}/agents/search`;
|
|
349
|
+
const response = await fetch(endpoint, {
|
|
350
|
+
method: 'POST',
|
|
351
|
+
headers: {
|
|
352
|
+
'Content-Type': 'application/json',
|
|
353
|
+
},
|
|
354
|
+
body: JSON.stringify({}),
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
if (!response.ok) {
|
|
358
|
+
console.error(`Failed to query ACP agents from ${baseUrl}: ${response.status}`);
|
|
359
|
+
return [];
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const data = await response.json();
|
|
363
|
+
if (!data.agents || !Array.isArray(data.agents)) {
|
|
364
|
+
console.error(`Invalid agents response from ${baseUrl}`);
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Convert ACP agent format to our internal format
|
|
369
|
+
return data.agents.map(agent => ({
|
|
370
|
+
id: agent.agent_id || agent.id,
|
|
371
|
+
name: agent.metadata?.ref?.name || agent.name || 'Unknown Agent',
|
|
372
|
+
icon: agent.metadata?.ref?.name?.charAt(0) || 'A',
|
|
373
|
+
path: baseUrl,
|
|
374
|
+
protocol: 'acp',
|
|
375
|
+
description: agent.metadata?.description || '',
|
|
376
|
+
}));
|
|
377
|
+
} catch (error) {
|
|
378
|
+
console.error(`Error querying ACP server ${baseUrl}:`, error.message);
|
|
379
|
+
return [];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
345
383
|
function discoverAgents() {
|
|
346
384
|
const agents = [];
|
|
347
385
|
const binaries = [
|
|
348
|
-
{ cmd: 'claude', id: 'claude-code', name: 'Claude Code', icon: 'C' },
|
|
349
|
-
{ cmd: 'opencode', id: 'opencode', name: 'OpenCode', icon: 'O' },
|
|
350
|
-
{ cmd: 'gemini', id: 'gemini', name: 'Gemini CLI', icon: 'G' },
|
|
351
|
-
{ cmd: 'kilo', id: 'kilo', name: 'Kilo Code', icon: 'K' },
|
|
352
|
-
{ cmd: 'goose', id: 'goose', name: 'Goose', icon: 'g' },
|
|
353
|
-
{ cmd: 'openhands', id: 'openhands', name: 'OpenHands', icon: 'H' },
|
|
354
|
-
{ cmd: 'augment', id: 'augment', name: 'Augment Code', icon: 'A' },
|
|
355
|
-
{ cmd: 'cline', id: 'cline', name: 'Cline', icon: 'c' },
|
|
356
|
-
{ cmd: 'kimi', id: 'kimi', name: 'Kimi CLI', icon: 'K' },
|
|
357
|
-
{ cmd: 'qwen-code', id: 'qwen', name: 'Qwen Code', icon: 'Q' },
|
|
358
|
-
{ cmd: 'codex', id: 'codex', name: 'Codex CLI', icon: 'X' },
|
|
359
|
-
{ cmd: 'mistral-vibe', id: 'mistral', name: 'Mistral Vibe', icon: 'M' },
|
|
360
|
-
{ cmd: 'kiro', id: 'kiro', name: 'Kiro CLI', icon: 'k' },
|
|
361
|
-
{ cmd: 'fast-agent', id: 'fast-agent', name: 'fast-agent', icon: 'F' },
|
|
386
|
+
{ cmd: 'claude', id: 'claude-code', name: 'Claude Code', icon: 'C', protocol: 'cli' },
|
|
387
|
+
{ cmd: 'opencode', id: 'opencode', name: 'OpenCode', icon: 'O', protocol: 'acp' },
|
|
388
|
+
{ cmd: 'gemini', id: 'gemini', name: 'Gemini CLI', icon: 'G', protocol: 'acp' },
|
|
389
|
+
{ cmd: 'kilo', id: 'kilo', name: 'Kilo Code', icon: 'K', protocol: 'acp' },
|
|
390
|
+
{ cmd: 'goose', id: 'goose', name: 'Goose', icon: 'g', protocol: 'acp' },
|
|
391
|
+
{ cmd: 'openhands', id: 'openhands', name: 'OpenHands', icon: 'H', protocol: 'acp' },
|
|
392
|
+
{ cmd: 'augment', id: 'augment', name: 'Augment Code', icon: 'A', protocol: 'acp' },
|
|
393
|
+
{ cmd: 'cline', id: 'cline', name: 'Cline', icon: 'c', protocol: 'acp' },
|
|
394
|
+
{ cmd: 'kimi', id: 'kimi', name: 'Kimi CLI', icon: 'K', protocol: 'acp' },
|
|
395
|
+
{ cmd: 'qwen-code', id: 'qwen', name: 'Qwen Code', icon: 'Q', protocol: 'acp' },
|
|
396
|
+
{ cmd: 'codex', id: 'codex', name: 'Codex CLI', icon: 'X', protocol: 'acp' },
|
|
397
|
+
{ cmd: 'mistral-vibe', id: 'mistral', name: 'Mistral Vibe', icon: 'M', protocol: 'acp' },
|
|
398
|
+
{ cmd: 'kiro', id: 'kiro', name: 'Kiro CLI', icon: 'k', protocol: 'acp' },
|
|
399
|
+
{ cmd: 'fast-agent', id: 'fast-agent', name: 'fast-agent', icon: 'F', protocol: 'acp' },
|
|
362
400
|
];
|
|
363
401
|
for (const bin of binaries) {
|
|
364
402
|
const result = findCommand(bin.cmd);
|
|
365
|
-
if (result) agents.push({
|
|
403
|
+
if (result) agents.push({
|
|
404
|
+
id: bin.id,
|
|
405
|
+
name: bin.name,
|
|
406
|
+
icon: bin.icon,
|
|
407
|
+
path: result,
|
|
408
|
+
protocol: bin.protocol
|
|
409
|
+
});
|
|
366
410
|
}
|
|
367
411
|
return agents;
|
|
368
412
|
}
|
|
369
413
|
|
|
414
|
+
// Function to discover agents from external ACP servers
|
|
415
|
+
async function discoverExternalACPServers() {
|
|
416
|
+
// Default ACP servers to query (excluding local server to prevent recursion)
|
|
417
|
+
const acpServers = [
|
|
418
|
+
'http://localhost:8080', // Common default ACP port
|
|
419
|
+
];
|
|
420
|
+
|
|
421
|
+
const externalAgents = [];
|
|
422
|
+
for (const serverUrl of acpServers) {
|
|
423
|
+
try {
|
|
424
|
+
console.log(`Querying ACP agents from: ${serverUrl}`);
|
|
425
|
+
const agents = await queryACPServerAgents(serverUrl);
|
|
426
|
+
externalAgents.push(...agents);
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error(`Failed to query ${serverUrl}:`, error.message);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return externalAgents;
|
|
433
|
+
}
|
|
434
|
+
|
|
370
435
|
const discoveredAgents = discoverAgents();
|
|
371
436
|
initializeDescriptors(discoveredAgents);
|
|
372
437
|
|
|
@@ -1947,8 +2012,31 @@ const server = http.createServer(async (req, res) => {
|
|
|
1947
2012
|
|
|
1948
2013
|
if (pathOnly === '/api/agents/search' && req.method === 'POST') {
|
|
1949
2014
|
const body = await parseBody(req);
|
|
1950
|
-
|
|
1951
|
-
|
|
2015
|
+
try {
|
|
2016
|
+
// Get local agents
|
|
2017
|
+
const localResult = queries.searchAgents(discoveredAgents, body);
|
|
2018
|
+
|
|
2019
|
+
// Get external agents from ACP servers
|
|
2020
|
+
const externalAgents = await discoverExternalACPServers();
|
|
2021
|
+
const externalResult = queries.searchAgents(externalAgents, body);
|
|
2022
|
+
|
|
2023
|
+
// Combine results
|
|
2024
|
+
const combinedAgents = [...localResult.agents, ...externalResult.agents];
|
|
2025
|
+
const total = localResult.total + externalResult.total;
|
|
2026
|
+
const hasMore = localResult.hasMore || externalResult.hasMore;
|
|
2027
|
+
|
|
2028
|
+
sendJSON(req, res, 200, {
|
|
2029
|
+
agents: combinedAgents,
|
|
2030
|
+
total,
|
|
2031
|
+
limit: body.limit || 50,
|
|
2032
|
+
offset: body.offset || 0,
|
|
2033
|
+
hasMore,
|
|
2034
|
+
});
|
|
2035
|
+
} catch (error) {
|
|
2036
|
+
console.error('Error searching agents:', error);
|
|
2037
|
+
const result = queries.searchAgents(discoveredAgents, body);
|
|
2038
|
+
sendJSON(req, res, 200, result);
|
|
2039
|
+
}
|
|
1952
2040
|
return;
|
|
1953
2041
|
}
|
|
1954
2042
|
|
package/static/index.html
CHANGED
|
@@ -804,25 +804,35 @@
|
|
|
804
804
|
align-items: flex-end;
|
|
805
805
|
}
|
|
806
806
|
|
|
807
|
-
.agent-selector {
|
|
808
|
-
padding: 0.5rem;
|
|
809
|
-
border: none;
|
|
810
|
-
border-radius: 0.375rem;
|
|
811
|
-
background-color: var(--color-bg-secondary);
|
|
812
|
-
color: var(--color-text-primary);
|
|
813
|
-
font-size: 0.8rem;
|
|
814
|
-
cursor: pointer;
|
|
815
|
-
flex-shrink: 0;
|
|
816
|
-
width: auto;
|
|
817
|
-
min-width: 80px;
|
|
818
|
-
max-width: 200px;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
.agent-selector
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
807
|
+
.agent-selector {
|
|
808
|
+
padding: 0.5rem;
|
|
809
|
+
border: none;
|
|
810
|
+
border-radius: 0.375rem;
|
|
811
|
+
background-color: var(--color-bg-secondary);
|
|
812
|
+
color: var(--color-text-primary);
|
|
813
|
+
font-size: 0.8rem;
|
|
814
|
+
cursor: pointer;
|
|
815
|
+
flex-shrink: 0;
|
|
816
|
+
width: auto;
|
|
817
|
+
min-width: 80px;
|
|
818
|
+
max-width: 200px;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.cli-agent-selector {
|
|
822
|
+
/* CLI agents have a different background color */
|
|
823
|
+
background-color: var(--color-bg-secondary);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.acp-agent-selector {
|
|
827
|
+
/* ACP agents have a different background color */
|
|
828
|
+
background-color: var(--color-bg-secondary);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.agent-selector:disabled, .model-selector:disabled {
|
|
832
|
+
opacity: 0.5;
|
|
833
|
+
cursor: not-allowed;
|
|
834
|
+
background-color: var(--color-bg-secondary);
|
|
835
|
+
}
|
|
826
836
|
|
|
827
837
|
.model-selector {
|
|
828
838
|
padding: 0.5rem;
|
|
@@ -3167,17 +3177,18 @@
|
|
|
3167
3177
|
</div>
|
|
3168
3178
|
|
|
3169
3179
|
<!-- Input area: fixed at bottom -->
|
|
3170
|
-
<div class="input-section">
|
|
3171
|
-
<div class="input-wrapper">
|
|
3172
|
-
<select class="agent-selector" data-agent-selector title="Select agent"></select>
|
|
3173
|
-
<select class="
|
|
3174
|
-
<
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3180
|
+
<div class="input-section">
|
|
3181
|
+
<div class="input-wrapper">
|
|
3182
|
+
<select class="agent-selector cli-agent-selector" data-cli-agent-selector title="Select CLI agent"></select>
|
|
3183
|
+
<select class="agent-selector acp-agent-selector" data-acp-agent-selector title="Select ACP agent"></select>
|
|
3184
|
+
<select class="model-selector" data-model-selector title="Select model" data-empty="true"></select>
|
|
3185
|
+
<textarea
|
|
3186
|
+
class="message-textarea"
|
|
3187
|
+
data-message-input
|
|
3188
|
+
placeholder="Message AgentGUI... (Ctrl+Enter to send)"
|
|
3189
|
+
aria-label="Message input"
|
|
3190
|
+
rows="1"
|
|
3191
|
+
></textarea>
|
|
3181
3192
|
<button class="inject-btn" id="injectBtn" title="Inject instructions into running agent" aria-label="Inject instructions">
|
|
3182
3193
|
<svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18">
|
|
3183
3194
|
<path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"/>
|
package/static/js/client.js
CHANGED
|
@@ -341,30 +341,50 @@ class AgentGUIClient {
|
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
/**
|
|
345
|
-
* Setup UI elements
|
|
346
|
-
*/
|
|
347
|
-
setupUI() {
|
|
348
|
-
const container = document.getElementById(this.config.containerId);
|
|
349
|
-
if (!container) {
|
|
350
|
-
throw new Error(`Container not found: ${this.config.containerId}`);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// Get references to key UI elements
|
|
354
|
-
this.ui.statusIndicator = document.querySelector('[data-status-indicator]');
|
|
355
|
-
this.ui.messageInput = document.querySelector('[data-message-input]');
|
|
356
|
-
this.ui.sendButton = document.querySelector('[data-send-button]');
|
|
357
|
-
this.ui.
|
|
358
|
-
this.ui.
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
this.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Setup UI elements
|
|
346
|
+
*/
|
|
347
|
+
setupUI() {
|
|
348
|
+
const container = document.getElementById(this.config.containerId);
|
|
349
|
+
if (!container) {
|
|
350
|
+
throw new Error(`Container not found: ${this.config.containerId}`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Get references to key UI elements
|
|
354
|
+
this.ui.statusIndicator = document.querySelector('[data-status-indicator]');
|
|
355
|
+
this.ui.messageInput = document.querySelector('[data-message-input]');
|
|
356
|
+
this.ui.sendButton = document.querySelector('[data-send-button]');
|
|
357
|
+
this.ui.cliAgentSelector = document.querySelector('[data-cli-agent-selector]');
|
|
358
|
+
this.ui.acpAgentSelector = document.querySelector('[data-acp-agent-selector]');
|
|
359
|
+
this.ui.modelSelector = document.querySelector('[data-model-selector]');
|
|
360
|
+
|
|
361
|
+
if (this.ui.cliAgentSelector) {
|
|
362
|
+
this.ui.cliAgentSelector.addEventListener('change', () => {
|
|
363
|
+
if (!this._agentLocked) {
|
|
364
|
+
this.loadModelsForAgent(this.ui.cliAgentSelector.value);
|
|
365
|
+
this.saveAgentAndModelToConversation();
|
|
366
|
+
// Hide ACP selector when CLI is selected
|
|
367
|
+
if (this.ui.acpAgentSelector) {
|
|
368
|
+
this.ui.acpAgentSelector.value = '';
|
|
369
|
+
this.ui.acpAgentSelector.style.display = 'none';
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (this.ui.acpAgentSelector) {
|
|
376
|
+
this.ui.acpAgentSelector.addEventListener('change', () => {
|
|
377
|
+
if (!this._agentLocked) {
|
|
378
|
+
this.loadModelsForAgent(this.ui.acpAgentSelector.value);
|
|
379
|
+
this.saveAgentAndModelToConversation();
|
|
380
|
+
// Hide CLI selector when ACP is selected
|
|
381
|
+
if (this.ui.cliAgentSelector) {
|
|
382
|
+
this.ui.cliAgentSelector.value = '';
|
|
383
|
+
this.ui.cliAgentSelector.style.display = 'none';
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
368
388
|
|
|
369
389
|
if (this.ui.modelSelector) {
|
|
370
390
|
this.ui.modelSelector.addEventListener('change', () => {
|
|
@@ -1244,12 +1264,12 @@ class AgentGUIClient {
|
|
|
1244
1264
|
}
|
|
1245
1265
|
}
|
|
1246
1266
|
|
|
1247
|
-
async startExecution() {
|
|
1248
|
-
const prompt = this.ui.messageInput?.value || '';
|
|
1249
|
-
const conv = this.state.currentConversation;
|
|
1250
|
-
const isNewConversation = conv && !conv.messageCount && !this.state.streamingConversations.has(conv.id);
|
|
1251
|
-
const agentId = (isNewConversation ? this.
|
|
1252
|
-
const model = this.ui.modelSelector?.value || null;
|
|
1267
|
+
async startExecution() {
|
|
1268
|
+
const prompt = this.ui.messageInput?.value || '';
|
|
1269
|
+
const conv = this.state.currentConversation;
|
|
1270
|
+
const isNewConversation = conv && !conv.messageCount && !this.state.streamingConversations.has(conv.id);
|
|
1271
|
+
const agentId = (isNewConversation ? this.getCurrentAgent() : null) || conv?.agentType || this.getCurrentAgent() || 'claude-code';
|
|
1272
|
+
const model = this.ui.modelSelector?.value || null;
|
|
1253
1273
|
|
|
1254
1274
|
if (!prompt.trim()) {
|
|
1255
1275
|
this.showError('Please enter a prompt');
|
|
@@ -1816,29 +1836,53 @@ class AgentGUIClient {
|
|
|
1816
1836
|
/**
|
|
1817
1837
|
* Load agents
|
|
1818
1838
|
*/
|
|
1819
|
-
async loadAgents() {
|
|
1820
|
-
return this._dedupedFetch('loadAgents', async () => {
|
|
1821
|
-
try {
|
|
1822
|
-
const { agents } = await window.wsClient.rpc('agent.ls');
|
|
1823
|
-
this.state.agents = agents;
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1839
|
+
async loadAgents() {
|
|
1840
|
+
return this._dedupedFetch('loadAgents', async () => {
|
|
1841
|
+
try {
|
|
1842
|
+
const { agents } = await window.wsClient.rpc('agent.ls');
|
|
1843
|
+
this.state.agents = agents;
|
|
1844
|
+
|
|
1845
|
+
// Split agents by protocol
|
|
1846
|
+
const cliAgents = agents.filter(agent => agent.protocol === 'cli');
|
|
1847
|
+
const acpAgents = agents.filter(agent => agent.protocol === 'acp');
|
|
1848
|
+
|
|
1849
|
+
// Populate CLI agent selector
|
|
1850
|
+
if (this.ui.cliAgentSelector) {
|
|
1851
|
+
if (cliAgents.length > 0) {
|
|
1852
|
+
this.ui.cliAgentSelector.innerHTML = cliAgents
|
|
1853
|
+
.map(agent => `<option value="${agent.id}">${agent.name}</option>`)
|
|
1854
|
+
.join('');
|
|
1855
|
+
this.ui.cliAgentSelector.style.display = 'inline-block';
|
|
1856
|
+
} else {
|
|
1857
|
+
this.ui.cliAgentSelector.innerHTML = '';
|
|
1858
|
+
this.ui.cliAgentSelector.style.display = 'none';
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
// Populate ACP agent selector
|
|
1863
|
+
if (this.ui.acpAgentSelector) {
|
|
1864
|
+
if (acpAgents.length > 0) {
|
|
1865
|
+
this.ui.acpAgentSelector.innerHTML = acpAgents
|
|
1866
|
+
.map(agent => `<option value="${agent.id}">${agent.name}</option>`)
|
|
1867
|
+
.join('');
|
|
1868
|
+
this.ui.acpAgentSelector.style.display = 'inline-block';
|
|
1869
|
+
} else {
|
|
1870
|
+
this.ui.acpAgentSelector.innerHTML = '';
|
|
1871
|
+
this.ui.acpAgentSelector.style.display = 'none';
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
window.dispatchEvent(new CustomEvent('agents-loaded', { detail: { agents } }));
|
|
1876
|
+
if (agents.length > 0 && !this._agentLocked) {
|
|
1877
|
+
this.loadModelsForAgent(agents[0].id);
|
|
1878
|
+
}
|
|
1879
|
+
return agents;
|
|
1880
|
+
} catch (error) {
|
|
1881
|
+
console.error('Failed to load agents:', error);
|
|
1882
|
+
return [];
|
|
1883
|
+
}
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1842
1886
|
|
|
1843
1887
|
async checkSpeechStatus() {
|
|
1844
1888
|
try {
|
|
@@ -1890,48 +1934,105 @@ class AgentGUIClient {
|
|
|
1890
1934
|
.join('');
|
|
1891
1935
|
}
|
|
1892
1936
|
|
|
1893
|
-
lockAgentAndModel(agentId, model) {
|
|
1894
|
-
this._agentLocked = true;
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
if (
|
|
1901
|
-
this.ui.
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1937
|
+
lockAgentAndModel(agentId, model) {
|
|
1938
|
+
this._agentLocked = true;
|
|
1939
|
+
|
|
1940
|
+
// Find the agent to determine protocol
|
|
1941
|
+
const agent = this.state.agents.find(a => a.id === agentId);
|
|
1942
|
+
|
|
1943
|
+
if (agent) {
|
|
1944
|
+
if (agent.protocol === 'cli') {
|
|
1945
|
+
if (this.ui.cliAgentSelector) {
|
|
1946
|
+
this.ui.cliAgentSelector.value = agentId;
|
|
1947
|
+
this.ui.cliAgentSelector.disabled = true;
|
|
1948
|
+
}
|
|
1949
|
+
if (this.ui.acpAgentSelector) {
|
|
1950
|
+
this.ui.acpAgentSelector.value = '';
|
|
1951
|
+
this.ui.acpAgentSelector.disabled = true;
|
|
1952
|
+
this.ui.acpAgentSelector.style.display = 'none';
|
|
1953
|
+
}
|
|
1954
|
+
} else {
|
|
1955
|
+
if (this.ui.acpAgentSelector) {
|
|
1956
|
+
this.ui.acpAgentSelector.value = agentId;
|
|
1957
|
+
this.ui.acpAgentSelector.disabled = true;
|
|
1958
|
+
}
|
|
1959
|
+
if (this.ui.cliAgentSelector) {
|
|
1960
|
+
this.ui.cliAgentSelector.value = '';
|
|
1961
|
+
this.ui.cliAgentSelector.disabled = true;
|
|
1962
|
+
this.ui.cliAgentSelector.style.display = 'none';
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
this.loadModelsForAgent(agentId).then(() => {
|
|
1968
|
+
if (this.ui.modelSelector && model) {
|
|
1969
|
+
this.ui.modelSelector.value = model;
|
|
1970
|
+
}
|
|
1971
|
+
});
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
unlockAgentAndModel() {
|
|
1975
|
+
this._agentLocked = false;
|
|
1976
|
+
if (this.ui.cliAgentSelector) {
|
|
1977
|
+
this.ui.cliAgentSelector.disabled = false;
|
|
1978
|
+
}
|
|
1979
|
+
if (this.ui.acpAgentSelector) {
|
|
1980
|
+
this.ui.acpAgentSelector.disabled = false;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
// Show both selectors again when unlocking
|
|
1984
|
+
if (this.ui.cliAgentSelector && this.state.agents.some(a => a.protocol === 'cli')) {
|
|
1985
|
+
this.ui.cliAgentSelector.style.display = 'inline-block';
|
|
1986
|
+
}
|
|
1987
|
+
if (this.ui.acpAgentSelector && this.state.agents.some(a => a.protocol === 'acp')) {
|
|
1988
|
+
this.ui.acpAgentSelector.style.display = 'inline-block';
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1912
1991
|
|
|
1913
1992
|
/**
|
|
1914
1993
|
* Apply agent and model selection based on conversation state
|
|
1915
1994
|
* Consolidates duplicate logic for cached and fresh conversation loads
|
|
1916
1995
|
*/
|
|
1917
|
-
applyAgentAndModelSelection(conversation, hasActivity) {
|
|
1918
|
-
const agentId = conversation.agentId || conversation.agentType || 'claude-code';
|
|
1919
|
-
const model = conversation.model || null;
|
|
1920
|
-
|
|
1921
|
-
if (hasActivity) {
|
|
1922
|
-
this.lockAgentAndModel(agentId, model);
|
|
1923
|
-
} else {
|
|
1924
|
-
this.unlockAgentAndModel();
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
if (
|
|
1930
|
-
this.ui.
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1996
|
+
applyAgentAndModelSelection(conversation, hasActivity) {
|
|
1997
|
+
const agentId = conversation.agentId || conversation.agentType || 'claude-code';
|
|
1998
|
+
const model = conversation.model || null;
|
|
1999
|
+
|
|
2000
|
+
if (hasActivity) {
|
|
2001
|
+
this.lockAgentAndModel(agentId, model);
|
|
2002
|
+
} else {
|
|
2003
|
+
this.unlockAgentAndModel();
|
|
2004
|
+
// Find the agent to determine protocol
|
|
2005
|
+
const agent = this.state.agents.find(a => a.id === agentId);
|
|
2006
|
+
|
|
2007
|
+
if (agent) {
|
|
2008
|
+
if (agent.protocol === 'cli') {
|
|
2009
|
+
if (this.ui.cliAgentSelector) {
|
|
2010
|
+
this.ui.cliAgentSelector.value = agentId;
|
|
2011
|
+
this.ui.cliAgentSelector.style.display = 'inline-block';
|
|
2012
|
+
}
|
|
2013
|
+
if (this.ui.acpAgentSelector) {
|
|
2014
|
+
this.ui.acpAgentSelector.value = '';
|
|
2015
|
+
this.ui.acpAgentSelector.style.display = 'none';
|
|
2016
|
+
}
|
|
2017
|
+
} else {
|
|
2018
|
+
if (this.ui.acpAgentSelector) {
|
|
2019
|
+
this.ui.acpAgentSelector.value = agentId;
|
|
2020
|
+
this.ui.acpAgentSelector.style.display = 'inline-block';
|
|
2021
|
+
}
|
|
2022
|
+
if (this.ui.cliAgentSelector) {
|
|
2023
|
+
this.ui.cliAgentSelector.value = '';
|
|
2024
|
+
this.ui.cliAgentSelector.style.display = 'none';
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
this.loadModelsForAgent(agentId).then(() => {
|
|
2030
|
+
if (model && this.ui.modelSelector) {
|
|
2031
|
+
this.ui.modelSelector.value = model;
|
|
2032
|
+
}
|
|
2033
|
+
});
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
1935
2036
|
|
|
1936
2037
|
/**
|
|
1937
2038
|
* Load conversations
|
|
@@ -2493,12 +2594,25 @@ class AgentGUIClient {
|
|
|
2493
2594
|
}
|
|
2494
2595
|
}
|
|
2495
2596
|
|
|
2496
|
-
/**
|
|
2497
|
-
* Get
|
|
2498
|
-
*/
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2597
|
+
/**
|
|
2598
|
+
* Get current selected agent
|
|
2599
|
+
*/
|
|
2600
|
+
getCurrentAgent() {
|
|
2601
|
+
if (this.ui.cliAgentSelector?.value) {
|
|
2602
|
+
return this.ui.cliAgentSelector.value;
|
|
2603
|
+
}
|
|
2604
|
+
if (this.ui.acpAgentSelector?.value) {
|
|
2605
|
+
return this.ui.acpAgentSelector.value;
|
|
2606
|
+
}
|
|
2607
|
+
return 'claude-code';
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
/**
|
|
2611
|
+
* Get current selected model
|
|
2612
|
+
*/
|
|
2613
|
+
getCurrentModel() {
|
|
2614
|
+
return this.ui.modelSelector?.value || null;
|
|
2615
|
+
}
|
|
2502
2616
|
|
|
2503
2617
|
/**
|
|
2504
2618
|
* Get metrics
|