@nmakarov/cli-toolkit 0.69.0 → 0.70.0
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/dist/cli-runner.cjs +312 -181
- package/dist/cli-runner.cjs.map +1 -1
- package/dist/cli-runner.js +312 -181
- package/dist/cli-runner.js.map +1 -1
- package/dist/index.cjs +350 -197
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +344 -197
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +129 -91
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +129 -91
- package/dist/init.js.map +1 -1
- package/dist/screen.cjs +124 -90
- package/dist/screen.cjs.map +1 -1
- package/dist/screen.js +121 -90
- package/dist/screen.js.map +1 -1
- package/dist/tasks.cjs +218 -106
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.js +215 -106
- package/dist/tasks.js.map +1 -1
- package/package.json +2 -2
package/dist/cli-runner.js
CHANGED
|
@@ -94,9 +94,48 @@ var init_components = __esm({
|
|
|
94
94
|
}
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
+
// src/screen/scrollbar.js
|
|
98
|
+
function scrollbarGlyphs(viewportRows, totalLines, scrollTop) {
|
|
99
|
+
const view = Math.max(1, Math.floor(viewportRows));
|
|
100
|
+
const total = Math.max(0, Math.floor(totalLines));
|
|
101
|
+
if (total <= view) return null;
|
|
102
|
+
const maxScroll = total - view;
|
|
103
|
+
const thumbSize = Math.max(1, Math.round(view / total * view));
|
|
104
|
+
const travel = Math.max(0, view - thumbSize);
|
|
105
|
+
const s = Math.min(Math.max(0, Math.floor(scrollTop)), maxScroll);
|
|
106
|
+
const thumbStart = maxScroll === 0 ? 0 : Math.round(s / maxScroll * travel);
|
|
107
|
+
const glyphs = [];
|
|
108
|
+
for (let i = 0; i < view; i++) {
|
|
109
|
+
glyphs.push(i >= thumbStart && i < thumbStart + thumbSize ? BAR_THUMB : BAR_TRACK);
|
|
110
|
+
}
|
|
111
|
+
return glyphs;
|
|
112
|
+
}
|
|
113
|
+
var BAR_THUMB, BAR_TRACK, PAGE_SCROLL_KEY_BINDINGS;
|
|
114
|
+
var init_scrollbar = __esm({
|
|
115
|
+
"src/screen/scrollbar.js"() {
|
|
116
|
+
BAR_THUMB = "#";
|
|
117
|
+
BAR_TRACK = "|";
|
|
118
|
+
PAGE_SCROLL_KEY_BINDINGS = [
|
|
119
|
+
{ key: "upArrow", meta: true, caption: "page", action: "pageUp", order: 0 },
|
|
120
|
+
{ key: "downArrow", meta: true, caption: "page", action: "pageDown", order: 0 },
|
|
121
|
+
{ key: "upArrow", ctrl: true, caption: "page", action: "pageUp", order: 0 },
|
|
122
|
+
{ key: "downArrow", ctrl: true, caption: "page", action: "pageDown", order: 0 },
|
|
123
|
+
{ key: "pageUp", caption: "page", action: "pageUp", order: 0 },
|
|
124
|
+
{ key: "pageDown", caption: "page", action: "pageDown", order: 0 }
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
97
129
|
// src/screen/list-components.js
|
|
98
130
|
import React, { useState, useEffect, useRef, createElement } from "react";
|
|
99
131
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
132
|
+
function clipNameForScrollbar(name, needsBar) {
|
|
133
|
+
if (!needsBar || name == null) return name;
|
|
134
|
+
const s = String(name);
|
|
135
|
+
if (s.length <= 1) return s;
|
|
136
|
+
if (/\s$/.test(s)) return s.slice(0, -1);
|
|
137
|
+
return s;
|
|
138
|
+
}
|
|
100
139
|
function MultiColumnListComponent({ items, ctx, selectedIndexRef }) {
|
|
101
140
|
const [, forceUpdate] = useState({});
|
|
102
141
|
const termWidth = (process.stdout.columns || 80) - 8;
|
|
@@ -310,17 +349,42 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
310
349
|
});
|
|
311
350
|
ctx.setAction("scrollUp", () => {
|
|
312
351
|
const { scrollOffset: currentScrollOffset } = scrollStateRef.current;
|
|
313
|
-
|
|
314
|
-
setScrollOffset(newScrollOffset);
|
|
352
|
+
setScrollOffset(Math.max(0, currentScrollOffset - 1));
|
|
315
353
|
forceUpdate({});
|
|
316
354
|
});
|
|
317
355
|
ctx.setAction("scrollDown", () => {
|
|
318
356
|
const { scrollOffset: currentScrollOffset, maxHeight: currentMaxHeight, totalItems } = scrollStateRef.current;
|
|
319
357
|
const currentMaxScrollOffset = Math.max(0, totalItems - currentMaxHeight);
|
|
320
|
-
|
|
321
|
-
|
|
358
|
+
setScrollOffset(Math.min(currentMaxScrollOffset, currentScrollOffset + 1));
|
|
359
|
+
forceUpdate({});
|
|
360
|
+
});
|
|
361
|
+
ctx.setAction("pageUp", () => {
|
|
362
|
+
const { maxHeight: vh } = scrollStateRef.current;
|
|
363
|
+
const page = Math.max(1, vh || 1);
|
|
364
|
+
const newIndex = Math.max(0, selectedIndexRef.current - page);
|
|
365
|
+
selectedIndexRef.current = newIndex;
|
|
366
|
+
const list = displayItemsRef.current;
|
|
367
|
+
onSelectionChangeRef.current?.(newIndex, list[newIndex]);
|
|
368
|
+
setScrollOffset(newIndex);
|
|
369
|
+
forceUpdate({});
|
|
370
|
+
});
|
|
371
|
+
ctx.setAction("pageDown", () => {
|
|
372
|
+
const { maxHeight: vh, totalItems } = scrollStateRef.current;
|
|
373
|
+
const page = Math.max(1, vh || 1);
|
|
374
|
+
const maxIndex = Math.max(0, totalItems - 1);
|
|
375
|
+
const newIndex = Math.min(maxIndex, selectedIndexRef.current + page);
|
|
376
|
+
selectedIndexRef.current = newIndex;
|
|
377
|
+
const list = displayItemsRef.current;
|
|
378
|
+
onSelectionChangeRef.current?.(newIndex, list[newIndex]);
|
|
379
|
+
const maxScroll = Math.max(0, totalItems - page);
|
|
380
|
+
setScrollOffset(Math.min(maxScroll, Math.max(0, newIndex - page + 1)));
|
|
322
381
|
forceUpdate({});
|
|
323
382
|
});
|
|
383
|
+
const navBindings = [
|
|
384
|
+
{ key: "upArrow", caption: "navigate", action: "moveUp", order: 0 },
|
|
385
|
+
{ key: "downArrow", caption: "navigate", action: "moveDown", order: 0 },
|
|
386
|
+
...PAGE_SCROLL_KEY_BINDINGS
|
|
387
|
+
];
|
|
324
388
|
if (sortable) {
|
|
325
389
|
ctx.setAction("toggleSort", () => {
|
|
326
390
|
const nextSort = sortOrder === "none" ? "asc" : sortOrder === "asc" ? "desc" : "none";
|
|
@@ -367,8 +431,7 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
367
431
|
}
|
|
368
432
|
};
|
|
369
433
|
ctx.setKeyBinding([
|
|
370
|
-
|
|
371
|
-
{ key: "downArrow", caption: "navigate", action: "moveDown", order: 0 },
|
|
434
|
+
...navBindings,
|
|
372
435
|
{
|
|
373
436
|
key: "s",
|
|
374
437
|
caption: sortCaption,
|
|
@@ -378,47 +441,47 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
378
441
|
]);
|
|
379
442
|
ctx.update();
|
|
380
443
|
} else {
|
|
381
|
-
ctx.setKeyBinding(
|
|
382
|
-
{ key: "upArrow", caption: "navigate", action: "moveUp", order: 0 },
|
|
383
|
-
{ key: "downArrow", caption: "navigate", action: "moveDown", order: 0 }
|
|
384
|
-
]);
|
|
444
|
+
ctx.setKeyBinding(navBindings);
|
|
385
445
|
}
|
|
386
446
|
}, [sortOrder, sortable]);
|
|
387
447
|
const selectedIndex = selectedIndexRef.current;
|
|
448
|
+
const needsBar = displayItems.length > effectiveMaxHeight;
|
|
449
|
+
const barGlyphs = needsBar ? scrollbarGlyphs(effectiveMaxHeight, displayItems.length, clampedScrollOffset) : null;
|
|
450
|
+
const appendBar = (rowContent, displayIndex) => {
|
|
451
|
+
if (!barGlyphs) return rowContent;
|
|
452
|
+
const glyph = barGlyphs[displayIndex] ?? BAR_TRACK;
|
|
453
|
+
return h2(
|
|
454
|
+
Box2,
|
|
455
|
+
{ flexDirection: "row" },
|
|
456
|
+
rowContent,
|
|
457
|
+
h2(Text2, { color: glyph === BAR_THUMB ? "cyan" : "gray" }, glyph)
|
|
458
|
+
);
|
|
459
|
+
};
|
|
388
460
|
const defaultRenderItem = (item, isSelected, displayIndex, actualIndex) => {
|
|
389
461
|
const isFirstVisible = displayIndex === 0;
|
|
390
462
|
const isLastVisible = displayIndex === visibleItems.length - 1;
|
|
391
|
-
let arrowPrefix = "";
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
arrowPrefix = "\
|
|
395
|
-
} else if (isLastVisible && canScrollDown) {
|
|
396
|
-
arrowPrefix = "\u2193 ";
|
|
397
|
-
} else {
|
|
398
|
-
arrowPrefix = " ";
|
|
399
|
-
}
|
|
400
|
-
if (isSelected) {
|
|
401
|
-
selectionPrefix = selectionMarker;
|
|
402
|
-
} else {
|
|
403
|
-
selectionPrefix = " ".repeat(selectionMarker.length);
|
|
463
|
+
let arrowPrefix = " ";
|
|
464
|
+
if (!needsBar) {
|
|
465
|
+
if (isFirstVisible && canScrollUp) arrowPrefix = "\u2191 ";
|
|
466
|
+
else if (isLastVisible && canScrollDown) arrowPrefix = "\u2193 ";
|
|
404
467
|
}
|
|
468
|
+
const selectionPrefix = isSelected ? selectionMarker : " ".repeat(selectionMarker.length);
|
|
469
|
+
const label = clipNameForScrollbar(item.name, needsBar);
|
|
405
470
|
return h2(
|
|
406
471
|
Box2,
|
|
407
472
|
{ flexDirection: "row" },
|
|
408
|
-
|
|
409
|
-
h2(Text2, {
|
|
410
|
-
key: `arrow-${actualIndex}`,
|
|
411
|
-
color: "white"
|
|
412
|
-
}, arrowPrefix),
|
|
413
|
-
// Selection marker space (always same width, not highlighted)
|
|
473
|
+
h2(Text2, { key: `arrow-${actualIndex}`, color: "white" }, arrowPrefix),
|
|
414
474
|
h2(Text2, { key: `marker-${actualIndex}`, color: "white" }, selectionPrefix),
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
475
|
+
h2(
|
|
476
|
+
Text2,
|
|
477
|
+
{
|
|
478
|
+
key: `name-${actualIndex}`,
|
|
479
|
+
color: isSelected ? "black" : "white",
|
|
480
|
+
backgroundColor: isSelected ? "cyan" : void 0,
|
|
481
|
+
bold: isSelected
|
|
482
|
+
},
|
|
483
|
+
label
|
|
484
|
+
)
|
|
422
485
|
);
|
|
423
486
|
};
|
|
424
487
|
const itemRenderer = renderItem || defaultRenderItem;
|
|
@@ -431,42 +494,32 @@ function ListComponent({ items, ctx, selectedIndexRef, renderItem, getTitle, sor
|
|
|
431
494
|
if (renderItem) {
|
|
432
495
|
const isFirstVisible = displayIndex === 0;
|
|
433
496
|
const isLastVisible = displayIndex === visibleItems.length - 1;
|
|
434
|
-
let arrowPrefix = "";
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
arrowPrefix = "\
|
|
438
|
-
} else if (isLastVisible && canScrollDown) {
|
|
439
|
-
arrowPrefix = "\u2193 ";
|
|
440
|
-
} else {
|
|
441
|
-
arrowPrefix = " ";
|
|
442
|
-
}
|
|
443
|
-
if (isSelected) {
|
|
444
|
-
selectionPrefix = selectionMarker;
|
|
445
|
-
} else {
|
|
446
|
-
selectionPrefix = " ".repeat(selectionMarker.length);
|
|
497
|
+
let arrowPrefix = " ";
|
|
498
|
+
if (!needsBar) {
|
|
499
|
+
if (isFirstVisible && canScrollUp) arrowPrefix = "\u2191 ";
|
|
500
|
+
else if (isLastVisible && canScrollDown) arrowPrefix = "\u2193 ";
|
|
447
501
|
}
|
|
502
|
+
const selectionPrefix = isSelected ? selectionMarker : " ".repeat(selectionMarker.length);
|
|
503
|
+
const clipped = needsBar ? { ...item, name: clipNameForScrollbar(item.name, true) } : item;
|
|
504
|
+
const row = h2(
|
|
505
|
+
Box2,
|
|
506
|
+
{ flexDirection: "row" },
|
|
507
|
+
h2(Text2, { key: `arrow-${actualIndex}`, color: "white" }, arrowPrefix),
|
|
508
|
+
h2(Text2, { key: `marker-${actualIndex}`, color: "white" }, selectionPrefix),
|
|
509
|
+
renderItem(clipped, isSelected, displayIndex)
|
|
510
|
+
);
|
|
448
511
|
return h2(ScreenRow, {
|
|
449
512
|
key: `item-${actualIndex}`,
|
|
450
|
-
children:
|
|
451
|
-
Box2,
|
|
452
|
-
{ flexDirection: "row" },
|
|
453
|
-
// Arrow (clickable if functional, not highlighted)
|
|
454
|
-
h2(Text2, {
|
|
455
|
-
key: `arrow-${actualIndex}`,
|
|
456
|
-
color: "white"
|
|
457
|
-
}, arrowPrefix),
|
|
458
|
-
// Selection marker space (always same width, not highlighted)
|
|
459
|
-
h2(Text2, { key: `marker-${actualIndex}`, color: "white" }, selectionPrefix),
|
|
460
|
-
// Custom rendered content
|
|
461
|
-
renderItem(item, isSelected, displayIndex)
|
|
462
|
-
)
|
|
463
|
-
});
|
|
464
|
-
} else {
|
|
465
|
-
return h2(ScreenRow, {
|
|
466
|
-
key: `item-${actualIndex}`,
|
|
467
|
-
children: itemRenderer(item, isSelected, displayIndex, actualIndex)
|
|
513
|
+
children: appendBar(row, displayIndex)
|
|
468
514
|
});
|
|
469
515
|
}
|
|
516
|
+
return h2(ScreenRow, {
|
|
517
|
+
key: `item-${actualIndex}`,
|
|
518
|
+
children: appendBar(
|
|
519
|
+
itemRenderer(item, isSelected, displayIndex, actualIndex),
|
|
520
|
+
displayIndex
|
|
521
|
+
)
|
|
522
|
+
});
|
|
470
523
|
})
|
|
471
524
|
);
|
|
472
525
|
}
|
|
@@ -474,6 +527,7 @@ var h2;
|
|
|
474
527
|
var init_list_components = __esm({
|
|
475
528
|
"src/screen/list-components.js"() {
|
|
476
529
|
init_components();
|
|
530
|
+
init_scrollbar();
|
|
477
531
|
h2 = createElement;
|
|
478
532
|
}
|
|
479
533
|
});
|
|
@@ -968,21 +1022,6 @@ function wrapTextLines(text, cols) {
|
|
|
968
1022
|
}
|
|
969
1023
|
return out;
|
|
970
1024
|
}
|
|
971
|
-
function scrollbarGlyphs(viewportRows, totalLines, scrollTop) {
|
|
972
|
-
const view = Math.max(1, Math.floor(viewportRows));
|
|
973
|
-
const total = Math.max(0, Math.floor(totalLines));
|
|
974
|
-
if (total <= view) return null;
|
|
975
|
-
const maxScroll = total - view;
|
|
976
|
-
const thumbSize = Math.max(1, Math.round(view / total * view));
|
|
977
|
-
const travel = Math.max(0, view - thumbSize);
|
|
978
|
-
const s = Math.min(Math.max(0, Math.floor(scrollTop)), maxScroll);
|
|
979
|
-
const thumbStart = maxScroll === 0 ? 0 : Math.round(s / maxScroll * travel);
|
|
980
|
-
const glyphs = [];
|
|
981
|
-
for (let i = 0; i < view; i++) {
|
|
982
|
-
glyphs.push(i >= thumbStart && i < thumbStart + thumbSize ? BAR_THUMB : BAR_TRACK);
|
|
983
|
-
}
|
|
984
|
-
return glyphs;
|
|
985
|
-
}
|
|
986
1025
|
function padEndVisible(s, w) {
|
|
987
1026
|
const t = String(s ?? "");
|
|
988
1027
|
if (t.length >= w) return t.slice(0, w);
|
|
@@ -1083,22 +1122,17 @@ function ScrollableText({
|
|
|
1083
1122
|
...rowNodes
|
|
1084
1123
|
);
|
|
1085
1124
|
}
|
|
1086
|
-
var h5,
|
|
1125
|
+
var h5, SCROLL_KEYS;
|
|
1087
1126
|
var init_scrollable_text = __esm({
|
|
1088
1127
|
"src/screen/scrollable-text.js"() {
|
|
1089
1128
|
init_components();
|
|
1129
|
+
init_scrollbar();
|
|
1130
|
+
init_scrollbar();
|
|
1090
1131
|
h5 = createElement2;
|
|
1091
|
-
BAR_THUMB = "#";
|
|
1092
|
-
BAR_TRACK = "|";
|
|
1093
1132
|
SCROLL_KEYS = [
|
|
1094
1133
|
{ key: "upArrow", caption: "scroll", action: "scrollUp", order: 0 },
|
|
1095
1134
|
{ key: "downArrow", caption: "scroll", action: "scrollDown", order: 0 },
|
|
1096
|
-
|
|
1097
|
-
{ key: "downArrow", meta: true, caption: "page", action: "pageDown", order: 0 },
|
|
1098
|
-
{ key: "upArrow", ctrl: true, caption: "page", action: "pageUp", order: 0 },
|
|
1099
|
-
{ key: "downArrow", ctrl: true, caption: "page", action: "pageDown", order: 0 },
|
|
1100
|
-
{ key: "pageUp", caption: "page", action: "pageUp", order: 0 },
|
|
1101
|
-
{ key: "pageDown", caption: "page", action: "pageDown", order: 0 }
|
|
1135
|
+
...PAGE_SCROLL_KEY_BINDINGS
|
|
1102
1136
|
];
|
|
1103
1137
|
}
|
|
1104
1138
|
});
|
|
@@ -1234,6 +1268,8 @@ var init_footer_builder = __esm({
|
|
|
1234
1268
|
// src/screen/index.js
|
|
1235
1269
|
var screen_exports = {};
|
|
1236
1270
|
__export(screen_exports, {
|
|
1271
|
+
BAR_THUMB: () => BAR_THUMB,
|
|
1272
|
+
BAR_TRACK: () => BAR_TRACK,
|
|
1237
1273
|
Box: () => Box5,
|
|
1238
1274
|
Divider: () => Divider,
|
|
1239
1275
|
FooterPresets: () => FooterPresets,
|
|
@@ -1243,6 +1279,7 @@ __export(screen_exports, {
|
|
|
1243
1279
|
ListItem: () => ListItem,
|
|
1244
1280
|
MultiColumnListComponent: () => MultiColumnListComponent,
|
|
1245
1281
|
MultiColumnListWithPreviewComponent: () => MultiColumnListWithPreviewComponent,
|
|
1282
|
+
PAGE_SCROLL_KEY_BINDINGS: () => PAGE_SCROLL_KEY_BINDINGS,
|
|
1246
1283
|
React: () => React2,
|
|
1247
1284
|
ScreenBody: () => ScreenBody,
|
|
1248
1285
|
ScreenContainer: () => ScreenContainer,
|
|
@@ -1298,6 +1335,7 @@ var init_screen = __esm({
|
|
|
1298
1335
|
init_components();
|
|
1299
1336
|
init_ui_elements();
|
|
1300
1337
|
init_scrollable_text();
|
|
1338
|
+
init_scrollbar();
|
|
1301
1339
|
init_key_bindings();
|
|
1302
1340
|
init_utils();
|
|
1303
1341
|
init_footer_builder();
|
|
@@ -4150,12 +4188,13 @@ function tasksSchemaSpec(queueName = "tasks") {
|
|
|
4150
4188
|
}
|
|
4151
4189
|
};
|
|
4152
4190
|
}
|
|
4153
|
-
function taskHistoryInsertFromQueueRow(row, overrides) {
|
|
4191
|
+
function taskHistoryInsertFromQueueRow(row, overrides = {}) {
|
|
4154
4192
|
const { id, ...snapshot } = row;
|
|
4155
|
-
void id;
|
|
4193
|
+
const opid = overrides.opid !== void 0 ? overrides.opid : snapshot.opid != null && String(snapshot.opid).trim() !== "" ? snapshot.opid : id;
|
|
4156
4194
|
return {
|
|
4157
4195
|
...snapshot,
|
|
4158
|
-
...overrides
|
|
4196
|
+
...overrides,
|
|
4197
|
+
opid
|
|
4159
4198
|
};
|
|
4160
4199
|
}
|
|
4161
4200
|
async function ensureTaskTables(context, options = {}) {
|
|
@@ -6455,69 +6494,6 @@ var TaskStopRunner = class extends AbstractTask {
|
|
|
6455
6494
|
}
|
|
6456
6495
|
};
|
|
6457
6496
|
|
|
6458
|
-
// src/tasks/coreTasks/TaskGetLogs.js
|
|
6459
|
-
var TaskGetLogs = class extends AbstractTask {
|
|
6460
|
-
/**
|
|
6461
|
-
* @param {object} context
|
|
6462
|
-
* @param {Record<string, unknown>} [overrides]
|
|
6463
|
-
* @returns {Promise<{ source: string, resource: string, tail: number, afterTs?: string }>}
|
|
6464
|
-
*/
|
|
6465
|
-
static async resolveCustomParams(context, overrides = {}) {
|
|
6466
|
-
const merged = AbstractTask._mergeTypedParams(context, "task-get-logs", {
|
|
6467
|
-
source: "string",
|
|
6468
|
-
resource: "string",
|
|
6469
|
-
tail: "number default 100",
|
|
6470
|
-
afterTs: "string"
|
|
6471
|
-
}, overrides);
|
|
6472
|
-
const source = typeof merged.source === "string" ? merged.source.trim() : "";
|
|
6473
|
-
const resource = typeof merged.resource === "string" ? merged.resource.trim() : "";
|
|
6474
|
-
if (!source) throw new ParamError('getLogs: param "source" is required');
|
|
6475
|
-
if (!resource) throw new ParamError('getLogs: param "resource" is required');
|
|
6476
|
-
let tail = Number(merged.tail);
|
|
6477
|
-
if (!Number.isFinite(tail) || tail < 1) tail = 100;
|
|
6478
|
-
tail = Math.min(1e4, Math.max(1, Math.floor(tail)));
|
|
6479
|
-
const out = { source, resource, tail };
|
|
6480
|
-
if (typeof merged.afterTs === "string" && merged.afterTs.trim()) {
|
|
6481
|
-
out.afterTs = merged.afterTs.trim();
|
|
6482
|
-
}
|
|
6483
|
-
return out;
|
|
6484
|
-
}
|
|
6485
|
-
/**
|
|
6486
|
-
* @param {unknown} _reportProgress Unused (single-shot read, no progress events).
|
|
6487
|
-
* @returns {Promise<{ success: boolean, results: unknown }>}
|
|
6488
|
-
*/
|
|
6489
|
-
async run(_reportProgress) {
|
|
6490
|
-
const p = this.task.params ?? {};
|
|
6491
|
-
const source = String(p.source ?? "").trim();
|
|
6492
|
-
const resource = String(p.resource ?? "").trim();
|
|
6493
|
-
const tail = Math.max(1, Math.min(1e4, Number(p.tail) > 0 ? Number(p.tail) : 100));
|
|
6494
|
-
const afterTs = p.afterTs != null && String(p.afterTs).trim() ? String(p.afterTs).trim() : null;
|
|
6495
|
-
if (!source || !resource) {
|
|
6496
|
-
return {
|
|
6497
|
-
success: false,
|
|
6498
|
-
results: { error: 'getLogs requires params "source" and "resource"' }
|
|
6499
|
-
};
|
|
6500
|
-
}
|
|
6501
|
-
try {
|
|
6502
|
-
const { records, latestTs } = await readTaskIpcLogsSnapshot(this.context, {
|
|
6503
|
-
source,
|
|
6504
|
-
resource,
|
|
6505
|
-
tail,
|
|
6506
|
-
afterTs
|
|
6507
|
-
});
|
|
6508
|
-
return {
|
|
6509
|
-
success: true,
|
|
6510
|
-
results: { records, latestTs, source, resource }
|
|
6511
|
-
};
|
|
6512
|
-
} catch (e) {
|
|
6513
|
-
return {
|
|
6514
|
-
success: false,
|
|
6515
|
-
results: { error: e?.message ?? String(e) }
|
|
6516
|
-
};
|
|
6517
|
-
}
|
|
6518
|
-
}
|
|
6519
|
-
};
|
|
6520
|
-
|
|
6521
6497
|
// src/tasks/runtimeParams.js
|
|
6522
6498
|
var LOOP_RUNTIME_KEYS = ["maxParallel", "pollMs", "claimJitterMs", "scanLimit"];
|
|
6523
6499
|
var LOGGER_RUNTIME_KEYS = [
|
|
@@ -6531,7 +6507,16 @@ var LOGGER_RUNTIME_KEYS = [
|
|
|
6531
6507
|
"progressWithTimes",
|
|
6532
6508
|
"progressThrottleMs"
|
|
6533
6509
|
];
|
|
6534
|
-
var CONTROL_LANE_TASK_NAMES = [
|
|
6510
|
+
var CONTROL_LANE_TASK_NAMES = [
|
|
6511
|
+
"stopRunner",
|
|
6512
|
+
"stop",
|
|
6513
|
+
"pauseRunner",
|
|
6514
|
+
"pause",
|
|
6515
|
+
"unpauseRunner",
|
|
6516
|
+
"unpause",
|
|
6517
|
+
"setRuntimeParam",
|
|
6518
|
+
"setRunnerParam"
|
|
6519
|
+
];
|
|
6535
6520
|
function controlLaneTaskNames(extra) {
|
|
6536
6521
|
const names = [...CONTROL_LANE_TASK_NAMES];
|
|
6537
6522
|
if (extra == null || extra === "") return names;
|
|
@@ -6594,6 +6579,7 @@ function ensureTasksRuntime(context, seed = {}) {
|
|
|
6594
6579
|
if (rt.pollMs === void 0) rt.pollMs = seed.pollMs ?? 1e3;
|
|
6595
6580
|
if (rt.claimJitterMs === void 0) rt.claimJitterMs = seed.claimJitterMs ?? 0;
|
|
6596
6581
|
if (rt.scanLimit === void 0) rt.scanLimit = seed.scanLimit ?? 100;
|
|
6582
|
+
if (rt.paused === void 0) rt.paused = seed.paused === true;
|
|
6597
6583
|
return rt;
|
|
6598
6584
|
}
|
|
6599
6585
|
async function applyRuntimeParam(context, key, value) {
|
|
@@ -6658,6 +6644,140 @@ function readLoopRuntime(context) {
|
|
|
6658
6644
|
};
|
|
6659
6645
|
}
|
|
6660
6646
|
|
|
6647
|
+
// src/tasks/coreTasks/TaskPauseRunner.js
|
|
6648
|
+
async function applyRunnerPaused(context, paused) {
|
|
6649
|
+
const runtime = ensureTasksRuntime(context);
|
|
6650
|
+
const was = runtime.paused === true;
|
|
6651
|
+
runtime.paused = paused === true;
|
|
6652
|
+
const registry = context.servicesRegistry;
|
|
6653
|
+
if (registry && typeof registry === "object") {
|
|
6654
|
+
await updateServicesRegistryMetadata(context, registry, {
|
|
6655
|
+
paused: runtime.paused,
|
|
6656
|
+
pausedAt: runtime.paused ? (/* @__PURE__ */ new Date()).toISOString() : null
|
|
6657
|
+
});
|
|
6658
|
+
}
|
|
6659
|
+
const message = runtime.paused ? was ? "Runner already paused (no new worker tasks)." : "Runner paused: finishing in-flight work; no new worker tasks until unpause." : was ? "Runner unpaused: claiming worker tasks again." : "Runner already running (not paused).";
|
|
6660
|
+
context.logger?.warn?.(
|
|
6661
|
+
runtime.paused ? `[TaskPauseRunner] ${message}` : `[TaskUnpauseRunner] ${message}`
|
|
6662
|
+
);
|
|
6663
|
+
return {
|
|
6664
|
+
success: true,
|
|
6665
|
+
results: {
|
|
6666
|
+
paused: runtime.paused,
|
|
6667
|
+
message
|
|
6668
|
+
}
|
|
6669
|
+
};
|
|
6670
|
+
}
|
|
6671
|
+
var TaskPauseRunner = class extends AbstractTask {
|
|
6672
|
+
static taskName = "pauseRunner";
|
|
6673
|
+
static description = "Pause a runner: finish in-flight tasks, claim no new worker tasks until unpaused";
|
|
6674
|
+
static aliases = ["pause"];
|
|
6675
|
+
static defaultWaitForResult = true;
|
|
6676
|
+
/**
|
|
6677
|
+
* @param {object} context
|
|
6678
|
+
* @param {Record<string, unknown>} [overrides]
|
|
6679
|
+
* @returns {Promise<object>}
|
|
6680
|
+
*/
|
|
6681
|
+
static async resolveParams(context, overrides = {}) {
|
|
6682
|
+
const main = await super.resolveParams(context, overrides);
|
|
6683
|
+
if (!main.serviceName) {
|
|
6684
|
+
throw new ParamError(
|
|
6685
|
+
"pause/pauseRunner requires --serviceName (registry instance name; optional --serviceGroup, --instanceNumber, --serverName to narrow targeting)"
|
|
6686
|
+
);
|
|
6687
|
+
}
|
|
6688
|
+
return main;
|
|
6689
|
+
}
|
|
6690
|
+
async run() {
|
|
6691
|
+
return applyRunnerPaused(this.context, true);
|
|
6692
|
+
}
|
|
6693
|
+
};
|
|
6694
|
+
var TaskUnpauseRunner = class extends AbstractTask {
|
|
6695
|
+
static taskName = "unpauseRunner";
|
|
6696
|
+
static description = "Unpause a runner: resume claiming worker tasks";
|
|
6697
|
+
static aliases = ["unpause"];
|
|
6698
|
+
static defaultWaitForResult = true;
|
|
6699
|
+
/**
|
|
6700
|
+
* @param {object} context
|
|
6701
|
+
* @param {Record<string, unknown>} [overrides]
|
|
6702
|
+
* @returns {Promise<object>}
|
|
6703
|
+
*/
|
|
6704
|
+
static async resolveParams(context, overrides = {}) {
|
|
6705
|
+
const main = await super.resolveParams(context, overrides);
|
|
6706
|
+
if (!main.serviceName) {
|
|
6707
|
+
throw new ParamError(
|
|
6708
|
+
"unpause/unpauseRunner requires --serviceName (registry instance name; optional --serviceGroup, --instanceNumber, --serverName to narrow targeting)"
|
|
6709
|
+
);
|
|
6710
|
+
}
|
|
6711
|
+
return main;
|
|
6712
|
+
}
|
|
6713
|
+
async run() {
|
|
6714
|
+
return applyRunnerPaused(this.context, false);
|
|
6715
|
+
}
|
|
6716
|
+
};
|
|
6717
|
+
|
|
6718
|
+
// src/tasks/coreTasks/TaskGetLogs.js
|
|
6719
|
+
var TaskGetLogs = class extends AbstractTask {
|
|
6720
|
+
/**
|
|
6721
|
+
* @param {object} context
|
|
6722
|
+
* @param {Record<string, unknown>} [overrides]
|
|
6723
|
+
* @returns {Promise<{ source: string, resource: string, tail: number, afterTs?: string }>}
|
|
6724
|
+
*/
|
|
6725
|
+
static async resolveCustomParams(context, overrides = {}) {
|
|
6726
|
+
const merged = AbstractTask._mergeTypedParams(context, "task-get-logs", {
|
|
6727
|
+
source: "string",
|
|
6728
|
+
resource: "string",
|
|
6729
|
+
tail: "number default 100",
|
|
6730
|
+
afterTs: "string"
|
|
6731
|
+
}, overrides);
|
|
6732
|
+
const source = typeof merged.source === "string" ? merged.source.trim() : "";
|
|
6733
|
+
const resource = typeof merged.resource === "string" ? merged.resource.trim() : "";
|
|
6734
|
+
if (!source) throw new ParamError('getLogs: param "source" is required');
|
|
6735
|
+
if (!resource) throw new ParamError('getLogs: param "resource" is required');
|
|
6736
|
+
let tail = Number(merged.tail);
|
|
6737
|
+
if (!Number.isFinite(tail) || tail < 1) tail = 100;
|
|
6738
|
+
tail = Math.min(1e4, Math.max(1, Math.floor(tail)));
|
|
6739
|
+
const out = { source, resource, tail };
|
|
6740
|
+
if (typeof merged.afterTs === "string" && merged.afterTs.trim()) {
|
|
6741
|
+
out.afterTs = merged.afterTs.trim();
|
|
6742
|
+
}
|
|
6743
|
+
return out;
|
|
6744
|
+
}
|
|
6745
|
+
/**
|
|
6746
|
+
* @param {unknown} _reportProgress Unused (single-shot read, no progress events).
|
|
6747
|
+
* @returns {Promise<{ success: boolean, results: unknown }>}
|
|
6748
|
+
*/
|
|
6749
|
+
async run(_reportProgress) {
|
|
6750
|
+
const p = this.task.params ?? {};
|
|
6751
|
+
const source = String(p.source ?? "").trim();
|
|
6752
|
+
const resource = String(p.resource ?? "").trim();
|
|
6753
|
+
const tail = Math.max(1, Math.min(1e4, Number(p.tail) > 0 ? Number(p.tail) : 100));
|
|
6754
|
+
const afterTs = p.afterTs != null && String(p.afterTs).trim() ? String(p.afterTs).trim() : null;
|
|
6755
|
+
if (!source || !resource) {
|
|
6756
|
+
return {
|
|
6757
|
+
success: false,
|
|
6758
|
+
results: { error: 'getLogs requires params "source" and "resource"' }
|
|
6759
|
+
};
|
|
6760
|
+
}
|
|
6761
|
+
try {
|
|
6762
|
+
const { records, latestTs } = await readTaskIpcLogsSnapshot(this.context, {
|
|
6763
|
+
source,
|
|
6764
|
+
resource,
|
|
6765
|
+
tail,
|
|
6766
|
+
afterTs
|
|
6767
|
+
});
|
|
6768
|
+
return {
|
|
6769
|
+
success: true,
|
|
6770
|
+
results: { records, latestTs, source, resource }
|
|
6771
|
+
};
|
|
6772
|
+
} catch (e) {
|
|
6773
|
+
return {
|
|
6774
|
+
success: false,
|
|
6775
|
+
results: { error: e?.message ?? String(e) }
|
|
6776
|
+
};
|
|
6777
|
+
}
|
|
6778
|
+
}
|
|
6779
|
+
};
|
|
6780
|
+
|
|
6661
6781
|
// src/tasks/coreTasks/TaskSetRuntimeParam.js
|
|
6662
6782
|
var TaskSetRuntimeParam = class extends AbstractTask {
|
|
6663
6783
|
static defaultWaitForResult = true;
|
|
@@ -6813,7 +6933,7 @@ var TasksRegistry = class _TasksRegistry {
|
|
|
6813
6933
|
* @returns {TasksRegistry}
|
|
6814
6934
|
*/
|
|
6815
6935
|
static withCoreTasks() {
|
|
6816
|
-
return new _TasksRegistry().add("ping", TaskPing).add("sampleProcess", TaskSampleProcess).add("shellCommand", TaskShellCommand).add("systemInfo", TaskSystemInfo).add("info", TaskSystemInfo).add("taskSumAB", TaskSumAB).add("stopRunner", TaskStopRunner).add("stop", TaskStopRunner).add("getLogs", TaskGetLogs).add("setRuntimeParam", TaskSetRuntimeParam).add("setRunnerParam", TaskSetRuntimeParam);
|
|
6936
|
+
return new _TasksRegistry().add("ping", TaskPing).add("sampleProcess", TaskSampleProcess).add("shellCommand", TaskShellCommand).add("systemInfo", TaskSystemInfo).add("info", TaskSystemInfo).add("taskSumAB", TaskSumAB).add("stopRunner", TaskStopRunner).add("stop", TaskStopRunner).add("pauseRunner", TaskPauseRunner).add("pause", TaskPauseRunner).add("unpauseRunner", TaskUnpauseRunner).add("unpause", TaskUnpauseRunner).add("getLogs", TaskGetLogs).add("setRuntimeParam", TaskSetRuntimeParam).add("setRunnerParam", TaskSetRuntimeParam);
|
|
6817
6937
|
}
|
|
6818
6938
|
/**
|
|
6819
6939
|
* Register a single task class under a name. Overwrites any previous entry.
|
|
@@ -7175,6 +7295,7 @@ async function runTasksLoop(context, options) {
|
|
|
7175
7295
|
const defaultMeta = {
|
|
7176
7296
|
component: "tasks-runner",
|
|
7177
7297
|
allowedTasks: allowedTasks?.length ? allowedTasks.join(",") : "all",
|
|
7298
|
+
paused: false,
|
|
7178
7299
|
runtime: {
|
|
7179
7300
|
maxParallel: loop0.maxParallel,
|
|
7180
7301
|
pollMs: loop0.pollMs,
|
|
@@ -7241,28 +7362,38 @@ async function runTasksLoop(context, options) {
|
|
|
7241
7362
|
if (claimJitterMs > 0) {
|
|
7242
7363
|
await sleepMs(Math.floor(Math.random() * (claimJitterMs + 1)));
|
|
7243
7364
|
}
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
if (
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7365
|
+
const paused = context.tasksRuntime?.paused === true;
|
|
7366
|
+
if (!paused) {
|
|
7367
|
+
while (runningPromises.size < maxParallel) {
|
|
7368
|
+
const claimed = await claimNextRunnableTask(
|
|
7369
|
+
context,
|
|
7370
|
+
tasksTable,
|
|
7371
|
+
target,
|
|
7372
|
+
registry,
|
|
7373
|
+
scanLimit,
|
|
7374
|
+
allowedTasks,
|
|
7375
|
+
runnerIdentity
|
|
7376
|
+
);
|
|
7377
|
+
if (!claimed) break;
|
|
7378
|
+
const p = executeClaimedTask(
|
|
7379
|
+
context,
|
|
7380
|
+
tasksTable,
|
|
7381
|
+
historyTable,
|
|
7382
|
+
claimed,
|
|
7383
|
+
registry,
|
|
7384
|
+
runningTaskInstances
|
|
7385
|
+
).then(async (outcome) => {
|
|
7386
|
+
if (outcome.stopRunnerRequested && !stopRequested) {
|
|
7387
|
+
stopRequested = true;
|
|
7388
|
+
stopAllowanceMs = outcome.stopAllowanceMs || stopAllowanceMs;
|
|
7389
|
+
context.tasksRunnerStop = true;
|
|
7390
|
+
await signalRunningTasksStop(context, runningTaskInstances, stopAllowanceMs);
|
|
7391
|
+
}
|
|
7392
|
+
}).finally(() => {
|
|
7393
|
+
runningPromises.delete(p);
|
|
7394
|
+
});
|
|
7395
|
+
runningPromises.add(p);
|
|
7396
|
+
}
|
|
7266
7397
|
}
|
|
7267
7398
|
const wakePromises = [...runningPromises];
|
|
7268
7399
|
if (runningControlPromise) {
|