instar 0.23.13 → 0.23.15

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.
@@ -1206,6 +1206,213 @@
1206
1206
  to { opacity: 1; transform: translateY(0); }
1207
1207
  }
1208
1208
 
1209
+ /* ── New Session modal ────────────────────────────── */
1210
+ .modal-backdrop {
1211
+ position: fixed;
1212
+ inset: 0;
1213
+ background: rgba(0,0,0,0.6);
1214
+ z-index: 5000;
1215
+ display: flex;
1216
+ align-items: center;
1217
+ justify-content: center;
1218
+ }
1219
+
1220
+ .modal-dialog {
1221
+ background: var(--bg-panel);
1222
+ border: 1px solid var(--border);
1223
+ border-radius: 12px;
1224
+ padding: 24px;
1225
+ width: 380px;
1226
+ max-width: 90vw;
1227
+ box-shadow: 0 8px 32px rgba(0,0,0,0.6);
1228
+ }
1229
+
1230
+ .modal-dialog h3 {
1231
+ color: var(--text-bright);
1232
+ font-size: 16px;
1233
+ margin-bottom: 16px;
1234
+ }
1235
+
1236
+ .modal-field {
1237
+ margin-bottom: 14px;
1238
+ }
1239
+
1240
+ .modal-field label {
1241
+ display: block;
1242
+ font-size: 12px;
1243
+ color: var(--text-dim);
1244
+ margin-bottom: 4px;
1245
+ text-transform: uppercase;
1246
+ letter-spacing: 0.04em;
1247
+ }
1248
+
1249
+ .modal-field input[type="text"] {
1250
+ width: 100%;
1251
+ padding: 10px 12px;
1252
+ border-radius: 6px;
1253
+ border: 1px solid var(--border);
1254
+ background: var(--bg);
1255
+ color: var(--text-bright);
1256
+ font-size: 14px;
1257
+ outline: none;
1258
+ box-sizing: border-box;
1259
+ }
1260
+
1261
+ .modal-field input[type="text"]:focus {
1262
+ border-color: var(--accent-dim);
1263
+ }
1264
+
1265
+ .modal-toggle {
1266
+ display: flex;
1267
+ align-items: center;
1268
+ gap: 10px;
1269
+ cursor: pointer;
1270
+ user-select: none;
1271
+ }
1272
+
1273
+ .modal-toggle input[type="checkbox"] {
1274
+ appearance: none;
1275
+ width: 36px;
1276
+ height: 20px;
1277
+ border-radius: 10px;
1278
+ background: #333;
1279
+ position: relative;
1280
+ cursor: pointer;
1281
+ transition: background 0.2s;
1282
+ flex-shrink: 0;
1283
+ }
1284
+
1285
+ .modal-toggle input[type="checkbox"]::after {
1286
+ content: '';
1287
+ position: absolute;
1288
+ top: 2px;
1289
+ left: 2px;
1290
+ width: 16px;
1291
+ height: 16px;
1292
+ border-radius: 50%;
1293
+ background: #888;
1294
+ transition: transform 0.2s, background 0.2s;
1295
+ }
1296
+
1297
+ .modal-toggle input[type="checkbox"]:checked {
1298
+ background: var(--accent-dim);
1299
+ }
1300
+
1301
+ .modal-toggle input[type="checkbox"]:checked::after {
1302
+ transform: translateX(16px);
1303
+ background: #fff;
1304
+ }
1305
+
1306
+ .modal-toggle span {
1307
+ font-size: 13px;
1308
+ color: var(--text);
1309
+ }
1310
+
1311
+ .modal-hint {
1312
+ font-size: 11px;
1313
+ color: var(--text-dim);
1314
+ margin-top: 4px;
1315
+ font-style: italic;
1316
+ }
1317
+
1318
+ .modal-actions {
1319
+ display: flex;
1320
+ gap: 8px;
1321
+ margin-top: 20px;
1322
+ justify-content: flex-end;
1323
+ }
1324
+
1325
+ .modal-actions button {
1326
+ padding: 8px 18px;
1327
+ border-radius: 6px;
1328
+ font-size: 13px;
1329
+ font-weight: 500;
1330
+ cursor: pointer;
1331
+ border: 1px solid var(--border);
1332
+ }
1333
+
1334
+ .modal-btn-cancel {
1335
+ background: var(--bg);
1336
+ color: var(--text);
1337
+ }
1338
+
1339
+ .modal-btn-cancel:hover {
1340
+ background: var(--bg-hover);
1341
+ }
1342
+
1343
+ .modal-btn-create {
1344
+ background: var(--accent-dim);
1345
+ color: #000;
1346
+ border-color: var(--accent-dim);
1347
+ }
1348
+
1349
+ .modal-btn-create:hover {
1350
+ background: var(--accent);
1351
+ }
1352
+
1353
+ .modal-btn-create:disabled {
1354
+ opacity: 0.4;
1355
+ cursor: not-allowed;
1356
+ }
1357
+
1358
+ /* ── New session button ───────────────────────────── */
1359
+ .new-session-btn {
1360
+ width: 28px;
1361
+ height: 28px;
1362
+ border-radius: 6px;
1363
+ border: 1px solid var(--border);
1364
+ background: var(--bg);
1365
+ color: var(--accent);
1366
+ font-size: 18px;
1367
+ cursor: pointer;
1368
+ display: flex;
1369
+ align-items: center;
1370
+ justify-content: center;
1371
+ transition: all 0.15s;
1372
+ line-height: 1;
1373
+ }
1374
+
1375
+ .new-session-btn:hover {
1376
+ background: var(--bg-hover);
1377
+ border-color: var(--accent-dim);
1378
+ }
1379
+
1380
+ /* ── Session close button ─────────────────────────── */
1381
+ .session-close-btn {
1382
+ background: none;
1383
+ border: none;
1384
+ color: var(--text-dim);
1385
+ cursor: pointer;
1386
+ font-size: 14px;
1387
+ padding: 2px 6px;
1388
+ border-radius: 4px;
1389
+ opacity: 0;
1390
+ transition: opacity 0.15s, color 0.15s;
1391
+ flex-shrink: 0;
1392
+ line-height: 1;
1393
+ }
1394
+
1395
+ .session-item:hover .session-close-btn,
1396
+ .session-item.active .session-close-btn {
1397
+ opacity: 1;
1398
+ }
1399
+
1400
+ .session-close-btn:hover {
1401
+ color: var(--red);
1402
+ background: rgba(239, 68, 68, 0.1);
1403
+ }
1404
+
1405
+ .session-name-row {
1406
+ display: flex;
1407
+ align-items: center;
1408
+ gap: 4px;
1409
+ }
1410
+
1411
+ .session-name-row .session-name {
1412
+ flex: 1;
1413
+ min-width: 0;
1414
+ }
1415
+
1209
1416
  /* Conflict dialog */
1210
1417
  .conflict-overlay {
1211
1418
  position: fixed;
@@ -1493,7 +1700,10 @@
1493
1700
  <aside class="sidebar" id="sessionsTab">
1494
1701
  <div class="sidebar-header">
1495
1702
  <h2>Sessions</h2>
1496
- <span class="session-count" id="sessionCount">0</span>
1703
+ <div style="display:flex;align-items:center;gap:8px;">
1704
+ <span class="session-count" id="sessionCount">0</span>
1705
+ <button class="new-session-btn" onclick="openNewSessionModal()" title="New session">+</button>
1706
+ </div>
1497
1707
  </div>
1498
1708
  <div class="session-list" id="sessionList">
1499
1709
  <div class="empty-state" id="emptyState">
@@ -1528,6 +1738,8 @@
1528
1738
  <button class="action-btn action-arrow" onclick="sendKey('Down')" title="Arrow Down">&darr;</button>
1529
1739
  <button class="action-btn action-arrow" onclick="sendKey('Left')" title="Arrow Left">&larr;</button>
1530
1740
  <button class="action-btn action-arrow" onclick="sendKey('Right')" title="Arrow Right">&rarr;</button>
1741
+ <span class="action-separator"></span>
1742
+ <button class="action-btn danger" onclick="closeActiveSession()" title="Close session">&times; Close</button>
1531
1743
  </div>
1532
1744
  </div>
1533
1745
  <div class="terminal-container" id="terminalContainer"></div>
@@ -1581,6 +1793,29 @@
1581
1793
  </div>
1582
1794
  </div>
1583
1795
 
1796
+ <!-- New Session modal -->
1797
+ <div class="modal-backdrop" id="newSessionModal" style="display:none" onclick="closeNewSessionModal(event)">
1798
+ <div class="modal-dialog" onclick="event.stopPropagation()">
1799
+ <h3>New Session</h3>
1800
+ <div class="modal-field">
1801
+ <label for="newSessionName">Topic Name</label>
1802
+ <input type="text" id="newSessionName" placeholder="e.g. dashboard-redesign" maxlength="128"
1803
+ onkeydown="if(event.key==='Enter')createNewSession()" autofocus>
1804
+ </div>
1805
+ <div class="modal-field">
1806
+ <label class="modal-toggle">
1807
+ <input type="checkbox" id="newSessionHeadless">
1808
+ <span>Headless (no Telegram topic)</span>
1809
+ </label>
1810
+ <div class="modal-hint">Headless sessions still appear in the dashboard but won't create a Telegram topic.</div>
1811
+ </div>
1812
+ <div class="modal-actions">
1813
+ <button class="modal-btn-cancel" onclick="closeNewSessionModal()">Cancel</button>
1814
+ <button class="modal-btn-create" id="createSessionBtn" onclick="createNewSession()">Create Session</button>
1815
+ </div>
1816
+ </div>
1817
+ </div>
1818
+
1584
1819
  <!-- Drop Zone tab -->
1585
1820
  <div class="dropzone-container" id="dropzoneTab" style="display:none">
1586
1821
  <div class="dropzone-panel">
@@ -1892,7 +2127,10 @@
1892
2127
  }
1893
2128
 
1894
2129
  el.innerHTML = `
1895
- <div class="session-name">${escapeHtml(session.name)}</div>
2130
+ <div class="session-name-row">
2131
+ <div class="session-name">${escapeHtml(session.name)}</div>
2132
+ <button class="session-close-btn" data-tmux="${escapeHtml(session.tmuxSession)}" data-name="${escapeHtml(session.name)}" onclick="event.stopPropagation();closeSession(this.dataset.tmux,this.dataset.name)" title="Close session">&times;</button>
2133
+ </div>
1896
2134
  <div class="session-meta">
1897
2135
  <span class="type-badge ${sType}">${sType}</span>
1898
2136
  <span class="model-badge ${model}">${model}</span>
@@ -2050,6 +2288,96 @@
2050
2288
  wsSend({ type: 'key', session: activeSession, key: text });
2051
2289
  }
2052
2290
 
2291
+ // ── New Session Modal ────────────────────────────────────
2292
+ function openNewSessionModal() {
2293
+ document.getElementById('newSessionModal').style.display = 'flex';
2294
+ const nameInput = document.getElementById('newSessionName');
2295
+ nameInput.value = '';
2296
+ document.getElementById('newSessionHeadless').checked = false;
2297
+ setTimeout(() => nameInput.focus(), 50);
2298
+ }
2299
+
2300
+ function closeNewSessionModal(e) {
2301
+ if (e && e.target !== e.currentTarget) return;
2302
+ document.getElementById('newSessionModal').style.display = 'none';
2303
+ }
2304
+
2305
+ async function createNewSession() {
2306
+ const nameInput = document.getElementById('newSessionName');
2307
+ const headless = document.getElementById('newSessionHeadless').checked;
2308
+ const name = nameInput.value.trim();
2309
+ const btn = document.getElementById('createSessionBtn');
2310
+
2311
+ if (!name) {
2312
+ nameInput.focus();
2313
+ nameInput.style.borderColor = 'var(--red)';
2314
+ setTimeout(() => nameInput.style.borderColor = '', 2000);
2315
+ return;
2316
+ }
2317
+
2318
+ btn.disabled = true;
2319
+ btn.textContent = 'Creating...';
2320
+
2321
+ try {
2322
+ const resp = await fetch('/sessions/create', {
2323
+ method: 'POST',
2324
+ headers: {
2325
+ 'Authorization': `Bearer ${token}`,
2326
+ 'Content-Type': 'application/json',
2327
+ },
2328
+ body: JSON.stringify({ name, headless }),
2329
+ });
2330
+ const data = await resp.json();
2331
+
2332
+ if (!resp.ok) {
2333
+ showToast(data.error || 'Failed to create session', 'error');
2334
+ return;
2335
+ }
2336
+
2337
+ showToast(`Session "${name}" created${data.topicId ? ' with Telegram topic' : ' (headless)'}`, 'success');
2338
+ document.getElementById('newSessionModal').style.display = 'none';
2339
+ } catch (err) {
2340
+ showToast('Network error: ' + (err.message || 'Cannot reach server'), 'error');
2341
+ } finally {
2342
+ btn.disabled = false;
2343
+ btn.textContent = 'Create Session';
2344
+ }
2345
+ }
2346
+
2347
+ // ── Close Session ─────────────────────────────────────────
2348
+ async function closeSession(tmuxSession, sessionName) {
2349
+ if (!confirm(`Close session "${sessionName}"?`)) return;
2350
+
2351
+ try {
2352
+ const resp = await fetch(`/sessions/${encodeURIComponent(tmuxSession)}`, {
2353
+ method: 'DELETE',
2354
+ headers: { 'Authorization': `Bearer ${token}` },
2355
+ });
2356
+ const data = await resp.json();
2357
+
2358
+ if (!resp.ok) {
2359
+ showToast(data.error || 'Failed to close session', 'error');
2360
+ return;
2361
+ }
2362
+
2363
+ showToast(`Session "${sessionName}" closed`, 'success');
2364
+
2365
+ // If this was the active session, clear terminal
2366
+ if (activeSession === tmuxSession) {
2367
+ goBack();
2368
+ }
2369
+ } catch (err) {
2370
+ showToast('Network error: ' + (err.message || 'Cannot reach server'), 'error');
2371
+ }
2372
+ }
2373
+
2374
+ function closeActiveSession() {
2375
+ if (!activeSession) return;
2376
+ const session = sessions.find(s => s.tmuxSession === activeSession);
2377
+ const name = session ? session.name : activeSession;
2378
+ closeSession(activeSession, name);
2379
+ }
2380
+
2053
2381
  // ── Helpers ───────────────────────────────────────────────
2054
2382
  function formatElapsed(isoStr) {
2055
2383
  const ms = Date.now() - new Date(isoStr).getTime();
package/dist/cli.js CHANGED
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/server/routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/server/routes.ts"],"names":[],"mappings":"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"}
@@ -2062,7 +2062,17 @@ export function createRoutes(ctx) {
2062
2062
  return;
2063
2063
  }
2064
2064
  try {
2065
- const killed = ctx.sessionManager.killSession(req.params.id);
2065
+ // Try direct UUID lookup first, then fall back to tmux session name lookup.
2066
+ // The dashboard sends tmux session names, not UUIDs.
2067
+ let killed = ctx.sessionManager.killSession(req.params.id);
2068
+ if (!killed) {
2069
+ // Look up by tmux session name
2070
+ const allSessions = ctx.state.listSessions({ status: 'running' });
2071
+ const match = allSessions.find(s => s.tmuxSession === req.params.id);
2072
+ if (match) {
2073
+ killed = ctx.sessionManager.killSession(match.id);
2074
+ }
2075
+ }
2066
2076
  if (!killed) {
2067
2077
  res.status(404).json({ error: `Session "${req.params.id}" not found` });
2068
2078
  return;
@@ -2073,6 +2083,61 @@ export function createRoutes(ctx) {
2073
2083
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
2074
2084
  }
2075
2085
  });
2086
+ // Create an interactive session from the dashboard.
2087
+ // By default creates a Telegram topic; set headless=true to skip.
2088
+ router.post('/sessions/create', spawnLimiter, async (req, res) => {
2089
+ const { name, headless } = req.body;
2090
+ if (!name || typeof name !== 'string' || name.trim().length < 1) {
2091
+ res.status(400).json({ error: '"name" is required (non-empty string)' });
2092
+ return;
2093
+ }
2094
+ if (name.length > 128) {
2095
+ res.status(400).json({ error: '"name" must be 128 characters or fewer' });
2096
+ return;
2097
+ }
2098
+ const topicName = name.trim();
2099
+ let topicId;
2100
+ // Create Telegram topic unless headless
2101
+ if (!headless && ctx.telegram) {
2102
+ try {
2103
+ const topic = await ctx.telegram.findOrCreateForumTopic(topicName);
2104
+ topicId = topic.topicId;
2105
+ }
2106
+ catch (err) {
2107
+ // Non-fatal: fall back to headless if topic creation fails
2108
+ console.error(`[sessions/create] Telegram topic creation failed, proceeding headless: ${err}`);
2109
+ }
2110
+ }
2111
+ try {
2112
+ const tmuxSession = await ctx.sessionManager.spawnInteractiveSession(undefined, // no initial message
2113
+ topicName, topicId ? { telegramTopicId: topicId } : undefined);
2114
+ // Update topic-session registry if we created a topic
2115
+ if (topicId) {
2116
+ const registryPath = path.join(ctx.config.stateDir, 'topic-session-registry.json');
2117
+ try {
2118
+ const reg = fs.existsSync(registryPath)
2119
+ ? JSON.parse(fs.readFileSync(registryPath, 'utf-8'))
2120
+ : { topicToSession: {}, topicToName: {} };
2121
+ reg.topicToSession[String(topicId)] = tmuxSession;
2122
+ reg.topicToName[String(topicId)] = topicName;
2123
+ fs.writeFileSync(registryPath, JSON.stringify(reg, null, 2));
2124
+ }
2125
+ catch {
2126
+ // Non-fatal — registry is best-effort
2127
+ }
2128
+ }
2129
+ res.status(201).json({
2130
+ ok: true,
2131
+ session: tmuxSession,
2132
+ name: topicName,
2133
+ topicId: topicId || null,
2134
+ headless: !topicId,
2135
+ });
2136
+ }
2137
+ catch (err) {
2138
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
2139
+ }
2140
+ });
2076
2141
  // ── Jobs ────────────────────────────────────────────────────────
2077
2142
  router.get('/jobs', (_req, res) => {
2078
2143
  if (!ctx.scheduler) {