4runr-os 2.10.55 → 2.10.56
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/apps/gateway/dist/apps/gateway/src/middleware/ddos-protection.d.ts.map +1 -1
- package/apps/gateway/dist/apps/gateway/src/middleware/ddos-protection.js +15 -0
- package/apps/gateway/dist/apps/gateway/src/middleware/ddos-protection.js.map +1 -1
- package/apps/gateway/package-lock.json +3 -3
- package/apps/gateway/src/middleware/ddos-protection.ts +20 -0
- package/mk3-tui/src/app.rs +60 -17
- package/mk3-tui/src/main.rs +45 -7
- package/mk3-tui/src/ui/run_manager.rs +47 -2
- package/package.json +2 -2
- package/scripts/os-tools-smoke.cjs +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ddos-protection.d.ts","sourceRoot":"","sources":["../../../../../src/middleware/ddos-protection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ddos-protection.d.ts","sourceRoot":"","sources":["../../../../../src/middleware/ddos-protection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA2OvD,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAwDf;AAKD,wBAAgB,YAAY;;;;;;;;;EAW3B"}
|
|
@@ -22,6 +22,18 @@ function generateFingerprint(request) {
|
|
|
22
22
|
const data = `${ip}:${userAgent}:${accept}:${acceptLanguage}`;
|
|
23
23
|
return crypto.createHash('sha256').update(data).digest('hex').substring(0, 16);
|
|
24
24
|
}
|
|
25
|
+
function isLoopbackIP(ip) {
|
|
26
|
+
const n = ip.toLowerCase();
|
|
27
|
+
return (n === '127.0.0.1' ||
|
|
28
|
+
n === '::1' ||
|
|
29
|
+
n === '::ffff:127.0.0.1' ||
|
|
30
|
+
n === 'localhost');
|
|
31
|
+
}
|
|
32
|
+
function loopbackExemptFromDdos() {
|
|
33
|
+
if (process.env['DDOS_LOOPBACK_EXEMPT'] === 'false')
|
|
34
|
+
return false;
|
|
35
|
+
return process.env['NODE_ENV'] !== 'production';
|
|
36
|
+
}
|
|
25
37
|
function getClientIP(request) {
|
|
26
38
|
const forwarded = request.headers['x-forwarded-for'];
|
|
27
39
|
if (forwarded) {
|
|
@@ -138,6 +150,9 @@ export async function ddosProtection(request, reply) {
|
|
|
138
150
|
return;
|
|
139
151
|
}
|
|
140
152
|
const ip = getClientIP(request);
|
|
153
|
+
if (loopbackExemptFromDdos() && isLoopbackIP(ip)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
141
156
|
const userAgent = request.headers['user-agent'] || 'unknown';
|
|
142
157
|
if (isIPBlocked(ip)) {
|
|
143
158
|
const block = ipBlocks.get(ip);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ddos-protection.js","sourceRoot":"","sources":["../../../../../src/middleware/ddos-protection.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ddos-protection.js","sourceRoot":"","sources":["../../../../../src/middleware/ddos-protection.ts"],"names":[],"mappings":"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"}
|
|
@@ -3546,9 +3546,9 @@
|
|
|
3546
3546
|
"license": "MIT"
|
|
3547
3547
|
},
|
|
3548
3548
|
"node_modules/baseline-browser-mapping": {
|
|
3549
|
-
"version": "2.10.
|
|
3550
|
-
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.
|
|
3551
|
-
"integrity": "sha512-
|
|
3549
|
+
"version": "2.10.33",
|
|
3550
|
+
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz",
|
|
3551
|
+
"integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==",
|
|
3552
3552
|
"dev": true,
|
|
3553
3553
|
"license": "Apache-2.0",
|
|
3554
3554
|
"bin": {
|
|
@@ -64,6 +64,22 @@ function generateFingerprint(request: FastifyRequest): string {
|
|
|
64
64
|
return crypto.createHash('sha256').update(data).digest('hex').substring(0, 16);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
function isLoopbackIP(ip: string): boolean {
|
|
68
|
+
const n = ip.toLowerCase();
|
|
69
|
+
return (
|
|
70
|
+
n === '127.0.0.1' ||
|
|
71
|
+
n === '::1' ||
|
|
72
|
+
n === '::ffff:127.0.0.1' ||
|
|
73
|
+
n === 'localhost'
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Local dev + smoke tests: loopback is not DDoS-blocked unless explicitly disabled. */
|
|
78
|
+
function loopbackExemptFromDdos(): boolean {
|
|
79
|
+
if (process.env['DDOS_LOOPBACK_EXEMPT'] === 'false') return false;
|
|
80
|
+
return process.env['NODE_ENV'] !== 'production';
|
|
81
|
+
}
|
|
82
|
+
|
|
67
83
|
/**
|
|
68
84
|
* Get client IP address
|
|
69
85
|
*/
|
|
@@ -232,6 +248,10 @@ export async function ddosProtection(
|
|
|
232
248
|
}
|
|
233
249
|
|
|
234
250
|
const ip = getClientIP(request);
|
|
251
|
+
if (loopbackExemptFromDdos() && isLoopbackIP(ip)) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
235
255
|
const userAgent = request.headers['user-agent'] || 'unknown';
|
|
236
256
|
|
|
237
257
|
// Check if IP is blocked
|
package/mk3-tui/src/app.rs
CHANGED
|
@@ -452,6 +452,7 @@ pub struct AppState {
|
|
|
452
452
|
|
|
453
453
|
// Step 6: Gateway runs
|
|
454
454
|
pub pending_run_list_id: Option<String>,
|
|
455
|
+
pub pending_run_list_silent: bool,
|
|
455
456
|
pub pending_run_get_id: Option<String>,
|
|
456
457
|
pub pending_run_cancel_id: Option<String>,
|
|
457
458
|
pub pending_run_quick_id: Option<String>,
|
|
@@ -537,6 +538,7 @@ impl Default for AppState {
|
|
|
537
538
|
pending_monitoring_drill_id: None,
|
|
538
539
|
pending_setup_detect_id: None,
|
|
539
540
|
pending_run_list_id: None,
|
|
541
|
+
pending_run_list_silent: false,
|
|
540
542
|
pending_run_get_id: None,
|
|
541
543
|
pending_run_cancel_id: None,
|
|
542
544
|
pending_run_quick_id: None,
|
|
@@ -778,6 +780,46 @@ impl App {
|
|
|
778
780
|
}
|
|
779
781
|
}
|
|
780
782
|
|
|
783
|
+
/// Fetch run list from Gateway (`run.list`). `silent` = background poll (no loading spinner).
|
|
784
|
+
pub fn begin_run_list_request(&mut self, ws: &WebSocketClient, silent: bool) {
|
|
785
|
+
if self.state.operation_mode != OperationMode::Connected {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
if self.state.pending_run_list_id.is_some() {
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
if !silent && self.state.run_manager.loading {
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
let data = serde_json::json!({ "limit": 50 });
|
|
795
|
+
match ws.send_command("run.list", Some(data)) {
|
|
796
|
+
Ok(id) => {
|
|
797
|
+
self.state.pending_run_list_id = Some(id);
|
|
798
|
+
self.state.pending_run_list_silent = silent;
|
|
799
|
+
if !silent {
|
|
800
|
+
self.state.run_manager.loading = true;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
Err(e) => {
|
|
804
|
+
self.add_log(format!("[RUN] run.list failed: {}", e));
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/// Refresh selected run detail (`run.get`) during live polling.
|
|
810
|
+
pub fn begin_run_get_request(&mut self, ws: &WebSocketClient, run_id: &str) {
|
|
811
|
+
if self.state.operation_mode != OperationMode::Connected {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if self.state.pending_run_get_id.is_some() {
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
let data = serde_json::json!({ "runId": run_id });
|
|
818
|
+
if let Ok(id) = ws.send_command("run.get", Some(data)) {
|
|
819
|
+
self.state.pending_run_get_id = Some(id);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
781
823
|
/// Phase 2: refresh one Portal Monitoring section via CLI (`monitoring.refresh` → Gateway APIs).
|
|
782
824
|
pub fn begin_monitoring_refresh_request(
|
|
783
825
|
&mut self,
|
|
@@ -1415,13 +1457,7 @@ impl App {
|
|
|
1415
1457
|
.push_back("[NAV] Opening Run Manager...".into());
|
|
1416
1458
|
if self.state.operation_mode == OperationMode::Connected {
|
|
1417
1459
|
if let Some(ws) = ws_client {
|
|
1418
|
-
|
|
1419
|
-
let data = serde_json::json!({ "limit": 50 });
|
|
1420
|
-
if let Ok(id) = ws.send_command("run.list", Some(data)) {
|
|
1421
|
-
self.state.pending_run_list_id = Some(id);
|
|
1422
|
-
self.state.run_manager.loading = true;
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1460
|
+
self.begin_run_list_request(ws, false);
|
|
1425
1461
|
}
|
|
1426
1462
|
} else {
|
|
1427
1463
|
self.add_log(
|
|
@@ -2212,18 +2248,12 @@ impl App {
|
|
|
2212
2248
|
self.request_render("run_manager_sort");
|
|
2213
2249
|
}
|
|
2214
2250
|
|
|
2215
|
-
// Refresh
|
|
2251
|
+
// Refresh (manual)
|
|
2216
2252
|
KeyCode::Char('r') | KeyCode::Char('R') => {
|
|
2217
2253
|
if self.state.operation_mode == OperationMode::Connected {
|
|
2218
|
-
if
|
|
2219
|
-
self.
|
|
2220
|
-
|
|
2221
|
-
let data = serde_json::json!({ "limit": 50 });
|
|
2222
|
-
if let Ok(id) = ws.send_command("run.list", Some(data)) {
|
|
2223
|
-
self.state.pending_run_list_id = Some(id);
|
|
2224
|
-
self.state.run_manager.loading = true;
|
|
2225
|
-
self.add_log("[RUN] Refreshing run list from Gateway...".to_string());
|
|
2226
|
-
}
|
|
2254
|
+
if let Some(ws) = ws_client {
|
|
2255
|
+
self.begin_run_list_request(ws, false);
|
|
2256
|
+
self.add_log("[RUN] Refreshing run list from Gateway...".to_string());
|
|
2227
2257
|
} else {
|
|
2228
2258
|
self.add_log("[RUN] WebSocket not connected".to_string());
|
|
2229
2259
|
}
|
|
@@ -2233,6 +2263,19 @@ impl App {
|
|
|
2233
2263
|
self.request_render("run_manager_refresh");
|
|
2234
2264
|
}
|
|
2235
2265
|
|
|
2266
|
+
// Toggle live auto-refresh (poll every ~3s)
|
|
2267
|
+
KeyCode::Char('a') | KeyCode::Char('A') => {
|
|
2268
|
+
self.state.run_manager.auto_refresh_enabled =
|
|
2269
|
+
!self.state.run_manager.auto_refresh_enabled;
|
|
2270
|
+
let status = if self.state.run_manager.auto_refresh_enabled {
|
|
2271
|
+
"on"
|
|
2272
|
+
} else {
|
|
2273
|
+
"off"
|
|
2274
|
+
};
|
|
2275
|
+
self.add_log(format!("[RUN] Live auto-refresh {}", status));
|
|
2276
|
+
self.request_render("run_manager_live_toggle");
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2236
2279
|
// View details / Close detail view
|
|
2237
2280
|
KeyCode::Enter => {
|
|
2238
2281
|
if self.state.run_manager.is_detail_view() {
|
package/mk3-tui/src/main.rs
CHANGED
|
@@ -18,7 +18,7 @@ mod storage;
|
|
|
18
18
|
mod ui;
|
|
19
19
|
mod websocket;
|
|
20
20
|
|
|
21
|
-
use app::App;
|
|
21
|
+
use app::{App, OperationMode};
|
|
22
22
|
use io::IoHandler;
|
|
23
23
|
use websocket::{WebSocketClient, WsClientMessage};
|
|
24
24
|
|
|
@@ -189,6 +189,31 @@ fn main() -> Result<()> {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
// Run Manager: live poll run.list every ~3s when enabled (no manual R)
|
|
193
|
+
if matches!(current_screen, Screen::RunManager)
|
|
194
|
+
&& app.state.operation_mode == OperationMode::Connected
|
|
195
|
+
{
|
|
196
|
+
let rm = &app.state.run_manager;
|
|
197
|
+
if rm.auto_refresh_enabled {
|
|
198
|
+
let due = rm
|
|
199
|
+
.last_refresh
|
|
200
|
+
.map(|lr| lr.elapsed() >= rm.auto_refresh_interval)
|
|
201
|
+
.unwrap_or(true);
|
|
202
|
+
if due {
|
|
203
|
+
if let Some(ws) = &ws_client {
|
|
204
|
+
app.state.run_manager.last_refresh = Some(Instant::now());
|
|
205
|
+
app.begin_run_list_request(ws, true);
|
|
206
|
+
if rm.is_detail_view() {
|
|
207
|
+
if let Some(run) = app.state.run_manager.selected_run() {
|
|
208
|
+
let run_id = run.id.clone();
|
|
209
|
+
app.begin_run_get_request(ws, &run_id);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
192
217
|
// ┌─────────────────────────────────────────────────────────┐
|
|
193
218
|
// │ STEP 2: CHECK WEBSOCKET MESSAGES │
|
|
194
219
|
// └─────────────────────────────────────────────────────────┘
|
|
@@ -423,7 +448,9 @@ fn main() -> Result<()> {
|
|
|
423
448
|
else if Some(&resp.id)
|
|
424
449
|
== app.state.pending_run_list_id.as_ref()
|
|
425
450
|
{
|
|
451
|
+
let silent = app.state.pending_run_list_silent;
|
|
426
452
|
app.state.pending_run_list_id = None;
|
|
453
|
+
app.state.pending_run_list_silent = false;
|
|
427
454
|
app.state.run_manager.loading = false;
|
|
428
455
|
if let Some(runs_arr) =
|
|
429
456
|
obj.get("runs").and_then(|r| r.as_array())
|
|
@@ -437,12 +464,22 @@ fn main() -> Result<()> {
|
|
|
437
464
|
parsed.push(info);
|
|
438
465
|
}
|
|
439
466
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
467
|
+
let preserve =
|
|
468
|
+
!app.state.run_manager.runs.is_empty();
|
|
469
|
+
if preserve {
|
|
470
|
+
app.state
|
|
471
|
+
.run_manager
|
|
472
|
+
.replace_runs_preserve(parsed);
|
|
473
|
+
} else {
|
|
474
|
+
app.state.run_manager.replace_runs(parsed);
|
|
475
|
+
}
|
|
476
|
+
if !silent {
|
|
477
|
+
app.add_log(format!(
|
|
478
|
+
"✓ [{}] Loaded {} run(s) from Gateway",
|
|
479
|
+
short_id,
|
|
480
|
+
app.state.run_manager.runs.len()
|
|
481
|
+
));
|
|
482
|
+
}
|
|
446
483
|
app.request_render("run_list_loaded");
|
|
447
484
|
} else {
|
|
448
485
|
app.add_log(format!(
|
|
@@ -1288,6 +1325,7 @@ fn main() -> Result<()> {
|
|
|
1288
1325
|
));
|
|
1289
1326
|
} else if Some(&resp.id) == app.state.pending_run_list_id.as_ref() {
|
|
1290
1327
|
app.state.pending_run_list_id = None;
|
|
1328
|
+
app.state.pending_run_list_silent = false;
|
|
1291
1329
|
app.state.run_manager.loading = false;
|
|
1292
1330
|
app.add_log(format!(
|
|
1293
1331
|
"✗ [{}] run.list failed: {}",
|
|
@@ -40,6 +40,10 @@ pub struct RunManagerState {
|
|
|
40
40
|
|
|
41
41
|
/// Detailed view state (None = list view, Some(index) = detail view)
|
|
42
42
|
pub detail_view: Option<usize>,
|
|
43
|
+
|
|
44
|
+
/// Poll Gateway for run list while Run Manager is open (no manual R).
|
|
45
|
+
pub auto_refresh_enabled: bool,
|
|
46
|
+
pub auto_refresh_interval: std::time::Duration,
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
#[derive(Debug, Clone)]
|
|
@@ -153,6 +157,8 @@ impl Default for RunManagerState {
|
|
|
153
157
|
loading: false,
|
|
154
158
|
last_refresh: None,
|
|
155
159
|
detail_view: None,
|
|
160
|
+
auto_refresh_enabled: true,
|
|
161
|
+
auto_refresh_interval: std::time::Duration::from_secs(3),
|
|
156
162
|
}
|
|
157
163
|
}
|
|
158
164
|
}
|
|
@@ -282,6 +288,36 @@ impl RunManagerState {
|
|
|
282
288
|
self.last_refresh = Some(std::time::Instant::now());
|
|
283
289
|
}
|
|
284
290
|
|
|
291
|
+
/// Auto-refresh: keep selection and detail view when the selected run still exists.
|
|
292
|
+
pub fn replace_runs_preserve(&mut self, runs: Vec<RunInfo>) {
|
|
293
|
+
let selected_id = self.selected_run().map(|r| r.id.clone());
|
|
294
|
+
let in_detail = self.detail_view.is_some();
|
|
295
|
+
self.runs = runs;
|
|
296
|
+
self.loading = false;
|
|
297
|
+
self.last_refresh = Some(std::time::Instant::now());
|
|
298
|
+
|
|
299
|
+
let filtered = self.filtered_runs();
|
|
300
|
+
if filtered.is_empty() {
|
|
301
|
+
self.selected_index = 0;
|
|
302
|
+
self.detail_view = None;
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if let Some(id) = selected_id {
|
|
307
|
+
if let Some(idx) = filtered.iter().position(|r| r.id == id) {
|
|
308
|
+
self.selected_index = idx;
|
|
309
|
+
} else if self.selected_index >= filtered.len() {
|
|
310
|
+
self.selected_index = filtered.len() - 1;
|
|
311
|
+
}
|
|
312
|
+
} else if self.selected_index >= filtered.len() {
|
|
313
|
+
self.selected_index = filtered.len() - 1;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if in_detail && self.selected_run().is_none() {
|
|
317
|
+
self.detail_view = None;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
285
321
|
pub fn clear_runs(&mut self) {
|
|
286
322
|
self.runs.clear();
|
|
287
323
|
self.selected_index = 0;
|
|
@@ -425,12 +461,19 @@ fn render_header(f: &mut Frame, area: Rect, state: &RunManagerState) {
|
|
|
425
461
|
let filtered_count = state.filtered_runs().len();
|
|
426
462
|
let total_count = state.runs.len();
|
|
427
463
|
|
|
464
|
+
let live = if state.auto_refresh_enabled {
|
|
465
|
+
" · LIVE"
|
|
466
|
+
} else {
|
|
467
|
+
""
|
|
468
|
+
};
|
|
469
|
+
|
|
428
470
|
let block = Block::default()
|
|
429
471
|
.title(format!(
|
|
430
|
-
" ⚡ Run Manager - {} ({}/{} runs) ",
|
|
472
|
+
" ⚡ Run Manager - {} ({}/{} runs){} ",
|
|
431
473
|
state.filter.as_str(),
|
|
432
474
|
filtered_count,
|
|
433
|
-
total_count
|
|
475
|
+
total_count,
|
|
476
|
+
live
|
|
434
477
|
))
|
|
435
478
|
.borders(Borders::ALL)
|
|
436
479
|
.border_style(Style::default().fg(BRAND_PURPLE))
|
|
@@ -776,6 +819,8 @@ fn render_actions(f: &mut Frame, area: Rect) {
|
|
|
776
819
|
Span::styled(" Sort │ ", Style::default().fg(TEXT_DIM)),
|
|
777
820
|
Span::styled("R", Style::default().fg(NEON_GREEN).bold()),
|
|
778
821
|
Span::styled(" Refresh │ ", Style::default().fg(TEXT_DIM)),
|
|
822
|
+
Span::styled("A", Style::default().fg(CYBER_CYAN).bold()),
|
|
823
|
+
Span::styled(" Live │ ", Style::default().fg(TEXT_DIM)),
|
|
779
824
|
Span::styled("C", Style::default().fg(Color::Rgb(255, 69, 69)).bold()),
|
|
780
825
|
Span::styled(" Cancel │ ", Style::default().fg(TEXT_DIM)),
|
|
781
826
|
Span::styled("D", Style::default().fg(Color::Rgb(255, 69, 69)).bold()),
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "4runr-os",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.56",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.
|
|
5
|
+
"description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.10.56: Run Manager live auto-refresh (~3s); DDoS loopback exempt for local dev/smoke; run retention + local API key; 4Runr Tools bundle.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"4runr": "dist/index.js",
|
|
@@ -395,11 +395,12 @@ Env:
|
|
|
395
395
|
|
|
396
396
|
await checkSentinelHealth(base, apiKey);
|
|
397
397
|
await checkShieldHealth(base, apiKey);
|
|
398
|
+
await sleep(1500);
|
|
398
399
|
await smokeSentinelCancel(base, apiKey);
|
|
399
400
|
if (args.full) {
|
|
400
|
-
await sleep(
|
|
401
|
+
await sleep(5000);
|
|
401
402
|
await smokeSentinelIdleKill(base, apiKey);
|
|
402
|
-
await sleep(
|
|
403
|
+
await sleep(5000);
|
|
403
404
|
} else {
|
|
404
405
|
console.log(colors.dim(' (skip N5 idle kill — use --full)'));
|
|
405
406
|
}
|