ninja-terminals 2.1.0 → 2.1.1

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": "ninja-terminals",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Multi-terminal Claude Code orchestrator with DAG task management, permission hooks, and resilience",
5
5
  "main": "server.js",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -339,11 +339,23 @@ function createTerminalUI(termData) {
339
339
  progressFill.style.width = `${progress || 0}%`;
340
340
  progressTrack.appendChild(progressFill);
341
341
 
342
+ // Close button (X)
343
+ const closeBtn = document.createElement('button');
344
+ closeBtn.className = 'close-btn';
345
+ closeBtn.innerHTML = '×';
346
+ closeBtn.title = 'Close terminal';
347
+ closeBtn.addEventListener('mousedown', (e) => {
348
+ e.preventDefault();
349
+ e.stopPropagation();
350
+ removeTerminal(id);
351
+ });
352
+
342
353
  header.appendChild(labelEl);
343
354
  header.appendChild(stateEl);
344
355
  header.appendChild(elapsedEl);
345
356
  header.appendChild(spacer);
346
357
  header.appendChild(actionsEl);
358
+ header.appendChild(closeBtn);
347
359
  header.appendChild(progressTrack);
348
360
 
349
361
  // Double-click header to maximize/restore
@@ -1010,6 +1022,13 @@ async function startApp() {
1010
1022
  setupSidebar();
1011
1023
  setupAddTask();
1012
1024
  setupLearnings();
1025
+ setupAddTerminal();
1026
+
1027
+ // Clear all button
1028
+ const clearBtn = document.getElementById('clear-all-btn');
1029
+ if (clearBtn) {
1030
+ clearBtn.addEventListener('click', clearAllTerminals);
1031
+ }
1013
1032
 
1014
1033
  // Load existing terminals
1015
1034
  try {
@@ -1047,6 +1066,53 @@ async function startApp() {
1047
1066
 
1048
1067
  // ── Learnings Module ───────────────────────────────────────────
1049
1068
 
1069
+ function setupAddTerminal() {
1070
+ const btn = document.getElementById('add-terminal-btn');
1071
+ if (!btn) return;
1072
+
1073
+ // Store last used directory
1074
+ let lastCwd = localStorage.getItem('ninja-last-cwd') || '/Users/davidmini/Desktop/Projects';
1075
+
1076
+ btn.addEventListener('click', async () => {
1077
+ try {
1078
+ const cwd = prompt('Working directory:', lastCwd);
1079
+ if (!cwd) return;
1080
+
1081
+ lastCwd = cwd;
1082
+ localStorage.setItem('ninja-last-cwd', cwd);
1083
+
1084
+ const res = await fetch(`${API_BASE}/api/terminals`, {
1085
+ method: 'POST',
1086
+ headers: { 'Content-Type': 'application/json', ...auth.getAuthHeader() },
1087
+ body: JSON.stringify({ cwd }),
1088
+ });
1089
+
1090
+ if (!res.ok) {
1091
+ const err = await res.json();
1092
+ alert(`Failed to create terminal: ${err.error || 'Unknown error'}`);
1093
+ return;
1094
+ }
1095
+
1096
+ const terminal = await res.json();
1097
+ createTerminalUI(terminal);
1098
+ addFeedEntry(`Terminal added: T${terminal.id}`);
1099
+ } catch (err) {
1100
+ console.error('Failed to add terminal:', err);
1101
+ alert('Failed to add terminal');
1102
+ }
1103
+ });
1104
+ }
1105
+
1106
+ async function clearAllTerminals() {
1107
+ if (!confirm('Close all terminals and start fresh?')) return;
1108
+
1109
+ const ids = Array.from(state.terminals.keys());
1110
+ for (const id of ids) {
1111
+ await removeTerminal(id);
1112
+ }
1113
+ addFeedEntry('All terminals cleared');
1114
+ }
1115
+
1050
1116
  function setupLearnings() {
1051
1117
  const btn = document.getElementById('learnings-btn');
1052
1118
  const overlay = document.getElementById('learnings-overlay');
package/public/index.html CHANGED
@@ -60,6 +60,8 @@
60
60
  <div class="logo-card">
61
61
  <span class="logo">NINJA TERMINALS</span>
62
62
  <span class="logo-sub">Multi-Agent Orchestrator</span>
63
+ <button id="add-terminal-btn" class="add-terminal-btn" title="Add Terminal">+</button>
64
+ <button id="clear-all-btn" class="clear-all-btn" title="Clear All Terminals">🗑</button>
63
65
  <button id="learnings-btn" class="learnings-btn" title="View Session Learnings">🧠</button>
64
66
  <button id="logout-btn" class="logout-btn" title="Sign out">Logout</button>
65
67
  </div>
package/public/style.css CHANGED
@@ -976,3 +976,60 @@ main {
976
976
  .learnings-btn:hover {
977
977
  background: var(--border);
978
978
  }
979
+
980
+ /* ── Terminal Close Button ─────────────────────── */
981
+
982
+ .close-btn {
983
+ background: none;
984
+ border: none;
985
+ color: var(--text-muted);
986
+ font-size: 20px;
987
+ line-height: 1;
988
+ padding: 2px 8px;
989
+ cursor: pointer;
990
+ opacity: 0.5;
991
+ transition: opacity 0.15s, color 0.15s;
992
+ margin-left: 8px;
993
+ }
994
+
995
+ .close-btn:hover {
996
+ opacity: 1;
997
+ color: #ff6b6b;
998
+ }
999
+
1000
+ /* ── Add Terminal Button ─────────────────────────── */
1001
+
1002
+ .add-terminal-btn {
1003
+ background: var(--feed-t1);
1004
+ border: none;
1005
+ color: var(--bg);
1006
+ font-size: 20px;
1007
+ font-weight: bold;
1008
+ line-height: 1;
1009
+ padding: 4px 10px;
1010
+ border-radius: 4px;
1011
+ cursor: pointer;
1012
+ transition: background 0.15s, transform 0.15s;
1013
+ }
1014
+
1015
+ .add-terminal-btn:hover {
1016
+ background: var(--feed-t2);
1017
+ transform: scale(1.1);
1018
+ }
1019
+
1020
+ /* ── Clear All Button ─────────────────────────────── */
1021
+
1022
+ .clear-all-btn {
1023
+ background: none;
1024
+ border: none;
1025
+ font-size: 16px;
1026
+ padding: 4px 8px;
1027
+ cursor: pointer;
1028
+ opacity: 0.6;
1029
+ transition: opacity 0.15s, transform 0.15s;
1030
+ }
1031
+
1032
+ .clear-all-btn:hover {
1033
+ opacity: 1;
1034
+ transform: scale(1.1);
1035
+ }