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.
- package/dashboard/index.html +330 -2
- package/dist/cli.js +0 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +66 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +46 -46
- package/upgrades/0.23.15.md +17 -0
- package/dist/core/ResponseReviewGate.d.ts +0 -182
- package/dist/core/ResponseReviewGate.d.ts.map +0 -1
- package/dist/core/ResponseReviewGate.js +0 -956
- package/dist/core/ResponseReviewGate.js.map +0 -1
- package/upgrades/0.23.10.md +0 -19
- package/upgrades/0.23.11.md +0 -21
- /package/upgrades/{NEXT.md → 0.23.14.md} +0 -0
package/dashboard/index.html
CHANGED
|
@@ -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
|
-
<
|
|
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">↓</button>
|
|
1529
1739
|
<button class="action-btn action-arrow" onclick="sendKey('Left')" title="Arrow Left">←</button>
|
|
1530
1740
|
<button class="action-btn action-arrow" onclick="sendKey('Right')" title="Arrow Right">→</button>
|
|
1741
|
+
<span class="action-separator"></span>
|
|
1742
|
+
<button class="action-btn danger" onclick="closeActiveSession()" title="Close session">× 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"
|
|
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">×</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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"}
|
package/dist/server/routes.js
CHANGED
|
@@ -2062,7 +2062,17 @@ export function createRoutes(ctx) {
|
|
|
2062
2062
|
return;
|
|
2063
2063
|
}
|
|
2064
2064
|
try {
|
|
2065
|
-
|
|
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) {
|