@skrr-ai/cli 0.1.105 → 0.1.106
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.
|
@@ -124,6 +124,13 @@ export declare const LIVE_LOG_RESOLUTION_RUNTIME_VERSION = "0.8.119";
|
|
|
124
124
|
* that file and its rotated siblings itself.
|
|
125
125
|
*/
|
|
126
126
|
export declare const ROTATED_LOGS_RUNTIME_VERSION = "0.8.120";
|
|
127
|
+
/**
|
|
128
|
+
* The first runtime whose `logs --rotated --lines N` says where a window that
|
|
129
|
+
* cut older lines starts, and whose `logs --path` names the rotated siblings
|
|
130
|
+
* on stderr (OSK-16228). 0.8.120 knows `--rotated` but says neither, so for it
|
|
131
|
+
* the CLI reads the files itself, exactly as it does for an older runtime.
|
|
132
|
+
*/
|
|
133
|
+
export declare const ROTATED_WINDOW_NOTE_RUNTIME_VERSION = "0.8.121";
|
|
127
134
|
/**
|
|
128
135
|
* Rotated siblings of a log, OLDEST FIRST (OSK-16214). The daemon's logger
|
|
129
136
|
* renames `daemon.app.log` to `daemon.app.1.log`, `.1` to `.2` and so on at
|
|
@@ -146,6 +153,31 @@ export declare function readLastLines(filePath: string, maxLines: number): strin
|
|
|
146
153
|
* file. A file renamed away between the listing and the read is skipped.
|
|
147
154
|
*/
|
|
148
155
|
export declare function readLastLinesAcross(files: readonly string[], maxLines: number): string[];
|
|
156
|
+
/**
|
|
157
|
+
* Where a `--rotated --lines N` window began when it left older lines out
|
|
158
|
+
* (OSK-16228). `startLine` is 1-based within `file`; `totalLines` counts the
|
|
159
|
+
* whole set. A copy of `daemon/src/rotated-log-files.ts`, like the helpers above.
|
|
160
|
+
*/
|
|
161
|
+
export interface LogWindowCut {
|
|
162
|
+
file: string;
|
|
163
|
+
startLine: number;
|
|
164
|
+
totalLines: number;
|
|
165
|
+
}
|
|
166
|
+
/** Lines in a file, split as `readLastLines` splits them; read in chunks. */
|
|
167
|
+
export declare function countLines(filePath: string): number;
|
|
168
|
+
/**
|
|
169
|
+
* `readLastLinesAcross`, plus where the window began when it cut older lines.
|
|
170
|
+
* Without it, `--rotated --lines 20000 | grep <id>` for an id 90k lines back
|
|
171
|
+
* printed nothing and said nothing, which reads as "never logged". Lines are
|
|
172
|
+
* counted only once the window is full, and only from the file it stopped in
|
|
173
|
+
* back.
|
|
174
|
+
*/
|
|
175
|
+
export declare function readLogWindow(files: readonly string[], maxLines: number): {
|
|
176
|
+
lines: string[];
|
|
177
|
+
cut: LogWindowCut | null;
|
|
178
|
+
};
|
|
179
|
+
/** The stderr sentence for a window that left older lines out. */
|
|
180
|
+
export declare function describeLogWindowCut(cut: LogWindowCut, shown: number): string;
|
|
149
181
|
/** Every byte of `files`, in order, to `out` — streamed, honouring back-pressure. */
|
|
150
182
|
export declare function streamLogFiles(files: readonly string[], out: NodeJS.WritableStream): Promise<void>;
|
|
151
183
|
/** `x.y.z` from a version string, or null. A prerelease suffix is ignored. */
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.STDERR_FLAG_DESCRIPTION = exports.ROTATED_LOGS_RUNTIME_VERSION = exports.LIVE_LOG_RESOLUTION_RUNTIME_VERSION = void 0;
|
|
6
|
+
exports.STDERR_FLAG_DESCRIPTION = exports.ROTATED_WINDOW_NOTE_RUNTIME_VERSION = exports.ROTATED_LOGS_RUNTIME_VERSION = exports.LIVE_LOG_RESOLUTION_RUNTIME_VERSION = void 0;
|
|
7
7
|
exports.describeLogAge = describeLogAge;
|
|
8
8
|
exports.resolveLegacyDaemonLogPath = resolveLegacyDaemonLogPath;
|
|
9
9
|
exports.resolveDaemonLogsProfile = resolveDaemonLogsProfile;
|
|
@@ -15,6 +15,9 @@ exports.rotatedLogSiblings = rotatedLogSiblings;
|
|
|
15
15
|
exports.describeRotatedSiblings = describeRotatedSiblings;
|
|
16
16
|
exports.readLastLines = readLastLines;
|
|
17
17
|
exports.readLastLinesAcross = readLastLinesAcross;
|
|
18
|
+
exports.countLines = countLines;
|
|
19
|
+
exports.readLogWindow = readLogWindow;
|
|
20
|
+
exports.describeLogWindowCut = describeLogWindowCut;
|
|
18
21
|
exports.streamLogFiles = streamLogFiles;
|
|
19
22
|
exports.parseRuntimeVersion = parseRuntimeVersion;
|
|
20
23
|
exports.runtimeVersionAtLeast = runtimeVersionAtLeast;
|
|
@@ -228,6 +231,13 @@ exports.LIVE_LOG_RESOLUTION_RUNTIME_VERSION = '0.8.119';
|
|
|
228
231
|
* that file and its rotated siblings itself.
|
|
229
232
|
*/
|
|
230
233
|
exports.ROTATED_LOGS_RUNTIME_VERSION = '0.8.120';
|
|
234
|
+
/**
|
|
235
|
+
* The first runtime whose `logs --rotated --lines N` says where a window that
|
|
236
|
+
* cut older lines starts, and whose `logs --path` names the rotated siblings
|
|
237
|
+
* on stderr (OSK-16228). 0.8.120 knows `--rotated` but says neither, so for it
|
|
238
|
+
* the CLI reads the files itself, exactly as it does for an older runtime.
|
|
239
|
+
*/
|
|
240
|
+
exports.ROTATED_WINDOW_NOTE_RUNTIME_VERSION = '0.8.121';
|
|
231
241
|
/**
|
|
232
242
|
* Rotated siblings of a log, OLDEST FIRST (OSK-16214). The daemon's logger
|
|
233
243
|
* renames `daemon.app.log` to `daemon.app.1.log`, `.1` to `.2` and so on at
|
|
@@ -304,19 +314,90 @@ function readLastLines(filePath, maxLines) {
|
|
|
304
314
|
* file. A file renamed away between the listing and the read is skipped.
|
|
305
315
|
*/
|
|
306
316
|
function readLastLinesAcross(files, maxLines) {
|
|
317
|
+
return readLogWindow(files, maxLines).lines;
|
|
318
|
+
}
|
|
319
|
+
/** Lines in a file, split as `readLastLines` splits them; read in chunks. */
|
|
320
|
+
function countLines(filePath) {
|
|
321
|
+
const descriptor = (0, node_fs_1.openSync)(filePath, 'r');
|
|
322
|
+
try {
|
|
323
|
+
const buffer = Buffer.alloc(64 * 1024);
|
|
324
|
+
let count = 0;
|
|
325
|
+
let last = -1;
|
|
326
|
+
let position = 0;
|
|
327
|
+
for (;;) {
|
|
328
|
+
const read = (0, node_fs_1.readSync)(descriptor, buffer, 0, buffer.length, position);
|
|
329
|
+
if (read === 0)
|
|
330
|
+
break;
|
|
331
|
+
position += read;
|
|
332
|
+
for (let i = 0; i < read; i += 1)
|
|
333
|
+
if (buffer[i] === 0x0a)
|
|
334
|
+
count += 1;
|
|
335
|
+
last = buffer[read - 1];
|
|
336
|
+
}
|
|
337
|
+
return last === -1 || last === 0x0a ? count : count + 1;
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
(0, node_fs_1.closeSync)(descriptor);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* `readLastLinesAcross`, plus where the window began when it cut older lines.
|
|
345
|
+
* Without it, `--rotated --lines 20000 | grep <id>` for an id 90k lines back
|
|
346
|
+
* printed nothing and said nothing, which reads as "never logged". Lines are
|
|
347
|
+
* counted only once the window is full, and only from the file it stopped in
|
|
348
|
+
* back.
|
|
349
|
+
*/
|
|
350
|
+
function readLogWindow(files, maxLines) {
|
|
307
351
|
const collected = [];
|
|
308
352
|
let remaining = maxLines;
|
|
353
|
+
let boundary = null;
|
|
309
354
|
for (let i = files.length - 1; i >= 0 && remaining > 0; i -= 1) {
|
|
310
355
|
try {
|
|
311
356
|
const lines = readLastLines(files[i], remaining);
|
|
312
357
|
collected.unshift(lines);
|
|
313
358
|
remaining -= lines.length;
|
|
359
|
+
if (remaining <= 0)
|
|
360
|
+
boundary = { index: i, taken: lines.length };
|
|
314
361
|
}
|
|
315
362
|
catch {
|
|
316
363
|
// Rotated away mid-read; the rest are still worth showing.
|
|
317
364
|
}
|
|
318
365
|
}
|
|
319
|
-
|
|
366
|
+
const lines = collected.flat();
|
|
367
|
+
if (boundary === null)
|
|
368
|
+
return { lines, cut: null };
|
|
369
|
+
let boundaryLines;
|
|
370
|
+
try {
|
|
371
|
+
boundaryLines = countLines(files[boundary.index]);
|
|
372
|
+
}
|
|
373
|
+
catch {
|
|
374
|
+
return { lines, cut: null };
|
|
375
|
+
}
|
|
376
|
+
let olderLines = 0;
|
|
377
|
+
for (const file of files.slice(0, boundary.index)) {
|
|
378
|
+
try {
|
|
379
|
+
olderLines += countLines(file);
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
// Rotated away since the read; it is not in the window either way.
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
const startLine = Math.max(1, boundaryLines - boundary.taken + 1);
|
|
386
|
+
if (startLine === 1 && olderLines === 0)
|
|
387
|
+
return { lines, cut: null };
|
|
388
|
+
return {
|
|
389
|
+
lines,
|
|
390
|
+
cut: {
|
|
391
|
+
file: files[boundary.index],
|
|
392
|
+
startLine,
|
|
393
|
+
totalLines: olderLines + (startLine - 1) + lines.length,
|
|
394
|
+
},
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
/** The stderr sentence for a window that left older lines out. */
|
|
398
|
+
function describeLogWindowCut(cut, shown) {
|
|
399
|
+
return (`Showing the last ${shown} of ${cut.totalLines} lines; the window starts at line ` +
|
|
400
|
+
`${cut.startLine} of ${node_path_1.default.basename(cut.file)}. Drop --lines to read the full history.`);
|
|
320
401
|
}
|
|
321
402
|
/** Every byte of `files`, in order, to `out` — streamed, honouring back-pressure. */
|
|
322
403
|
async function streamLogFiles(files, out) {
|
|
@@ -623,30 +704,46 @@ class DaemonLogs extends core_1.Command {
|
|
|
623
704
|
const runtimeKnowsRotated = plan.kind === 'forward' &&
|
|
624
705
|
plan.runtimeVersion !== null &&
|
|
625
706
|
runtimeVersionAtLeast(plan.runtimeVersion, exports.ROTATED_LOGS_RUNTIME_VERSION) === true;
|
|
626
|
-
|
|
707
|
+
// OSK-16228: a `--rotated --lines N` window that cuts older lines, and
|
|
708
|
+
// `--path` with rotated siblings beside it, are said on stderr only from
|
|
709
|
+
// ROTATED_WINDOW_NOTE_RUNTIME_VERSION. Below it, read the files here.
|
|
710
|
+
const runtimeSaysWindow = plan.kind === 'forward' &&
|
|
711
|
+
plan.runtimeVersion !== null &&
|
|
712
|
+
runtimeVersionAtLeast(plan.runtimeVersion, exports.ROTATED_WINDOW_NOTE_RUNTIME_VERSION) === true;
|
|
713
|
+
if (plan.kind === 'forward' && !runtimeSaysWindow && (flags.rotated || flags.path)) {
|
|
627
714
|
const resolved = await resolveForwardedLogPath(flags);
|
|
628
|
-
if (
|
|
715
|
+
if (resolved) {
|
|
716
|
+
plan = {
|
|
717
|
+
kind: 'read',
|
|
718
|
+
path: resolved,
|
|
719
|
+
note: null,
|
|
720
|
+
missingHint: 'The live daemon has not written it yet; `skrr daemon status` shows whether one is running.',
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
else if (flags.rotated && !runtimeKnowsRotated) {
|
|
629
724
|
this.error(`The installed runtime${plan.runtimeVersion ? ` (${plan.runtimeVersion})` : ''} predates ` +
|
|
630
725
|
`--rotated (${exports.ROTATED_LOGS_RUNTIME_VERSION}) and did not name its log file, so its ` +
|
|
631
726
|
'rotated files cannot be found. Upgrade it (`skrr daemon update`), or list the ' +
|
|
632
727
|
'directory `skrr daemon logs --path` prints.', { exit: 1 });
|
|
633
728
|
}
|
|
634
|
-
|
|
635
|
-
kind: 'read',
|
|
636
|
-
path: resolved,
|
|
637
|
-
note: null,
|
|
638
|
-
missingHint: 'The live daemon has not written it yet; `skrr daemon status` shows whether one is running.',
|
|
639
|
-
};
|
|
729
|
+
// Otherwise forward: the runtime still answers, just without the note.
|
|
640
730
|
}
|
|
641
731
|
if (plan.kind === 'read') {
|
|
642
732
|
const logPath = plan.path;
|
|
643
733
|
const siblings = rotatedLogSiblings(logPath);
|
|
644
|
-
// `--path` prints the one path and nothing else
|
|
645
|
-
//
|
|
734
|
+
// `--path` prints the one path and nothing else on stdout — under
|
|
735
|
+
// --rotated, every file oldest first, the current one last. Without
|
|
736
|
+
// --rotated, stderr names the siblings a grep of that path would miss
|
|
737
|
+
// (OSK-16228).
|
|
646
738
|
if (flags.path) {
|
|
647
739
|
for (const file of flags.rotated ? siblings : [])
|
|
648
740
|
this.log(file);
|
|
649
741
|
this.log(logPath);
|
|
742
|
+
if (!flags.rotated) {
|
|
743
|
+
const hint = describeRotatedSiblings(logPath, siblings);
|
|
744
|
+
if (hint)
|
|
745
|
+
this.logToStderr(hint);
|
|
746
|
+
}
|
|
650
747
|
return;
|
|
651
748
|
}
|
|
652
749
|
if (plan.note)
|
|
@@ -668,11 +765,16 @@ class DaemonLogs extends core_1.Command {
|
|
|
668
765
|
await streamLogFiles([...siblings, logPath], process.stdout);
|
|
669
766
|
}
|
|
670
767
|
else {
|
|
671
|
-
const
|
|
672
|
-
?
|
|
673
|
-
:
|
|
768
|
+
const window = flags.rotated
|
|
769
|
+
? readLogWindow([...siblings, logPath], flags.lines ?? 200)
|
|
770
|
+
: null;
|
|
771
|
+
const lines = window ? window.lines : readDaemonLogTail(logPath, flags.lines ?? 200);
|
|
674
772
|
if (lines.length > 0)
|
|
675
773
|
this.log(lines.join('\n'));
|
|
774
|
+
// OSK-16228: after the content, so it is the last thing a terminal
|
|
775
|
+
// shows, and on stderr, so a grep over stdout is unchanged.
|
|
776
|
+
if (window?.cut)
|
|
777
|
+
this.logToStderr(describeLogWindowCut(window.cut, lines.length));
|
|
676
778
|
}
|
|
677
779
|
if (flags.follow) {
|
|
678
780
|
let position = (0, node_fs_1.statSync)(logPath).size;
|
|
@@ -40,7 +40,17 @@ class TasksRetrySchedule extends base_command_1.BaseCommand {
|
|
|
40
40
|
const t = result;
|
|
41
41
|
const ref = t.identifier ?? (t.taskNumber ? `#${t.taskNumber}` : '');
|
|
42
42
|
const when = flags.at ?? t.scheduledFor ?? '(server default)';
|
|
43
|
-
|
|
43
|
+
const retry = t.scheduleRetry;
|
|
44
|
+
const subject = `task ${t.id ?? t._id ?? taskRef}${ref ? ` (${ref})` : ''}`;
|
|
45
|
+
if (retry?.changed === false) {
|
|
46
|
+
this.log(`Schedule for ${subject} is already armed for ${when}; nothing changed.`);
|
|
47
|
+
}
|
|
48
|
+
else if (retry?.armedFirstSchedule) {
|
|
49
|
+
this.log(`Armed a first schedule for ${subject} → ${when} (it had none; \`tasks schedule\` is the command for that).`);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.log(`Re-armed schedule for ${subject} → ${when}`);
|
|
53
|
+
}
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
exports.default = TasksRetrySchedule;
|
package/oclif.manifest.json
CHANGED
|
@@ -132497,5 +132497,5 @@
|
|
|
132497
132497
|
]
|
|
132498
132498
|
}
|
|
132499
132499
|
},
|
|
132500
|
-
"version": "0.1.
|
|
132500
|
+
"version": "0.1.106"
|
|
132501
132501
|
}
|