@openagents-org/agent-launcher 0.1.10 → 0.1.11

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/tui.js +51 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagents-org/agent-launcher",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "OpenAgents Launcher — install, configure, and run AI coding agents from your terminal",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/tui.js CHANGED
@@ -203,18 +203,19 @@ function createTUI() {
203
203
  style: { fg: 'white' },
204
204
  });
205
205
 
206
- // ── Footer ──
207
- const footer = blessed.box({
206
+ // ── Footer (clickable buttons) ──
207
+ const footerBar = blessed.box({
208
208
  bottom: 0, left: 0, width: '100%', height: 1,
209
209
  tags: true,
210
210
  style: { bg: COLORS.footerBg, fg: COLORS.footerFg },
211
211
  });
212
+ let footerButtons = [];
212
213
 
213
214
  screen.append(header);
214
215
  screen.append(titleBox);
215
216
  screen.append(agentPanel);
216
217
  screen.append(logPanel);
217
- screen.append(footer);
218
+ screen.append(footerBar);
218
219
 
219
220
  // ── Log helper ──
220
221
  function log(msg) {
@@ -223,36 +224,68 @@ function createTUI() {
223
224
  screen.render();
224
225
  }
225
226
 
226
- // ── Footer rendering (context-aware) ──
227
+ // ── Footer rendering (context-aware, clickable) ──
228
+ // Maps footer action labels to the key they simulate
229
+ const footerKeyMap = {
230
+ 'Install': 'i', 'New': 'n', 'Start': 's', 'Stop': 'x',
231
+ 'Configure': 'e', 'Connect': 'c', 'Disconnect': 'd',
232
+ 'Workspace': 'w', 'Remove': 'delete', 'Daemon': 'u',
233
+ 'Refresh': 'r', 'Quit': 'q',
234
+ };
235
+
227
236
  function updateFooter() {
228
237
  const agent = agentRows[agentList.selected];
229
- const parts = [];
238
+ const items = [];
230
239
 
231
- parts.push('{cyan-fg}i{/cyan-fg} Install');
232
- parts.push('{cyan-fg}n{/cyan-fg} New');
240
+ items.push({ key: 'i', label: 'Install' });
241
+ items.push({ key: 'n', label: 'New' });
233
242
 
234
243
  if (agent && agent.configured) {
235
244
  const isRunning = ['running', 'online', 'starting', 'reconnecting'].includes(agent.state);
236
245
  const isStopped = ['stopped', 'error'].includes(agent.state);
237
246
 
238
- if (isStopped) parts.push('{cyan-fg}s{/cyan-fg} Start');
239
- if (isRunning) parts.push('{cyan-fg}x{/cyan-fg} Stop');
247
+ if (isStopped) items.push({ key: 's', label: 'Start' });
248
+ if (isRunning) items.push({ key: 'x', label: 'Stop' });
240
249
 
241
250
  const envFields = connector.registry.getEnvFields(agent.type);
242
- if (envFields && envFields.length > 0) parts.push('{cyan-fg}e{/cyan-fg} Configure');
251
+ if (envFields && envFields.length > 0) items.push({ key: 'e', label: 'Configure' });
243
252
 
244
- if (!agent.workspace) parts.push('{cyan-fg}c{/cyan-fg} Connect');
245
- if (agent.workspace) parts.push('{cyan-fg}d{/cyan-fg} Disconnect');
246
- if (agent.workspace) parts.push('{cyan-fg}w{/cyan-fg} Workspace');
253
+ if (!agent.workspace) items.push({ key: 'c', label: 'Connect' });
254
+ if (agent.workspace) items.push({ key: 'd', label: 'Disconnect' });
255
+ if (agent.workspace) items.push({ key: 'w', label: 'Workspace' });
247
256
 
248
- parts.push('{cyan-fg}Del{/cyan-fg} Remove');
257
+ items.push({ key: 'Del', label: 'Remove' });
249
258
  }
250
259
 
251
- parts.push('{cyan-fg}u{/cyan-fg} Daemon');
252
- parts.push('{cyan-fg}r{/cyan-fg} Refresh');
253
- parts.push('{cyan-fg}q{/cyan-fg} Quit');
260
+ items.push({ key: 'u', label: 'Daemon' });
261
+ items.push({ key: 'r', label: 'Refresh' });
262
+ items.push({ key: 'q', label: 'Quit' });
263
+
264
+ // Remove old buttons
265
+ for (const btn of footerButtons) { footerBar.remove(btn); btn.destroy(); }
266
+ footerButtons = [];
267
+
268
+ let left = 1;
269
+ for (const item of items) {
270
+ const text = `${item.key} ${item.label}`;
271
+ const btn = blessed.box({
272
+ parent: footerBar,
273
+ left, top: 0, height: 1,
274
+ width: text.length + 2,
275
+ tags: true,
276
+ mouse: true,
277
+ clickable: true,
278
+ content: `{cyan-fg}${item.key}{/cyan-fg} ${item.label}`,
279
+ style: { bg: COLORS.footerBg, fg: COLORS.footerFg, hover: { bg: 'cyan', fg: 'black' } },
280
+ });
281
+ const actionKey = footerKeyMap[item.label];
282
+ if (actionKey) {
283
+ btn.on('click', () => { screen.emit('keypress', null, { full: actionKey, name: actionKey }); });
284
+ }
285
+ footerButtons.push(btn);
286
+ left += text.length + 2;
287
+ }
254
288
 
255
- footer.setContent(' ' + parts.join(' '));
256
289
  screen.render();
257
290
  }
258
291