agentgui 1.0.542 → 1.0.544

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.
@@ -9,6 +9,7 @@ const TOOLS = [
9
9
  { id: 'gm-oc', name: 'gm-oc', pkg: 'gm-oc', pluginId: 'gm-oc' },
10
10
  { id: 'gm-gc', name: 'gm-gc', pkg: 'gm-gc', pluginId: 'gm' },
11
11
  { id: 'gm-kilo', name: 'gm-kilo', pkg: 'gm-kilo', pluginId: 'gm-kilo' },
12
+ { id: 'codex', name: '@openai/codex', pkg: '@openai/codex', pluginId: 'codex' },
12
13
  ];
13
14
 
14
15
  const statusCache = new Map();
@@ -76,6 +77,17 @@ const getInstalledVersion = (pkg, pluginId = null) => {
76
77
  console.warn(`[tool-manager] Failed to parse ${kiloPath}:`, e.message);
77
78
  }
78
79
  }
80
+
81
+ // Check Codex CLI (stored at ~/.codex)
82
+ const codexPath = path.join(homeDir, '.codex', 'plugin.json');
83
+ if (fs.existsSync(codexPath)) {
84
+ try {
85
+ const pluginJson = JSON.parse(fs.readFileSync(codexPath, 'utf-8'));
86
+ if (pluginJson.version) return pluginJson.version;
87
+ } catch (e) {
88
+ console.warn(`[tool-manager] Failed to parse ${codexPath}:`, e.message);
89
+ }
90
+ }
79
91
  } catch (_) {}
80
92
  return null;
81
93
  };
@@ -129,6 +141,7 @@ const checkToolInstalled = (pluginId) => {
129
141
  if (fs.existsSync(path.join(homeDir, '.config', 'kilo', 'agents', pluginId + '.md'))) return true;
130
142
  if (fs.existsSync(path.join(homeDir, '.config', 'opencode', 'agents', 'gm.md'))) return true;
131
143
  if (fs.existsSync(path.join(homeDir, '.config', 'kilo', 'agents', 'gm.md'))) return true;
144
+ if (pluginId === 'codex' && fs.existsSync(path.join(homeDir, '.codex', 'plugin.json'))) return true;
132
145
  } catch (_) {}
133
146
  return false;
134
147
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.542",
3
+ "version": "1.0.544",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "server.js",
package/server.js CHANGED
@@ -3360,7 +3360,7 @@ function serveFile(filePath, res, req) {
3360
3360
  'Content-Type': contentType,
3361
3361
  'Content-Length': stats.size,
3362
3362
  'ETag': etag,
3363
- 'Cache-Control': 'public, max-age=3600, must-revalidate'
3363
+ 'Cache-Control': ['.js', '.css'].includes(ext) ? 'no-cache' : 'public, max-age=3600, must-revalidate'
3364
3364
  };
3365
3365
  if (acceptsEncoding(req, 'br') && stats.size > 860) {
3366
3366
  const stream = fs.createReadStream(filePath);
package/static/index.html CHANGED
@@ -864,9 +864,15 @@
864
864
  display: inline-block;
865
865
  }
866
866
 
867
+ .message-input-container {
868
+ position: relative;
869
+ flex: 1;
870
+ display: flex;
871
+ }
872
+
867
873
  .message-textarea {
868
874
  flex: 1;
869
- padding: 0.625rem 0.875rem;
875
+ padding: 0.625rem 2.75rem 0.625rem 0.875rem;
870
876
  border: none;
871
877
  border-radius: 0.75rem;
872
878
  background-color: var(--color-bg-secondary);
@@ -1144,11 +1150,14 @@
1144
1150
  }
1145
1151
 
1146
1152
  .voice-mic-btn {
1153
+ position: absolute;
1154
+ top: 4px;
1155
+ right: 4px;
1147
1156
  display: flex;
1148
1157
  align-items: center;
1149
1158
  justify-content: center;
1150
- width: 44px;
1151
- height: 44px;
1159
+ width: 36px;
1160
+ height: 36px;
1152
1161
  background: var(--color-bg-secondary);
1153
1162
  color: var(--color-text-secondary);
1154
1163
  border: 2px solid var(--color-border);
@@ -3187,21 +3196,23 @@
3187
3196
  <select class="agent-selector cli-selector" data-cli-selector title="Select CLI tool"></select>
3188
3197
  <select class="agent-selector sub-agent-selector" data-agent-selector title="Select sub-agent" style="display:none"></select>
3189
3198
  <select class="model-selector" data-model-selector title="Select model" data-empty="true"></select>
3190
- <textarea
3191
- class="message-textarea"
3192
- data-message-input
3193
- placeholder="Message AgentGUI... (Ctrl+Enter to send)"
3194
- aria-label="Message input"
3195
- rows="1"
3196
- ></textarea>
3197
- <button class="voice-mic-btn" id="chatMicBtn" title="Record voice input" aria-label="Voice input">
3198
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3199
- <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
3200
- <path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
3201
- <line x1="12" y1="19" x2="12" y2="23"/>
3202
- <line x1="8" y1="23" x2="16" y2="23"/>
3203
- </svg>
3204
- </button>
3199
+ <div class="message-input-container">
3200
+ <textarea
3201
+ class="message-textarea"
3202
+ data-message-input
3203
+ placeholder="Message AgentGUI... (Ctrl+Enter to send)"
3204
+ aria-label="Message input"
3205
+ rows="1"
3206
+ ></textarea>
3207
+ <button class="voice-mic-btn" id="chatMicBtn" title="Record voice input" aria-label="Voice input">
3208
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3209
+ <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/>
3210
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2"/>
3211
+ <line x1="12" y1="19" x2="12" y2="23"/>
3212
+ <line x1="8" y1="23" x2="16" y2="23"/>
3213
+ </svg>
3214
+ </button>
3215
+ </div>
3205
3216
  <button class="inject-btn" id="injectBtn" title="Inject instructions into running agent" aria-label="Inject instructions">
3206
3217
  <svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18">
3207
3218
  <path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"/>
@@ -873,6 +873,17 @@ class StreamingRenderer {
873
873
  }
874
874
  }
875
875
 
876
+ // Handle Claude image content block arrays: [{type:"image", source:{type:"base64", data:"...", media_type:"..."}}]
877
+ if (Array.isArray(parsed) && parsed.length > 0) {
878
+ const imgParts = parsed.filter(b => b.type === 'image' && b.source && b.source.type === 'base64' && b.source.data);
879
+ if (imgParts.length > 0) {
880
+ return imgParts.map(b => {
881
+ const mime = b.source.media_type || 'image/png';
882
+ return `<div style="padding:0.5rem"><img src="data:${esc(mime)};base64,${b.source.data}" style="max-width:100%;max-height:24rem;border-radius:0.375rem"></div>`;
883
+ }).join('');
884
+ }
885
+ }
886
+
876
887
  // For other JSON, render as itemized key-value structure
877
888
  return `<div style="padding:0.5rem 0.75rem">${StreamingRenderer.renderParamsHTML(parsed, 0, esc)}</div>`;
878
889
  } catch (e) {