agentgui 1.0.335 → 1.0.337

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.335",
3
+ "version": "1.0.337",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -3419,6 +3419,35 @@ wss.on('connection', (ws, req) => {
3419
3419
  requestId: data.requestId,
3420
3420
  timestamp: Date.now()
3421
3421
  }));
3422
+ } else if (data.type === 'terminal_start') {
3423
+ if (ws.terminalProc) {
3424
+ try { ws.terminalProc.kill(); } catch(e) {}
3425
+ }
3426
+ const { spawn } = require('child_process');
3427
+ const shell = process.env.SHELL || '/bin/bash';
3428
+ const cwd = data.cwd || process.env.STARTUP_CWD || process.env.HOME || '/';
3429
+ const proc = spawn(shell, [], { cwd, env: { ...process.env, TERM: 'xterm-256color', COLORTERM: 'truecolor' }, stdio: ['pipe', 'pipe', 'pipe'] });
3430
+ ws.terminalProc = proc;
3431
+ proc.stdout.on('data', (chunk) => {
3432
+ if (ws.readyState === 1) ws.send(JSON.stringify({ type: 'terminal_output', data: chunk.toString('base64'), encoding: 'base64' }));
3433
+ });
3434
+ proc.stderr.on('data', (chunk) => {
3435
+ if (ws.readyState === 1) ws.send(JSON.stringify({ type: 'terminal_output', data: chunk.toString('base64'), encoding: 'base64' }));
3436
+ });
3437
+ proc.on('exit', (code) => {
3438
+ if (ws.readyState === 1) ws.send(JSON.stringify({ type: 'terminal_exit', code }));
3439
+ ws.terminalProc = null;
3440
+ });
3441
+ ws.send(JSON.stringify({ type: 'terminal_started', timestamp: Date.now() }));
3442
+ } else if (data.type === 'terminal_input') {
3443
+ if (ws.terminalProc && ws.terminalProc.stdin.writable) {
3444
+ ws.terminalProc.stdin.write(Buffer.from(data.data, 'base64'));
3445
+ }
3446
+ } else if (data.type === 'terminal_stop') {
3447
+ if (ws.terminalProc) {
3448
+ try { ws.terminalProc.kill(); } catch(e) {}
3449
+ ws.terminalProc = null;
3450
+ }
3422
3451
  }
3423
3452
  } catch (e) {
3424
3453
  console.error('WebSocket message parse error:', e.message);
@@ -3432,6 +3461,7 @@ wss.on('connection', (ws, req) => {
3432
3461
 
3433
3462
  ws.on('pong', () => { ws.isAlive = true; });
3434
3463
  ws.on('close', () => {
3464
+ if (ws.terminalProc) { try { ws.terminalProc.kill(); } catch(e) {} ws.terminalProc = null; }
3435
3465
  syncClients.delete(ws);
3436
3466
  for (const sub of ws.subscriptions) {
3437
3467
  const idx = subscriptionIndex.get(sub);
package/static/index.html CHANGED
@@ -63,7 +63,6 @@
63
63
  .app-shell {
64
64
  display: flex;
65
65
  height: 100dvh;
66
- height: 100vh;
67
66
  overflow: hidden;
68
67
  padding-top: env(safe-area-inset-top);
69
68
  padding-bottom: env(safe-area-inset-bottom);
@@ -496,7 +495,7 @@
496
495
  .terminal-container {
497
496
  flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #1e1e1e;
498
497
  }
499
- .terminal-output { flex: 1; overflow: hidden; }
498
+ .terminal-output { flex: 1; overflow: hidden; position: relative; }
500
499
 
501
500
  .models-container {
502
501
  flex: 1; display: flex; flex-direction: column; overflow-y: auto;
@@ -835,6 +834,9 @@
835
834
  font-size: 0.8rem;
836
835
  cursor: pointer;
837
836
  flex-shrink: 0;
837
+ width: auto;
838
+ min-width: 80px;
839
+ max-width: 200px;
838
840
  }
839
841
 
840
842
  .agent-selector:disabled, .model-selector:disabled {
@@ -852,7 +854,9 @@
852
854
  font-size: 0.8rem;
853
855
  cursor: pointer;
854
856
  flex-shrink: 0;
855
- max-width: 160px;
857
+ width: auto;
858
+ min-width: 80px;
859
+ max-width: 220px;
856
860
  }
857
861
 
858
862
  .model-selector:empty, .model-selector[data-empty="true"] {
@@ -2051,24 +2055,24 @@
2051
2055
  .tool-color-default > .folded-tool-body { border-top-color: #a5f3fc; }
2052
2056
  html.dark .tool-color-default > .folded-tool-body { border-top-color: #164e63; }
2053
2057
 
2054
- .block-type-tool_result { background: #f0fdf4; }
2055
- html.dark .block-type-tool_result { background: #0a1f0f; }
2056
- .block-type-tool_result .tool-result-status { background: #dcfce7; }
2057
- html.dark .block-type-tool_result .tool-result-status { background: #0f2b1a; }
2058
+ .block-type-tool_result { background: #f3f4f6; }
2059
+ html.dark .block-type-tool_result { background: #1f2937; }
2060
+ .block-type-tool_result .tool-result-status { background: #e5e7eb; }
2061
+ html.dark .block-type-tool_result .tool-result-status { background: #374151; }
2058
2062
  .block-type-tool_result .folded-tool-icon { color: #16a34a; }
2059
2063
  html.dark .block-type-tool_result .folded-tool-icon { color: #4ade80; }
2060
- .block-type-tool_result .folded-tool-name { color: #166534; }
2061
- html.dark .block-type-tool_result .folded-tool-name { color: #86efac; }
2062
- .block-type-tool_result > .folded-tool-body { border-top-color: #bbf7d0; }
2063
- html.dark .block-type-tool_result > .folded-tool-body { border-top-color: #166534; }
2064
- .block-type-tool_result.tool-result-error { background: #fef2f2; }
2065
- html.dark .block-type-tool_result.tool-result-error { background: #1c0f0f; }
2066
- .block-type-tool_result.tool-result-error .tool-result-status { background: #fee2e2; }
2067
- html.dark .block-type-tool_result.tool-result-error .tool-result-status { background: #2c1010; }
2064
+ .block-type-tool_result .folded-tool-name { color: #374151; }
2065
+ html.dark .block-type-tool_result .folded-tool-name { color: #d1d5db; }
2066
+ .block-type-tool_result > .folded-tool-body { border-top-color: #d1d5db; }
2067
+ html.dark .block-type-tool_result > .folded-tool-body { border-top-color: #4b5563; }
2068
+ .block-type-tool_result.tool-result-error { background: #f3f4f6; }
2069
+ html.dark .block-type-tool_result.tool-result-error { background: #1f2937; }
2070
+ .block-type-tool_result.tool-result-error .tool-result-status { background: #e5e7eb; }
2071
+ html.dark .block-type-tool_result.tool-result-error .tool-result-status { background: #374151; }
2068
2072
  .block-type-tool_result.tool-result-error .folded-tool-icon { color: #dc2626; }
2069
2073
  html.dark .block-type-tool_result.tool-result-error .folded-tool-icon { color: #f87171; }
2070
- .block-type-tool_result.tool-result-error .folded-tool-name { color: #991b1b; }
2071
- html.dark .block-type-tool_result.tool-result-error .folded-tool-name { color: #fca5a5; }
2074
+ .block-type-tool_result.tool-result-error .folded-tool-name { color: #374151; }
2075
+ html.dark .block-type-tool_result.tool-result-error .folded-tool-name { color: #d1d5db; }
2072
2076
 
2073
2077
  .block-type-code { background: #1e293b; }
2074
2078
  html.dark .block-type-code { background: #0f172a; }
@@ -2176,51 +2180,51 @@
2176
2180
 
2177
2181
  /* --- Tool result success styling in body --- */
2178
2182
  .tool-result-success .tool-result-status {
2179
- background: #dcfce7;
2183
+ background: #e5e7eb;
2180
2184
  padding: 0.4rem 0.75rem;
2181
2185
  }
2182
2186
  html.dark .tool-result-success .tool-result-status {
2183
- background: #0f2b1a;
2187
+ background: #374151;
2184
2188
  }
2185
2189
  .tool-result-success .folded-tool-icon { color: #16a34a; }
2186
2190
  html.dark .tool-result-success .folded-tool-icon { color: #4ade80; }
2187
- .tool-result-success .folded-tool-name { color: #166534; font-weight: 600; }
2188
- html.dark .tool-result-success .folded-tool-name { color: #86efac; }
2191
+ .tool-result-success .folded-tool-name { color: #374151; font-weight: 600; }
2192
+ html.dark .tool-result-success .folded-tool-name { color: #d1d5db; }
2189
2193
 
2190
2194
  /* --- Tool_use parent: has-success / has-error indicators on header --- */
2191
- .folded-tool.has-success { background: #f0fdf4; }
2192
- html.dark .folded-tool.has-success { background: #0a1f0f; }
2193
- .folded-tool.has-success > .folded-tool-bar { background: #dcfce7; }
2194
- html.dark .folded-tool.has-success > .folded-tool-bar { background: #0f2b1a; }
2195
- .folded-tool.has-success > .folded-tool-bar:hover { background: #bbf7d0; }
2196
- html.dark .folded-tool.has-success > .folded-tool-bar:hover { background: #14532d; }
2195
+ .folded-tool.has-success { background: #f3f4f6; }
2196
+ html.dark .folded-tool.has-success { background: #1f2937; }
2197
+ .folded-tool.has-success > .folded-tool-bar { background: #e5e7eb; }
2198
+ html.dark .folded-tool.has-success > .folded-tool-bar { background: #374151; }
2199
+ .folded-tool.has-success > .folded-tool-bar:hover { background: #d1d5db; }
2200
+ html.dark .folded-tool.has-success > .folded-tool-bar:hover { background: #4b5563; }
2197
2201
  .folded-tool.has-success > .folded-tool-bar::before { color: #16a34a; }
2198
2202
  html.dark .folded-tool.has-success > .folded-tool-bar::before { color: #4ade80; }
2199
2203
  .folded-tool.has-success .folded-tool-icon { color: #16a34a; }
2200
2204
  html.dark .folded-tool.has-success .folded-tool-icon { color: #4ade80; }
2201
- .folded-tool.has-success .folded-tool-name { color: #166534; }
2202
- html.dark .folded-tool.has-success .folded-tool-name { color: #86efac; }
2203
- .folded-tool.has-success .folded-tool-desc { color: #15803d; }
2204
- html.dark .folded-tool.has-success .folded-tool-desc { color: #4ade80; }
2205
- .folded-tool.has-success > .folded-tool-body { border-top-color: #bbf7d0; }
2206
- html.dark .folded-tool.has-success > .folded-tool-body { border-top-color: #166534; }
2207
-
2208
- .folded-tool.has-error { background: #fef2f2; }
2209
- html.dark .folded-tool.has-error { background: #1c0f0f; }
2210
- .folded-tool.has-error > .folded-tool-bar { background: #fee2e2; }
2211
- html.dark .folded-tool.has-error > .folded-tool-bar { background: #2c1010; }
2212
- .folded-tool.has-error > .folded-tool-bar:hover { background: #fecaca; }
2213
- html.dark .folded-tool.has-error > .folded-tool-bar:hover { background: #451a1a; }
2205
+ .folded-tool.has-success .folded-tool-name { color: #374151; }
2206
+ html.dark .folded-tool.has-success .folded-tool-name { color: #d1d5db; }
2207
+ .folded-tool.has-success .folded-tool-desc { color: #6b7280; }
2208
+ html.dark .folded-tool.has-success .folded-tool-desc { color: #9ca3af; }
2209
+ .folded-tool.has-success > .folded-tool-body { border-top-color: #d1d5db; }
2210
+ html.dark .folded-tool.has-success > .folded-tool-body { border-top-color: #4b5563; }
2211
+
2212
+ .folded-tool.has-error { background: #f3f4f6; }
2213
+ html.dark .folded-tool.has-error { background: #1f2937; }
2214
+ .folded-tool.has-error > .folded-tool-bar { background: #e5e7eb; }
2215
+ html.dark .folded-tool.has-error > .folded-tool-bar { background: #374151; }
2216
+ .folded-tool.has-error > .folded-tool-bar:hover { background: #d1d5db; }
2217
+ html.dark .folded-tool.has-error > .folded-tool-bar:hover { background: #4b5563; }
2214
2218
  .folded-tool.has-error > .folded-tool-bar::before { color: #ef4444; }
2215
2219
  html.dark .folded-tool.has-error > .folded-tool-bar::before { color: #f87171; }
2216
2220
  .folded-tool.has-error .folded-tool-icon { color: #ef4444; }
2217
2221
  html.dark .folded-tool.has-error .folded-tool-icon { color: #f87171; }
2218
- .folded-tool.has-error .folded-tool-name { color: #991b1b; }
2219
- html.dark .folded-tool.has-error .folded-tool-name { color: #fca5a5; }
2220
- .folded-tool.has-error .folded-tool-desc { color: #b91c1c; }
2221
- html.dark .folded-tool.has-error .folded-tool-desc { color: #f87171; }
2222
- .folded-tool.has-error > .folded-tool-body { border-top-color: #fecaca; }
2223
- html.dark .folded-tool.has-error > .folded-tool-body { border-top-color: #7f1d1d; }
2222
+ .folded-tool.has-error .folded-tool-name { color: #374151; }
2223
+ html.dark .folded-tool.has-error .folded-tool-name { color: #d1d5db; }
2224
+ .folded-tool.has-error .folded-tool-desc { color: #6b7280; }
2225
+ html.dark .folded-tool.has-error .folded-tool-desc { color: #9ca3af; }
2226
+ .folded-tool.has-error > .folded-tool-body { border-top-color: #d1d5db; }
2227
+ html.dark .folded-tool.has-error > .folded-tool-body { border-top-color: #4b5563; }
2224
2228
 
2225
2229
  /* --- Success/Error status icons in header --- */
2226
2230
  .folded-tool.has-success > .folded-tool-bar .folded-tool-icon::after,
@@ -3042,12 +3046,12 @@
3042
3046
  </div>
3043
3047
 
3044
3048
  <!-- View toggle bar (hidden by default) -->
3045
- <div class="view-toggle-bar" id="viewToggleBar" style="display:none;">
3049
+ <div class="view-toggle-bar" id="viewToggleBar">
3046
3050
  <button class="view-toggle-btn active" data-view="chat">Chat</button>
3047
3051
  <button class="view-toggle-btn" data-view="files">Files</button>
3048
3052
  <button class="view-toggle-btn" data-view="voice" style="display:none;">Voice</button>
3049
3053
  <button class="view-toggle-btn" data-view="models">Models</button>
3050
- <button class="view-toggle-btn" data-view="terminal" id="terminalTabBtn" style="display:none;">Terminal</button>
3054
+ <button class="view-toggle-btn" data-view="terminal" id="terminalTabBtn">Terminal</button>
3051
3055
  </div>
3052
3056
 
3053
3057
  <!-- Messages scroll area -->
@@ -3189,6 +3193,7 @@
3189
3193
  <script defer src="/gm/js/client.js"></script>
3190
3194
  <script type="module" src="/gm/js/voice.js"></script>
3191
3195
  <script defer src="/gm/js/features.js"></script>
3196
+ <script defer src="/gm/js/terminal.js"></script>
3192
3197
  <script defer src="/gm/js/script-runner.js"></script>
3193
3198
  <script defer src="/gm/js/agent-auth.js"></script>
3194
3199
 
@@ -0,0 +1,105 @@
1
+ (function() {
2
+ var ws = null;
3
+ var term = null;
4
+ var fitAddon = null;
5
+ var termActive = false;
6
+ var BASE = window.__BASE_URL || '';
7
+
8
+ function getWsUrl() {
9
+ var proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
10
+ return proto + '//' + location.host + BASE + '/sync';
11
+ }
12
+
13
+ function ensureTerm() {
14
+ var output = document.getElementById('terminalOutput');
15
+ if (!output) return false;
16
+ if (term) return true;
17
+ if (!window.Terminal || !window.FitAddon) return false;
18
+
19
+ term = new Terminal({
20
+ cursorBlink: true,
21
+ fontSize: 14,
22
+ fontFamily: 'Menlo, Monaco, "Courier New", monospace',
23
+ theme: {
24
+ background: '#0d1117',
25
+ foreground: '#e6edf3',
26
+ cursor: '#e6edf3',
27
+ selectionBackground: '#3b4455'
28
+ },
29
+ convertEol: false,
30
+ scrollback: 5000
31
+ });
32
+ fitAddon = new FitAddon.FitAddon();
33
+ term.loadAddon(fitAddon);
34
+ output.innerHTML = '';
35
+ term.open(output);
36
+ fitAddon.fit();
37
+
38
+ term.onData(function(data) {
39
+ if (ws && ws.readyState === WebSocket.OPEN) {
40
+ var encoded = btoa(unescape(encodeURIComponent(data)));
41
+ ws.send(JSON.stringify({ type: 'terminal_input', data: encoded }));
42
+ }
43
+ });
44
+
45
+ window.addEventListener('resize', function() {
46
+ if (fitAddon) try { fitAddon.fit(); } catch(_) {}
47
+ });
48
+ return true;
49
+ }
50
+
51
+ function connectAndStart() {
52
+ if (ws && ws.readyState === WebSocket.OPEN) {
53
+ ws.send(JSON.stringify({ type: 'terminal_start', cwd: window.__STARTUP_CWD || undefined }));
54
+ return;
55
+ }
56
+ ws = new WebSocket(getWsUrl());
57
+ ws.onopen = function() {
58
+ ws.send(JSON.stringify({ type: 'terminal_start', cwd: window.__STARTUP_CWD || undefined }));
59
+ };
60
+ ws.onmessage = function(e) {
61
+ try {
62
+ var msg = JSON.parse(e.data);
63
+ if (msg.type === 'terminal_output' && term) {
64
+ var raw = msg.encoding === 'base64'
65
+ ? decodeURIComponent(escape(atob(msg.data)))
66
+ : msg.data;
67
+ term.write(raw);
68
+ } else if (msg.type === 'terminal_exit' && term) {
69
+ term.write('\r\n[Process exited with code ' + msg.code + ']\r\n');
70
+ if (termActive) setTimeout(connectAndStart, 2000);
71
+ }
72
+ } catch(_) {}
73
+ };
74
+ ws.onclose = function() {
75
+ if (termActive) setTimeout(connectAndStart, 2000);
76
+ };
77
+ }
78
+
79
+ function startTerminal() {
80
+ if (!ensureTerm()) {
81
+ setTimeout(startTerminal, 200);
82
+ return;
83
+ }
84
+ termActive = true;
85
+ connectAndStart();
86
+ setTimeout(function() { if (fitAddon) try { fitAddon.fit(); } catch(_) {} }, 100);
87
+ }
88
+
89
+ function stopTerminal() {
90
+ termActive = false;
91
+ if (ws && ws.readyState === WebSocket.OPEN) {
92
+ ws.send(JSON.stringify({ type: 'terminal_stop' }));
93
+ }
94
+ }
95
+
96
+ window.addEventListener('view-switched', function(e) {
97
+ if (e.detail.view === 'terminal') {
98
+ startTerminal();
99
+ } else if (termActive) {
100
+ stopTerminal();
101
+ }
102
+ });
103
+
104
+ window.terminalModule = { start: startTerminal, stop: stopTerminal };
105
+ })();