@vendian/cli 0.0.28 → 0.0.30
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/cli-wrapper.mjs +250 -36
- package/package.json +1 -1
package/cli-wrapper.mjs
CHANGED
|
@@ -1107,7 +1107,7 @@ import path8 from "node:path";
|
|
|
1107
1107
|
import readlinePromises from "node:readline/promises";
|
|
1108
1108
|
|
|
1109
1109
|
// src/version.js
|
|
1110
|
-
var CLI_VERSION = true ? "0.0.
|
|
1110
|
+
var CLI_VERSION = true ? "0.0.30" : process.env.npm_package_version || "0.0.0-dev";
|
|
1111
1111
|
|
|
1112
1112
|
// src/npm-update.js
|
|
1113
1113
|
var NPM_CHECK_INTERVAL_MS = 30 * 60 * 1e3;
|
|
@@ -2399,6 +2399,87 @@ async function loadTerm() {
|
|
|
2399
2399
|
}
|
|
2400
2400
|
var HEADER_ROWS_BASE = 7;
|
|
2401
2401
|
var SERVE_CONTENT_ROW = 10;
|
|
2402
|
+
function clampListIndex(index, count) {
|
|
2403
|
+
if (!Number.isFinite(count) || count <= 0) return 0;
|
|
2404
|
+
if (!Number.isFinite(index)) return 0;
|
|
2405
|
+
return Math.max(0, Math.min(count - 1, index));
|
|
2406
|
+
}
|
|
2407
|
+
function centeredWindowStart(selectedIdx, visibleCount, totalCount) {
|
|
2408
|
+
if (visibleCount >= totalCount) return 0;
|
|
2409
|
+
const half = Math.floor(visibleCount / 2);
|
|
2410
|
+
const maxStart = Math.max(0, totalCount - visibleCount);
|
|
2411
|
+
return Math.max(0, Math.min(maxStart, selectedIdx - half));
|
|
2412
|
+
}
|
|
2413
|
+
function computeServeDashboardViewport({
|
|
2414
|
+
termHeight = 24,
|
|
2415
|
+
agentCount = 0,
|
|
2416
|
+
selectedIdx = 0,
|
|
2417
|
+
activityCount = 0,
|
|
2418
|
+
diagnosticsCount = 0
|
|
2419
|
+
} = {}) {
|
|
2420
|
+
const availableRows = Math.max(4, (termHeight || 24) - SERVE_CONTENT_ROW + 1);
|
|
2421
|
+
const clampedSelectedIdx = clampListIndex(selectedIdx, agentCount);
|
|
2422
|
+
const viewport = {
|
|
2423
|
+
selectedIdx: clampedSelectedIdx,
|
|
2424
|
+
showBlankAfterStatus: false,
|
|
2425
|
+
showAgentHeader: agentCount > 0,
|
|
2426
|
+
visibleAgentCount: 0,
|
|
2427
|
+
agentWindowStart: 0,
|
|
2428
|
+
showAgentHint: false,
|
|
2429
|
+
showAgentRange: false,
|
|
2430
|
+
visibleActivityCount: 0,
|
|
2431
|
+
showActivityHeader: false,
|
|
2432
|
+
visibleDiagnosticsCount: 0,
|
|
2433
|
+
showDiagnosticsHeader: false,
|
|
2434
|
+
showInlineErrors: (termHeight || 24) >= 24
|
|
2435
|
+
};
|
|
2436
|
+
let remaining = availableRows;
|
|
2437
|
+
remaining -= 1;
|
|
2438
|
+
remaining -= 1;
|
|
2439
|
+
if (agentCount > 0) {
|
|
2440
|
+
remaining -= 1;
|
|
2441
|
+
viewport.visibleAgentCount = 1;
|
|
2442
|
+
remaining -= 1;
|
|
2443
|
+
} else {
|
|
2444
|
+
remaining -= 1;
|
|
2445
|
+
}
|
|
2446
|
+
if (remaining > 0) {
|
|
2447
|
+
viewport.showBlankAfterStatus = true;
|
|
2448
|
+
remaining -= 1;
|
|
2449
|
+
}
|
|
2450
|
+
if (agentCount > 1 && remaining > 0) {
|
|
2451
|
+
const extraAgentRows = Math.min(agentCount - 1, remaining);
|
|
2452
|
+
viewport.visibleAgentCount += extraAgentRows;
|
|
2453
|
+
remaining -= extraAgentRows;
|
|
2454
|
+
}
|
|
2455
|
+
if (agentCount > 0) {
|
|
2456
|
+
viewport.agentWindowStart = centeredWindowStart(
|
|
2457
|
+
clampedSelectedIdx,
|
|
2458
|
+
viewport.visibleAgentCount,
|
|
2459
|
+
agentCount
|
|
2460
|
+
);
|
|
2461
|
+
viewport.showAgentHint = remaining > 0;
|
|
2462
|
+
if (viewport.showAgentHint) remaining -= 1;
|
|
2463
|
+
viewport.showAgentRange = viewport.visibleAgentCount > 0 && viewport.visibleAgentCount < agentCount;
|
|
2464
|
+
}
|
|
2465
|
+
if (activityCount > 0 && remaining > 1) {
|
|
2466
|
+
viewport.showActivityHeader = true;
|
|
2467
|
+
remaining -= 1;
|
|
2468
|
+
viewport.visibleActivityCount = Math.min(activityCount, remaining);
|
|
2469
|
+
remaining -= viewport.visibleActivityCount;
|
|
2470
|
+
}
|
|
2471
|
+
if (diagnosticsCount > 0 && remaining > 1) {
|
|
2472
|
+
viewport.showDiagnosticsHeader = true;
|
|
2473
|
+
remaining -= 1;
|
|
2474
|
+
viewport.visibleDiagnosticsCount = Math.min(diagnosticsCount, remaining);
|
|
2475
|
+
}
|
|
2476
|
+
return viewport;
|
|
2477
|
+
}
|
|
2478
|
+
function stopSignalForAttempt(attempt = 0) {
|
|
2479
|
+
if (!Number.isFinite(attempt) || attempt <= 0) return "SIGINT";
|
|
2480
|
+
if (attempt === 1) return "SIGTERM";
|
|
2481
|
+
return "SIGKILL";
|
|
2482
|
+
}
|
|
2402
2483
|
async function runTui({
|
|
2403
2484
|
env = process.env,
|
|
2404
2485
|
platform = process.platform,
|
|
@@ -2912,6 +2993,10 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
2912
2993
|
let dashboardClosed = false;
|
|
2913
2994
|
let exitPromptActive = false;
|
|
2914
2995
|
let selectedIdx = 0;
|
|
2996
|
+
let pressedAgentIdx = null;
|
|
2997
|
+
let stopRequested = false;
|
|
2998
|
+
let stopSignalAttempt = 0;
|
|
2999
|
+
let stopTimer = null;
|
|
2915
3000
|
const agentRowMap = /* @__PURE__ */ new Map();
|
|
2916
3001
|
function agentDisplayList() {
|
|
2917
3002
|
return state.agents.map((agent, i) => {
|
|
@@ -2939,12 +3024,26 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
2939
3024
|
}
|
|
2940
3025
|
function redraw() {
|
|
2941
3026
|
if (dashboardClosed || overlayActive) return;
|
|
3027
|
+
const agents = agentDisplayList();
|
|
3028
|
+
const activity = recentActivityLines();
|
|
3029
|
+
const diagnostics = daemonDebugLines();
|
|
3030
|
+
const viewport = computeServeDashboardViewport({
|
|
3031
|
+
termHeight: term.height || 24,
|
|
3032
|
+
agentCount: agents.length,
|
|
3033
|
+
selectedIdx,
|
|
3034
|
+
activityCount: activity.length,
|
|
3035
|
+
diagnosticsCount: diagnostics.length
|
|
3036
|
+
});
|
|
3037
|
+
selectedIdx = viewport.selectedIdx;
|
|
2942
3038
|
drawHeader({ env, platform, serveState: state });
|
|
2943
3039
|
term.moveTo(1, SERVE_CONTENT_ROW);
|
|
2944
3040
|
term.eraseDisplayBelow();
|
|
2945
3041
|
agentRowMap.clear();
|
|
2946
3042
|
if (startupError) {
|
|
2947
3043
|
term.red(` ${fig.cross} ${clip(startupError, (term.width || 80) - 6)}
|
|
3044
|
+
`);
|
|
3045
|
+
} else if (stopRequested) {
|
|
3046
|
+
term.yellow(` ${fig.warning} ${clip(state.activity || "Stopping your agents\u2026", (term.width || 80) - 6)}
|
|
2948
3047
|
`);
|
|
2949
3048
|
} else if (state.stopped) {
|
|
2950
3049
|
term.yellow(` ${fig.warning} Your agents have stopped.
|
|
@@ -2958,12 +3057,15 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
2958
3057
|
term.gray(`${clip(state.activity || "Starting up\u2026", 55)}
|
|
2959
3058
|
`);
|
|
2960
3059
|
}
|
|
2961
|
-
const agents = agentDisplayList();
|
|
2962
3060
|
if (agents.length > 0) {
|
|
2963
|
-
term("\n");
|
|
3061
|
+
if (viewport.showBlankAfterStatus) term("\n");
|
|
2964
3062
|
term.bold.gray(" Your agents:\n");
|
|
2965
|
-
let lineOffset = SERVE_CONTENT_ROW +
|
|
2966
|
-
|
|
3063
|
+
let lineOffset = SERVE_CONTENT_ROW + 2 + (viewport.showBlankAfterStatus ? 1 : 0);
|
|
3064
|
+
const visibleAgents = agents.slice(
|
|
3065
|
+
viewport.agentWindowStart,
|
|
3066
|
+
viewport.agentWindowStart + viewport.visibleAgentCount
|
|
3067
|
+
);
|
|
3068
|
+
for (const ag of visibleAgents) {
|
|
2967
3069
|
const isSelected = ag.num - 1 === selectedIdx;
|
|
2968
3070
|
agentRowMap.set(lineOffset, ag.num - 1);
|
|
2969
3071
|
const numStr = String(ag.num).padStart(2);
|
|
@@ -3014,26 +3116,32 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3014
3116
|
}
|
|
3015
3117
|
term("\n");
|
|
3016
3118
|
lineOffset++;
|
|
3017
|
-
if (ag.errMsg) {
|
|
3119
|
+
if (viewport.showInlineErrors && isSelected && ag.errMsg) {
|
|
3018
3120
|
term.red(` \u2514\u2500 ${clip(ag.errMsg, (term.width || 80) - 14)}
|
|
3019
3121
|
`);
|
|
3020
3122
|
lineOffset++;
|
|
3021
3123
|
}
|
|
3022
3124
|
}
|
|
3023
|
-
|
|
3024
|
-
|
|
3125
|
+
if (viewport.showAgentRange) {
|
|
3126
|
+
const first = viewport.agentWindowStart + 1;
|
|
3127
|
+
const last = viewport.agentWindowStart + visibleAgents.length;
|
|
3128
|
+
term.gray(` Showing agents ${first}\u2013${last} of ${agents.length}
|
|
3129
|
+
`);
|
|
3130
|
+
}
|
|
3131
|
+
if (viewport.showAgentHint) {
|
|
3132
|
+
term.gray(` Click an agent or use \u2191\u2193 + Enter to see its activity log
|
|
3025
3133
|
`);
|
|
3134
|
+
}
|
|
3026
3135
|
} else {
|
|
3027
|
-
term("\n");
|
|
3136
|
+
if (viewport.showBlankAfterStatus) term("\n");
|
|
3028
3137
|
term.gray(" Looking for your agents\u2026\n");
|
|
3029
3138
|
}
|
|
3030
|
-
|
|
3031
|
-
|
|
3139
|
+
if (viewport.showActivityHeader) {
|
|
3140
|
+
const visibleActivity = activity.slice(-viewport.visibleActivityCount);
|
|
3032
3141
|
const divW = Math.min((term.width || 80) - 4, 60);
|
|
3033
|
-
term("\n");
|
|
3034
3142
|
term.gray(` ${"\u2500".repeat(3)} Recent activity ${"\u2500".repeat(Math.max(0, divW - 18))}
|
|
3035
3143
|
`);
|
|
3036
|
-
for (const e of
|
|
3144
|
+
for (const e of visibleActivity) {
|
|
3037
3145
|
const t = formatLogTime(e.timestamp);
|
|
3038
3146
|
const name = clip(e._agentName || "Agent", 20);
|
|
3039
3147
|
const msg = clip(friendlyActivityLine(e), (term.width || 80) - 30);
|
|
@@ -3055,13 +3163,12 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3055
3163
|
}
|
|
3056
3164
|
}
|
|
3057
3165
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3166
|
+
if (viewport.showDiagnosticsHeader) {
|
|
3167
|
+
const visibleDiagnostics = diagnostics.slice(-viewport.visibleDiagnosticsCount);
|
|
3060
3168
|
const divW = Math.min((term.width || 80) - 4, 72);
|
|
3061
|
-
term("\n");
|
|
3062
3169
|
term.gray(` ${"\u2500".repeat(3)} Daemon diagnostics ${"\u2500".repeat(Math.max(0, divW - 23))}
|
|
3063
3170
|
`);
|
|
3064
|
-
for (const entry of
|
|
3171
|
+
for (const entry of visibleDiagnostics) {
|
|
3065
3172
|
const t = formatLogTime(entry.timestamp);
|
|
3066
3173
|
const type = clip(entry.eventType || "event", 24).padEnd(24);
|
|
3067
3174
|
const msg = clip(entry.message || "", (term.width || 80) - 38);
|
|
@@ -3081,6 +3188,10 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3081
3188
|
term("\n");
|
|
3082
3189
|
if (ctrlCArmed) {
|
|
3083
3190
|
term.yellow.bold(" Press Ctrl+C again to exit.\n");
|
|
3191
|
+
} else if (stopRequested) {
|
|
3192
|
+
term.yellow(" Stopping your agents\u2026");
|
|
3193
|
+
if (stopSignalAttempt > 0) term.gray(" (retrying shutdown)");
|
|
3194
|
+
term("\n");
|
|
3084
3195
|
} else {
|
|
3085
3196
|
term.gray(" ");
|
|
3086
3197
|
term.brightBlue.bold("S");
|
|
@@ -3137,10 +3248,12 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3137
3248
|
}
|
|
3138
3249
|
return new Promise((resolve) => {
|
|
3139
3250
|
function openAgentLog(idx) {
|
|
3140
|
-
|
|
3251
|
+
const agents = agentDisplayList();
|
|
3252
|
+
const clampedIdx = clampListIndex(idx, agents.length);
|
|
3253
|
+
if (dashboardClosed || exitPromptActive || agents.length === 0 || idx !== clampedIdx) return;
|
|
3141
3254
|
overlayActive = true;
|
|
3142
|
-
const ag =
|
|
3143
|
-
showAgentLog({ agent: ag, state, env, platform }).then(() => {
|
|
3255
|
+
const ag = agents[clampedIdx];
|
|
3256
|
+
showAgentLog({ agent: ag, getState: () => state, env, platform }).then(() => {
|
|
3144
3257
|
if (dashboardClosed) return;
|
|
3145
3258
|
overlayActive = false;
|
|
3146
3259
|
term.clear();
|
|
@@ -3154,14 +3267,62 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3154
3267
|
ctrlCArmTimer = null;
|
|
3155
3268
|
}
|
|
3156
3269
|
}
|
|
3270
|
+
function clearStopTimer() {
|
|
3271
|
+
if (stopTimer) {
|
|
3272
|
+
clearTimeout(stopTimer);
|
|
3273
|
+
stopTimer = null;
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
function childIsRunning() {
|
|
3277
|
+
return Boolean(child) && child.exitCode == null && child.signalCode == null;
|
|
3278
|
+
}
|
|
3279
|
+
function scheduleStopEscalation() {
|
|
3280
|
+
clearStopTimer();
|
|
3281
|
+
if (!childIsRunning()) return;
|
|
3282
|
+
stopTimer = setTimeout(() => {
|
|
3283
|
+
if (!stopRequested || dashboardClosed || !childIsRunning()) return;
|
|
3284
|
+
stopSignalAttempt += 1;
|
|
3285
|
+
const signal = stopSignalForAttempt(stopSignalAttempt);
|
|
3286
|
+
state = {
|
|
3287
|
+
...state,
|
|
3288
|
+
activity: signal === "SIGTERM" ? "Still stopping your agents\u2026" : "Force stopping your agents\u2026"
|
|
3289
|
+
};
|
|
3290
|
+
try {
|
|
3291
|
+
child.kill(signal);
|
|
3292
|
+
} catch {
|
|
3293
|
+
}
|
|
3294
|
+
if (!overlayActive) redraw();
|
|
3295
|
+
if (signal !== "SIGKILL") scheduleStopEscalation();
|
|
3296
|
+
}, 4e3);
|
|
3297
|
+
}
|
|
3298
|
+
function requestStop() {
|
|
3299
|
+
if (dashboardClosed) return;
|
|
3300
|
+
if (stopRequested) return;
|
|
3301
|
+
if (!childIsRunning()) {
|
|
3302
|
+
finish("home");
|
|
3303
|
+
return;
|
|
3304
|
+
}
|
|
3305
|
+
stopRequested = true;
|
|
3306
|
+
stopSignalAttempt = 0;
|
|
3307
|
+
state = { ...state, activity: "Stopping your agents\u2026" };
|
|
3308
|
+
clearCtrlCArm();
|
|
3309
|
+
try {
|
|
3310
|
+
child.kill(stopSignalForAttempt(stopSignalAttempt));
|
|
3311
|
+
} catch {
|
|
3312
|
+
}
|
|
3313
|
+
scheduleStopEscalation();
|
|
3314
|
+
if (!overlayActive) redraw();
|
|
3315
|
+
}
|
|
3157
3316
|
function detachDashboardHandlers() {
|
|
3158
3317
|
term.off("key", handleKey);
|
|
3159
3318
|
term.off("mouse", handleMouse);
|
|
3319
|
+
term.off("resize", handleResize);
|
|
3160
3320
|
}
|
|
3161
3321
|
function finish(next) {
|
|
3162
3322
|
if (dashboardClosed) return;
|
|
3163
3323
|
dashboardClosed = true;
|
|
3164
3324
|
clearCtrlCArm();
|
|
3325
|
+
clearStopTimer();
|
|
3165
3326
|
detachDashboardHandlers();
|
|
3166
3327
|
resolve(next);
|
|
3167
3328
|
}
|
|
@@ -3181,41 +3342,62 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3181
3342
|
return;
|
|
3182
3343
|
}
|
|
3183
3344
|
if (overlayActive) return;
|
|
3184
|
-
|
|
3345
|
+
if (stopRequested) return;
|
|
3346
|
+
const agCount = agentDisplayList().length;
|
|
3185
3347
|
if (name >= "1" && name <= "9") {
|
|
3186
3348
|
openAgentLog(parseInt(name, 10) - 1);
|
|
3187
3349
|
return;
|
|
3188
3350
|
}
|
|
3189
3351
|
if (name === "UP" && agCount > 0) {
|
|
3190
|
-
selectedIdx = (selectedIdx - 1
|
|
3352
|
+
selectedIdx = clampListIndex(selectedIdx - 1, agCount);
|
|
3191
3353
|
redraw();
|
|
3192
3354
|
} else if (name === "DOWN" && agCount > 0) {
|
|
3193
|
-
selectedIdx = (selectedIdx + 1
|
|
3355
|
+
selectedIdx = clampListIndex(selectedIdx + 1, agCount);
|
|
3194
3356
|
redraw();
|
|
3195
3357
|
} else if (name === "ENTER") {
|
|
3196
3358
|
openAgentLog(selectedIdx);
|
|
3197
3359
|
} else if (name === "s" || name === "S") {
|
|
3198
|
-
|
|
3199
|
-
finish("home");
|
|
3360
|
+
requestStop();
|
|
3200
3361
|
}
|
|
3201
3362
|
}
|
|
3202
3363
|
function handleMouse(name, data) {
|
|
3203
|
-
if (overlayActive) return;
|
|
3364
|
+
if (overlayActive || stopRequested) return;
|
|
3204
3365
|
const idx = agentRowMap.get(data.y);
|
|
3205
|
-
if (idx === void 0) return;
|
|
3206
3366
|
if (name === "MOUSE_LEFT_BUTTON_PRESSED") {
|
|
3207
|
-
|
|
3208
|
-
|
|
3367
|
+
pressedAgentIdx = idx ?? null;
|
|
3368
|
+
if (idx !== void 0 && idx !== selectedIdx) {
|
|
3369
|
+
selectedIdx = idx;
|
|
3370
|
+
redraw();
|
|
3371
|
+
}
|
|
3372
|
+
return;
|
|
3373
|
+
}
|
|
3374
|
+
if (name === "MOUSE_LEFT_BUTTON_RELEASED") {
|
|
3375
|
+
const shouldOpen = idx !== void 0 && idx === pressedAgentIdx;
|
|
3376
|
+
pressedAgentIdx = null;
|
|
3377
|
+
if (shouldOpen) openAgentLog(idx);
|
|
3378
|
+
return;
|
|
3379
|
+
}
|
|
3380
|
+
if (idx === void 0) return;
|
|
3381
|
+
if (name !== "MOUSE_LEFT_BUTTON_RELEASED") {
|
|
3209
3382
|
if (idx !== selectedIdx) {
|
|
3210
3383
|
selectedIdx = idx;
|
|
3211
3384
|
redraw();
|
|
3212
3385
|
}
|
|
3213
3386
|
}
|
|
3214
3387
|
}
|
|
3388
|
+
function handleResize() {
|
|
3389
|
+
if (!overlayActive) redraw();
|
|
3390
|
+
}
|
|
3215
3391
|
term.on("key", handleKey);
|
|
3216
3392
|
term.on("mouse", handleMouse);
|
|
3393
|
+
term.on("resize", handleResize);
|
|
3217
3394
|
if (child) {
|
|
3218
3395
|
child.once("exit", () => {
|
|
3396
|
+
clearStopTimer();
|
|
3397
|
+
if (stopRequested) {
|
|
3398
|
+
finish("home");
|
|
3399
|
+
return;
|
|
3400
|
+
}
|
|
3219
3401
|
setTimeout(() => {
|
|
3220
3402
|
if (dashboardClosed || overlayActive) return;
|
|
3221
3403
|
exitPromptActive = true;
|
|
@@ -3229,14 +3411,23 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
|
3229
3411
|
}
|
|
3230
3412
|
});
|
|
3231
3413
|
}
|
|
3232
|
-
async function showAgentLog({ agent,
|
|
3233
|
-
const
|
|
3234
|
-
const agentObj = state.agents.find((a) => (a.relativePath || ".") === agent.path);
|
|
3235
|
-
const runtime = agentObj ? agentRuntimeStatus(agentObj, state.agentRunState) : { status: "unknown", label: "offline" };
|
|
3236
|
-
const status = friendlyStatus(runtime.status);
|
|
3414
|
+
async function showAgentLog({ agent, getState, env, platform }) {
|
|
3415
|
+
const liveState = typeof getState === "function" ? getState : () => getState;
|
|
3237
3416
|
let scrollOffset = 0;
|
|
3417
|
+
let autoScroll = true;
|
|
3238
3418
|
const visibleCount = Math.max(8, (term.height || 24) - 14);
|
|
3419
|
+
function currentLogs() {
|
|
3420
|
+
return agentLogEntries(liveState().agentLogs, agent.path);
|
|
3421
|
+
}
|
|
3239
3422
|
function draw() {
|
|
3423
|
+
const state = liveState();
|
|
3424
|
+
const logs = currentLogs();
|
|
3425
|
+
const agentObj = state.agents.find((a) => (a.relativePath || ".") === agent.path);
|
|
3426
|
+
const runtime = agentObj ? agentRuntimeStatus(agentObj, state.agentRunState) : { status: "unknown", label: "offline" };
|
|
3427
|
+
const status = friendlyStatus(runtime.status);
|
|
3428
|
+
if (autoScroll) {
|
|
3429
|
+
scrollOffset = Math.max(0, logs.length - visibleCount);
|
|
3430
|
+
}
|
|
3240
3431
|
term.clear();
|
|
3241
3432
|
drawHeader({ env, platform, serveState: state });
|
|
3242
3433
|
term("\n");
|
|
@@ -3301,27 +3492,50 @@ async function showAgentLog({ agent, state, env, platform }) {
|
|
|
3301
3492
|
term.gray(" scroll ");
|
|
3302
3493
|
term.brightBlue.bold("PgUp/PgDn");
|
|
3303
3494
|
term.gray(" page ");
|
|
3304
|
-
|
|
3305
|
-
|
|
3495
|
+
if (autoScroll) {
|
|
3496
|
+
term.brightBlue.bold("Esc");
|
|
3497
|
+
term.gray(" back ");
|
|
3498
|
+
term.cyan("\u2193 live\n");
|
|
3499
|
+
} else {
|
|
3500
|
+
term.brightBlue.bold("Esc");
|
|
3501
|
+
term.gray(" back ");
|
|
3502
|
+
term.gray("\u2193 ");
|
|
3503
|
+
term.brightBlue.bold("End");
|
|
3504
|
+
term.gray(" resume live\n");
|
|
3505
|
+
}
|
|
3306
3506
|
}
|
|
3307
3507
|
draw();
|
|
3508
|
+
let overlayDone = false;
|
|
3509
|
+
const redrawInterval = setInterval(() => {
|
|
3510
|
+
if (!overlayDone) draw();
|
|
3511
|
+
}, 500);
|
|
3308
3512
|
await new Promise((resolve) => {
|
|
3309
3513
|
function handler(name) {
|
|
3514
|
+
const logs = currentLogs();
|
|
3310
3515
|
const maxOff = Math.max(0, logs.length - visibleCount);
|
|
3311
3516
|
if (name === "ESCAPE") {
|
|
3312
3517
|
term.off("key", handler);
|
|
3518
|
+
overlayDone = true;
|
|
3519
|
+
clearInterval(redrawInterval);
|
|
3313
3520
|
resolve();
|
|
3314
3521
|
} else if (name === "UP") {
|
|
3522
|
+
autoScroll = false;
|
|
3315
3523
|
scrollOffset = Math.max(0, scrollOffset - 1);
|
|
3316
3524
|
draw();
|
|
3317
3525
|
} else if (name === "DOWN") {
|
|
3318
3526
|
scrollOffset = Math.min(maxOff, scrollOffset + 1);
|
|
3527
|
+
if (scrollOffset >= maxOff) autoScroll = true;
|
|
3319
3528
|
draw();
|
|
3320
3529
|
} else if (name === "PAGE_UP") {
|
|
3530
|
+
autoScroll = false;
|
|
3321
3531
|
scrollOffset = Math.max(0, scrollOffset - visibleCount);
|
|
3322
3532
|
draw();
|
|
3323
3533
|
} else if (name === "PAGE_DOWN") {
|
|
3324
3534
|
scrollOffset = Math.min(maxOff, scrollOffset + visibleCount);
|
|
3535
|
+
if (scrollOffset >= maxOff) autoScroll = true;
|
|
3536
|
+
draw();
|
|
3537
|
+
} else if (name === "END") {
|
|
3538
|
+
autoScroll = true;
|
|
3325
3539
|
draw();
|
|
3326
3540
|
}
|
|
3327
3541
|
}
|