helixmind 0.2.1 → 0.2.3
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.
Potentially problematic release.
This version of helixmind might be problematic. Click here for more details.
- package/README.md +31 -0
- package/dist/cli/agent/autonomous.d.ts +14 -0
- package/dist/cli/agent/autonomous.d.ts.map +1 -1
- package/dist/cli/agent/autonomous.js +22 -0
- package/dist/cli/agent/autonomous.js.map +1 -1
- package/dist/cli/agent/monitor/alerter.d.ts +29 -0
- package/dist/cli/agent/monitor/alerter.d.ts.map +1 -0
- package/dist/cli/agent/monitor/alerter.js +80 -0
- package/dist/cli/agent/monitor/alerter.js.map +1 -0
- package/dist/cli/agent/monitor/baseline.d.ts +14 -0
- package/dist/cli/agent/monitor/baseline.d.ts.map +1 -0
- package/dist/cli/agent/monitor/baseline.js +157 -0
- package/dist/cli/agent/monitor/baseline.js.map +1 -0
- package/dist/cli/agent/monitor/prompts.d.ts +9 -0
- package/dist/cli/agent/monitor/prompts.d.ts.map +1 -0
- package/dist/cli/agent/monitor/prompts.js +103 -0
- package/dist/cli/agent/monitor/prompts.js.map +1 -0
- package/dist/cli/agent/monitor/responder.d.ts +12 -0
- package/dist/cli/agent/monitor/responder.d.ts.map +1 -0
- package/dist/cli/agent/monitor/responder.js +59 -0
- package/dist/cli/agent/monitor/responder.js.map +1 -0
- package/dist/cli/agent/monitor/scanner.d.ts +18 -0
- package/dist/cli/agent/monitor/scanner.d.ts.map +1 -0
- package/dist/cli/agent/monitor/scanner.js +81 -0
- package/dist/cli/agent/monitor/scanner.js.map +1 -0
- package/dist/cli/agent/monitor/types.d.ts +119 -0
- package/dist/cli/agent/monitor/types.d.ts.map +1 -0
- package/dist/cli/agent/monitor/types.js +5 -0
- package/dist/cli/agent/monitor/types.js.map +1 -0
- package/dist/cli/agent/monitor/watcher.d.ts +4 -0
- package/dist/cli/agent/monitor/watcher.d.ts.map +1 -0
- package/dist/cli/agent/monitor/watcher.js +214 -0
- package/dist/cli/agent/monitor/watcher.js.map +1 -0
- package/dist/cli/brain/control-protocol.d.ts +47 -1
- package/dist/cli/brain/control-protocol.d.ts.map +1 -1
- package/dist/cli/brain/control-protocol.js.map +1 -1
- package/dist/cli/brain/generator.d.ts +14 -0
- package/dist/cli/brain/generator.d.ts.map +1 -1
- package/dist/cli/brain/generator.js +40 -0
- package/dist/cli/brain/generator.js.map +1 -1
- package/dist/cli/checkpoints/browser.d.ts +3 -4
- package/dist/cli/checkpoints/browser.d.ts.map +1 -1
- package/dist/cli/checkpoints/browser.js +162 -135
- package/dist/cli/checkpoints/browser.js.map +1 -1
- package/dist/cli/checkpoints/store.js +1 -1
- package/dist/cli/checkpoints/store.js.map +1 -1
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/chat.js +248 -2
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/context/trimmer.d.ts.map +1 -1
- package/dist/cli/context/trimmer.js +31 -6
- package/dist/cli/context/trimmer.js.map +1 -1
- package/package.json +1 -1
|
@@ -80,6 +80,7 @@ const HELP_CATEGORIES = [
|
|
|
80
80
|
{ cmd: '/auto', label: '/auto', description: 'Autonomous mode' },
|
|
81
81
|
{ cmd: '/stop', label: '/stop', description: 'Stop autonomous mode' },
|
|
82
82
|
{ cmd: '/security', label: '/security', description: 'Run security audit (background)' },
|
|
83
|
+
{ cmd: '/monitor', label: '/monitor', description: 'Continuous security monitoring' },
|
|
83
84
|
{ cmd: '/sessions', label: '/sessions', description: 'List all sessions & tabs' },
|
|
84
85
|
{ cmd: '/local', label: '/local', description: 'Local LLM setup (Ollama)' },
|
|
85
86
|
],
|
|
@@ -536,6 +537,95 @@ export async function chatCommand(options) {
|
|
|
536
537
|
});
|
|
537
538
|
}).catch(() => { });
|
|
538
539
|
},
|
|
540
|
+
startMonitor: (mode) => {
|
|
541
|
+
const existingMonitor = sessionMgr.background.find(s => s.name.includes('Monitor') && s.status === 'running');
|
|
542
|
+
if (existingMonitor)
|
|
543
|
+
return existingMonitor.id;
|
|
544
|
+
const modeIcons = { passive: '\u{1F50D}', defensive: '\u{1F6E1}\uFE0F', active: '\u2694\uFE0F' };
|
|
545
|
+
const icon = modeIcons[mode] || '\u{1F6E1}\uFE0F';
|
|
546
|
+
const bgSession = sessionMgr.create(`${icon} Monitor`, icon, agentHistory);
|
|
547
|
+
bgSession.start();
|
|
548
|
+
wireSessionOutput(bgSession);
|
|
549
|
+
pushSessionCreated(serializeSession(bgSession));
|
|
550
|
+
// Start monitor in background (same as /monitor command)
|
|
551
|
+
(async () => {
|
|
552
|
+
try {
|
|
553
|
+
const { scanSystem } = await import('../agent/monitor/scanner.js');
|
|
554
|
+
const { buildBaseline } = await import('../agent/monitor/baseline.js');
|
|
555
|
+
const { runMonitorLoop } = await import('../agent/monitor/watcher.js');
|
|
556
|
+
const { pushMonitorStatus: pushStatus } = await import('../brain/generator.js');
|
|
557
|
+
const scanResult = await scanSystem({
|
|
558
|
+
sendMessage: async (prompt) => {
|
|
559
|
+
bgSession.controller.reset();
|
|
560
|
+
const rth = { text: '' };
|
|
561
|
+
const orig = bgSession.buffer.addAssistantSummary.bind(bgSession.buffer);
|
|
562
|
+
bgSession.buffer.addAssistantSummary = (t) => { rth.text = t; orig(t); };
|
|
563
|
+
await sendAgentMessage(prompt, bgSession.history, provider, project, spiralEngine, config, permissions, bgSession.undoStack, checkpointStore, bgSession.controller, new ActivityIndicator(), bgSession.buffer, (inp, out) => { sessionTokensInput += inp; sessionTokensOutput += out; }, () => { sessionToolCalls++; }, undefined, { enabled: false, verbose: false, strict: false });
|
|
564
|
+
bgSession.buffer.addAssistantSummary = orig;
|
|
565
|
+
return rth.text;
|
|
566
|
+
},
|
|
567
|
+
isAborted: () => bgSession.controller.isAborted,
|
|
568
|
+
onThreat: () => { }, onDefense: () => { },
|
|
569
|
+
onScanComplete: (p) => bgSession.capture(`Scan: ${p}`),
|
|
570
|
+
onStatusUpdate: () => { }, updateStatus: () => { },
|
|
571
|
+
});
|
|
572
|
+
if (bgSession.controller.isAborted)
|
|
573
|
+
return;
|
|
574
|
+
const baseline = buildBaseline(scanResult);
|
|
575
|
+
if (bgSession.controller.isAborted)
|
|
576
|
+
return;
|
|
577
|
+
await runMonitorLoop({
|
|
578
|
+
sendMessage: async (prompt) => {
|
|
579
|
+
bgSession.controller.reset();
|
|
580
|
+
const rth = { text: '' };
|
|
581
|
+
const orig = bgSession.buffer.addAssistantSummary.bind(bgSession.buffer);
|
|
582
|
+
bgSession.buffer.addAssistantSummary = (t) => { rth.text = t; orig(t); };
|
|
583
|
+
await sendAgentMessage(prompt, bgSession.history, provider, project, spiralEngine, config, permissions, bgSession.undoStack, checkpointStore, bgSession.controller, new ActivityIndicator(), bgSession.buffer, (inp, out) => { sessionTokensInput += inp; sessionTokensOutput += out; }, () => { sessionToolCalls++; }, undefined, { enabled: false, verbose: false, strict: false });
|
|
584
|
+
bgSession.buffer.addAssistantSummary = orig;
|
|
585
|
+
return rth.text;
|
|
586
|
+
},
|
|
587
|
+
isAborted: () => bgSession.controller.isAborted,
|
|
588
|
+
onThreat: (t) => bgSession.capture(`THREAT [${t.severity}]: ${t.title}`),
|
|
589
|
+
onDefense: (d) => bgSession.capture(`DEFENSE: ${d.action} \u2192 ${d.target}`),
|
|
590
|
+
onScanComplete: (p) => bgSession.capture(`Check: ${p}`),
|
|
591
|
+
onStatusUpdate: (state) => {
|
|
592
|
+
pushStatus({ mode: state.mode, uptime: state.uptime, threatCount: state.threats.length, defenseCount: state.defenses.length, lastScan: state.lastScan });
|
|
593
|
+
},
|
|
594
|
+
updateStatus: () => updateStatusBar(),
|
|
595
|
+
}, mode, baseline);
|
|
596
|
+
}
|
|
597
|
+
catch (err) {
|
|
598
|
+
if (!(err instanceof AgentAbortError))
|
|
599
|
+
bgSession.capture(`Monitor error: ${err}`);
|
|
600
|
+
}
|
|
601
|
+
sessionMgr.complete(bgSession.id, { text: 'Monitor ended', steps: [], errors: bgSession.controller.isAborted ? ['Stopped'] : [], durationMs: bgSession.elapsed });
|
|
602
|
+
pushSessionUpdate(serializeSession(bgSession));
|
|
603
|
+
})();
|
|
604
|
+
return bgSession.id;
|
|
605
|
+
},
|
|
606
|
+
stopMonitor: () => {
|
|
607
|
+
const monitorSession = sessionMgr.background.find(s => s.name.includes('Monitor') && s.status === 'running');
|
|
608
|
+
if (!monitorSession)
|
|
609
|
+
return false;
|
|
610
|
+
monitorSession.abort();
|
|
611
|
+
pushSessionUpdate(serializeSession(monitorSession));
|
|
612
|
+
return true;
|
|
613
|
+
},
|
|
614
|
+
handleMonitorCommand: (command, params) => {
|
|
615
|
+
if (command === 'stop_monitor') {
|
|
616
|
+
const ms = sessionMgr.background.find(s => s.name.includes('Monitor') && s.status === 'running');
|
|
617
|
+
if (ms) {
|
|
618
|
+
ms.abort();
|
|
619
|
+
pushSessionUpdate(serializeSession(ms));
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
// Other commands (set_mode, rescan, unblock_ip) can be extended here
|
|
623
|
+
},
|
|
624
|
+
handleApprovalResponse: (requestId, approved) => {
|
|
625
|
+
import('../agent/monitor/alerter.js').then(({ resolveApproval }) => {
|
|
626
|
+
resolveApproval(requestId, approved);
|
|
627
|
+
}).catch(() => { });
|
|
628
|
+
},
|
|
539
629
|
getFindings: () => [...collectedFindings],
|
|
540
630
|
getBugs: () => bugJournal.getAllBugs().map(b => ({
|
|
541
631
|
id: b.id,
|
|
@@ -639,6 +729,10 @@ export async function chatCommand(options) {
|
|
|
639
729
|
});
|
|
640
730
|
}).catch(() => { });
|
|
641
731
|
},
|
|
732
|
+
startMonitor: () => '',
|
|
733
|
+
stopMonitor: () => false,
|
|
734
|
+
handleMonitorCommand: () => { },
|
|
735
|
+
handleApprovalResponse: () => { },
|
|
642
736
|
getFindings: () => [...collectedFindings],
|
|
643
737
|
getBugs: () => bugJournal.getAllBugs().map(b => ({
|
|
644
738
|
id: b.id, description: b.description, file: b.file, line: b.line,
|
|
@@ -1013,6 +1107,11 @@ export async function chatCommand(options) {
|
|
|
1013
1107
|
renderInfo(chalk.yellow(`${r.messagesRemoved} message(s) reverted`));
|
|
1014
1108
|
if (r.filesReverted > 0)
|
|
1015
1109
|
renderInfo(chalk.yellow(`${r.filesReverted} file(s) reverted`));
|
|
1110
|
+
// Restore user text into readline input
|
|
1111
|
+
if (browserResult.messageText) {
|
|
1112
|
+
rl.line = browserResult.messageText;
|
|
1113
|
+
rl.cursor = browserResult.messageText.length;
|
|
1114
|
+
}
|
|
1016
1115
|
}
|
|
1017
1116
|
}
|
|
1018
1117
|
catch {
|
|
@@ -1238,6 +1337,108 @@ export async function chatCommand(options) {
|
|
|
1238
1337
|
});
|
|
1239
1338
|
return;
|
|
1240
1339
|
}
|
|
1340
|
+
if (action === 'monitor') {
|
|
1341
|
+
// Monitor mode — runs as background session with continuous watch loop
|
|
1342
|
+
const monitorMode = goal || 'passive';
|
|
1343
|
+
const existingMonitor = sessionMgr.background.find(s => s.name.includes('Monitor') && s.status === 'running');
|
|
1344
|
+
if (existingMonitor) {
|
|
1345
|
+
renderInfo('Monitor already running. Use /stop to stop it first.');
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
const modeIcons = { passive: '\u{1F50D}', defensive: '\u{1F6E1}\uFE0F', active: '\u2694\uFE0F' };
|
|
1349
|
+
const icon = modeIcons[monitorMode] || '\u{1F6E1}\uFE0F';
|
|
1350
|
+
const bgSession = sessionMgr.create(`${icon} Monitor`, icon, agentHistory);
|
|
1351
|
+
bgSession.start();
|
|
1352
|
+
renderInfo(`${chalk.hex('#ff6600')(icon)} Monitor started (${monitorMode}) ${chalk.dim(`[session ${bgSession.id}]`)}`);
|
|
1353
|
+
updateStatusBar();
|
|
1354
|
+
// Run monitor loop in background — user keeps prompt
|
|
1355
|
+
(async () => {
|
|
1356
|
+
try {
|
|
1357
|
+
const { scanSystem } = await import('../agent/monitor/scanner.js');
|
|
1358
|
+
const { buildBaseline } = await import('../agent/monitor/baseline.js');
|
|
1359
|
+
const { runMonitorLoop } = await import('../agent/monitor/watcher.js');
|
|
1360
|
+
const { pushMonitorStatus } = await import('../brain/generator.js');
|
|
1361
|
+
// Phase 1: Full system scan
|
|
1362
|
+
bgSession.capture('Phase 1: Scanning system...');
|
|
1363
|
+
const scanResult = await scanSystem({
|
|
1364
|
+
sendMessage: async (prompt) => {
|
|
1365
|
+
bgSession.controller.reset();
|
|
1366
|
+
const resultTextHolder = { text: '' };
|
|
1367
|
+
const origAddSummary = bgSession.buffer.addAssistantSummary.bind(bgSession.buffer);
|
|
1368
|
+
bgSession.buffer.addAssistantSummary = (t) => {
|
|
1369
|
+
resultTextHolder.text = t;
|
|
1370
|
+
origAddSummary(t);
|
|
1371
|
+
};
|
|
1372
|
+
await sendAgentMessage(prompt, bgSession.history, provider, project, spiralEngine, config, permissions, bgSession.undoStack, checkpointStore, bgSession.controller, new ActivityIndicator(), bgSession.buffer, (inp, out) => { sessionTokensInput += inp; sessionTokensOutput += out; }, () => { sessionToolCalls++; }, undefined, { enabled: false, verbose: false, strict: false });
|
|
1373
|
+
bgSession.buffer.addAssistantSummary = origAddSummary;
|
|
1374
|
+
return resultTextHolder.text;
|
|
1375
|
+
},
|
|
1376
|
+
isAborted: () => bgSession.controller.isAborted,
|
|
1377
|
+
onThreat: () => { },
|
|
1378
|
+
onDefense: () => { },
|
|
1379
|
+
onScanComplete: (phase) => bgSession.capture(`Scan: ${phase}`),
|
|
1380
|
+
onStatusUpdate: () => updateStatusBar(),
|
|
1381
|
+
updateStatus: () => updateStatusBar(),
|
|
1382
|
+
});
|
|
1383
|
+
if (bgSession.controller.isAborted)
|
|
1384
|
+
return;
|
|
1385
|
+
// Phase 2: Build baseline
|
|
1386
|
+
bgSession.capture('Phase 2: Building security baseline...');
|
|
1387
|
+
const baseline = buildBaseline(scanResult);
|
|
1388
|
+
bgSession.capture(`Baseline: ${baseline.processes.length} processes, ${baseline.ports.length} ports`);
|
|
1389
|
+
if (bgSession.controller.isAborted)
|
|
1390
|
+
return;
|
|
1391
|
+
// Phase 3: Continuous watching
|
|
1392
|
+
bgSession.capture(`Phase 3: Monitoring (${monitorMode} mode)...`);
|
|
1393
|
+
await runMonitorLoop({
|
|
1394
|
+
sendMessage: async (prompt) => {
|
|
1395
|
+
bgSession.controller.reset();
|
|
1396
|
+
const resultTextHolder = { text: '' };
|
|
1397
|
+
const origAddSummary = bgSession.buffer.addAssistantSummary.bind(bgSession.buffer);
|
|
1398
|
+
bgSession.buffer.addAssistantSummary = (t) => {
|
|
1399
|
+
resultTextHolder.text = t;
|
|
1400
|
+
origAddSummary(t);
|
|
1401
|
+
};
|
|
1402
|
+
await sendAgentMessage(prompt, bgSession.history, provider, project, spiralEngine, config, permissions, bgSession.undoStack, checkpointStore, bgSession.controller, new ActivityIndicator(), bgSession.buffer, (inp, out) => { sessionTokensInput += inp; sessionTokensOutput += out; }, () => { sessionToolCalls++; }, undefined, { enabled: false, verbose: false, strict: false });
|
|
1403
|
+
bgSession.buffer.addAssistantSummary = origAddSummary;
|
|
1404
|
+
return resultTextHolder.text;
|
|
1405
|
+
},
|
|
1406
|
+
isAborted: () => bgSession.controller.isAborted,
|
|
1407
|
+
onThreat: (threat) => {
|
|
1408
|
+
bgSession.capture(`THREAT [${threat.severity}]: ${threat.title}`);
|
|
1409
|
+
},
|
|
1410
|
+
onDefense: (defense) => {
|
|
1411
|
+
bgSession.capture(`DEFENSE: ${defense.action} \u2192 ${defense.target}`);
|
|
1412
|
+
},
|
|
1413
|
+
onScanComplete: (phase) => bgSession.capture(`Check: ${phase}`),
|
|
1414
|
+
onStatusUpdate: (state) => {
|
|
1415
|
+
pushMonitorStatus({
|
|
1416
|
+
mode: state.mode,
|
|
1417
|
+
uptime: state.uptime,
|
|
1418
|
+
threatCount: state.threats.length,
|
|
1419
|
+
defenseCount: state.defenses.length,
|
|
1420
|
+
lastScan: state.lastScan,
|
|
1421
|
+
});
|
|
1422
|
+
updateStatusBar();
|
|
1423
|
+
},
|
|
1424
|
+
updateStatus: () => updateStatusBar(),
|
|
1425
|
+
}, monitorMode, baseline);
|
|
1426
|
+
}
|
|
1427
|
+
catch (err) {
|
|
1428
|
+
if (!(err instanceof AgentAbortError)) {
|
|
1429
|
+
bgSession.capture(`Monitor error: ${err}`);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
sessionMgr.complete(bgSession.id, {
|
|
1433
|
+
text: 'Monitor session ended',
|
|
1434
|
+
steps: [],
|
|
1435
|
+
errors: bgSession.controller.isAborted ? ['Stopped by user'] : [],
|
|
1436
|
+
durationMs: bgSession.elapsed,
|
|
1437
|
+
});
|
|
1438
|
+
updateStatusBar();
|
|
1439
|
+
})();
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1241
1442
|
if (action === 'start') {
|
|
1242
1443
|
// Check if autonomous is already running
|
|
1243
1444
|
const existingAuto = sessionMgr.background.find(s => s.name.includes('Auto') && s.status === 'running');
|
|
@@ -1351,8 +1552,9 @@ export async function chatCommand(options) {
|
|
|
1351
1552
|
showPrompt();
|
|
1352
1553
|
return;
|
|
1353
1554
|
}
|
|
1354
|
-
//
|
|
1355
|
-
//
|
|
1555
|
+
// Clear the readline echo line (prompt + typed text) and replace with the
|
|
1556
|
+
// styled "You" label so the user doesn't see their input twice.
|
|
1557
|
+
process.stdout.write('\x1b[A\x1b[2K');
|
|
1356
1558
|
renderUserMessage(input);
|
|
1357
1559
|
// Track user message in session buffer
|
|
1358
1560
|
sessionBuffer.addUserMessage(input);
|
|
@@ -2434,6 +2636,50 @@ async function handleSlashCommand(input, messages, agentHistory, config, spiralE
|
|
|
2434
2636
|
await onAutonomous('security');
|
|
2435
2637
|
}
|
|
2436
2638
|
break;
|
|
2639
|
+
case '/monitor': {
|
|
2640
|
+
if (!onAutonomous)
|
|
2641
|
+
break;
|
|
2642
|
+
const { MONITOR_MODES, MONITOR_WARNINGS } = await import('../agent/autonomous.js');
|
|
2643
|
+
// Interactive setup: show banner + mode selection
|
|
2644
|
+
rl.pause();
|
|
2645
|
+
process.stdout.write('\n');
|
|
2646
|
+
const monitorMenuItems = [
|
|
2647
|
+
...MONITOR_MODES.map(m => ({ label: chalk.hex('#ff6600').bold(m.label), description: m.description })),
|
|
2648
|
+
{ label: chalk.dim('\u2715 Cancel'), description: 'Go back' },
|
|
2649
|
+
];
|
|
2650
|
+
const modeIdx = await selectMenu(monitorMenuItems, {
|
|
2651
|
+
title: chalk.hex('#ff6600').bold('\u{1F6E1}\uFE0F MONITOR MODE'),
|
|
2652
|
+
cancelLabel: 'Cancel',
|
|
2653
|
+
});
|
|
2654
|
+
if (modeIdx < 0 || modeIdx >= MONITOR_MODES.length) {
|
|
2655
|
+
rl.resume();
|
|
2656
|
+
renderInfo('Monitor cancelled.');
|
|
2657
|
+
break;
|
|
2658
|
+
}
|
|
2659
|
+
const selectedMode = MONITOR_MODES[modeIdx].key;
|
|
2660
|
+
// Defensive/Active modes: show warning + confirm
|
|
2661
|
+
if (selectedMode !== 'passive') {
|
|
2662
|
+
const warnings = MONITOR_WARNINGS[selectedMode] || [];
|
|
2663
|
+
process.stdout.write('\n');
|
|
2664
|
+
process.stdout.write(chalk.yellow(` \u26A0\uFE0F ${selectedMode.charAt(0).toUpperCase() + selectedMode.slice(1)} mode will:\n`));
|
|
2665
|
+
for (const w of warnings) {
|
|
2666
|
+
process.stdout.write(chalk.dim(` \u2022 ${w}\n`));
|
|
2667
|
+
}
|
|
2668
|
+
process.stdout.write('\n');
|
|
2669
|
+
const confirmIdx = await selectMenu([
|
|
2670
|
+
{ label: chalk.hex('#ff6600').bold('Yes, activate'), description: `Start ${selectedMode} monitor` },
|
|
2671
|
+
{ label: 'No, go back', description: 'Cancel' },
|
|
2672
|
+
], { title: chalk.yellow(`Activate ${selectedMode} monitor?`), cancelLabel: 'Cancel' });
|
|
2673
|
+
if (confirmIdx !== 0) {
|
|
2674
|
+
rl.resume();
|
|
2675
|
+
renderInfo('Monitor cancelled.');
|
|
2676
|
+
break;
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
rl.resume();
|
|
2680
|
+
await onAutonomous('monitor', selectedMode);
|
|
2681
|
+
break;
|
|
2682
|
+
}
|
|
2437
2683
|
case '/sessions':
|
|
2438
2684
|
case '/session': {
|
|
2439
2685
|
if (!sessionManager)
|