servicemap 0.1.15 → 0.1.17
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/bin/servicemap.mjs +19 -63
- package/package.json +1 -1
package/bin/servicemap.mjs
CHANGED
|
@@ -404,62 +404,6 @@ function runTargetSurvey() {
|
|
|
404
404
|
});
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
function renderInstallMethodSurvey(cursor) {
|
|
408
|
-
console.clear();
|
|
409
|
-
const methods = [
|
|
410
|
-
{ id: 'symlink', label: 'Symlink', note: 'Recommended, one stable source for easy updates' },
|
|
411
|
-
{ id: 'copy', label: 'Copy', note: 'Standalone copies in each selected agent folder' },
|
|
412
|
-
];
|
|
413
|
-
|
|
414
|
-
timelineStep(cyan('servicemap'));
|
|
415
|
-
timelineStep(`Source: ${repositoryUrl}`);
|
|
416
|
-
timelineStep(`Stable source: ${stableSourceRoot()}`);
|
|
417
|
-
timelineStep('Agents selected');
|
|
418
|
-
timelineActive('Installation method');
|
|
419
|
-
methods.forEach((method, index) => {
|
|
420
|
-
const pointer = index === cursor ? '>' : ' ';
|
|
421
|
-
const selected = index === cursor ? '●' : '○';
|
|
422
|
-
timelineLine(`${pointer} ${selected} ${method.label} ${dim(`(${method.note})`)}`);
|
|
423
|
-
});
|
|
424
|
-
timelineLine(dim('↑/↓ to navigate • Enter to confirm'));
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function runInstallMethodSurvey() {
|
|
428
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
429
|
-
return Promise.resolve('copy');
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const methods = ['symlink', 'copy'];
|
|
433
|
-
let cursor = 0;
|
|
434
|
-
|
|
435
|
-
return new Promise((resolvePromise) => {
|
|
436
|
-
readline.emitKeypressEvents(process.stdin);
|
|
437
|
-
process.stdin.setRawMode(true);
|
|
438
|
-
renderInstallMethodSurvey(cursor);
|
|
439
|
-
|
|
440
|
-
const onKeypress = (_str, key) => {
|
|
441
|
-
if (key.name === 'up') cursor = Math.max(0, cursor - 1);
|
|
442
|
-
if (key.name === 'down') cursor = Math.min(methods.length - 1, cursor + 1);
|
|
443
|
-
if (key.name === 'return') {
|
|
444
|
-
process.stdin.setRawMode(false);
|
|
445
|
-
process.stdin.off('keypress', onKeypress);
|
|
446
|
-
console.log('');
|
|
447
|
-
resolvePromise(methods[cursor]);
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
if (key.ctrl && key.name === 'c') {
|
|
451
|
-
process.stdin.setRawMode(false);
|
|
452
|
-
process.stdin.off('keypress', onKeypress);
|
|
453
|
-
process.exit(130);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
renderInstallMethodSurvey(cursor);
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
process.stdin.on('keypress', onKeypress);
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
|
|
463
407
|
function runSilent(command, args, options = {}) {
|
|
464
408
|
return new Promise((resolvePromise, reject) => {
|
|
465
409
|
const child = spawn(command, args, {
|
|
@@ -475,7 +419,13 @@ function runSilent(command, args, options = {}) {
|
|
|
475
419
|
});
|
|
476
420
|
}
|
|
477
421
|
|
|
478
|
-
|
|
422
|
+
function wait(ms) {
|
|
423
|
+
return new Promise((resolvePromise) => {
|
|
424
|
+
setTimeout(resolvePromise, ms);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
async function withSpinner(message, action, minimumMs = 900) {
|
|
479
429
|
if (!process.stdout.isTTY) {
|
|
480
430
|
return action();
|
|
481
431
|
}
|
|
@@ -483,15 +433,22 @@ async function withSpinner(message, action) {
|
|
|
483
433
|
const frames = ['◒', '◐', '◓', '◑'];
|
|
484
434
|
let frame = 0;
|
|
485
435
|
let dots = '';
|
|
486
|
-
|
|
487
|
-
const
|
|
436
|
+
const startedAt = Date.now();
|
|
437
|
+
const writeFrame = () => {
|
|
488
438
|
process.stdout.write(`\r\x1b[J${frames[frame]} ${message}${dots}`);
|
|
489
439
|
frame = (frame + 1) % frames.length;
|
|
490
440
|
if (frame === 0) dots = dots.length >= 5 ? '' : `${dots}.`;
|
|
491
|
-
}
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
process.stdout.write('\x1b[?25l');
|
|
444
|
+
writeFrame();
|
|
445
|
+
const interval = setInterval(writeFrame, 120);
|
|
492
446
|
|
|
493
447
|
try {
|
|
494
|
-
|
|
448
|
+
const result = await action();
|
|
449
|
+
const remainingMs = minimumMs - (Date.now() - startedAt);
|
|
450
|
+
if (remainingMs > 0) await wait(remainingMs);
|
|
451
|
+
return result;
|
|
495
452
|
} finally {
|
|
496
453
|
clearInterval(interval);
|
|
497
454
|
process.stdout.write('\r\x1b[J\x1b[?25h');
|
|
@@ -553,8 +510,7 @@ async function installSkill(options) {
|
|
|
553
510
|
? [{ id: 'universal', label: 'Universal', root: universalRoot }, ...await runTargetSurvey()]
|
|
554
511
|
: targetsForOptions(options);
|
|
555
512
|
const roots = skillRootsForTargets(options, selectedTargets);
|
|
556
|
-
const method = options.installMethod
|
|
557
|
-
?? (options.survey && !options.yes ? await runInstallMethodSurvey() : 'copy');
|
|
513
|
+
const method = options.installMethod ?? 'symlink';
|
|
558
514
|
|
|
559
515
|
if (!existsSync(source)) {
|
|
560
516
|
throw new Error(`Bundled skill folder not found: ${source}`);
|