chainlesschain 0.43.2 → 0.43.4
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/package.json +4 -2
- package/src/commands/init.js +2252 -1
- package/src/commands/skill.js +166 -0
- package/src/lib/skill-loader.js +4 -0
- package/src/lib/skill-packs/generator.js +630 -0
- package/src/lib/skill-packs/schema.js +462 -0
package/src/commands/skill.js
CHANGED
|
@@ -14,6 +14,12 @@ import { logger } from "../lib/logger.js";
|
|
|
14
14
|
import { CLISkillLoader, LAYER_NAMES } from "../lib/skill-loader.js";
|
|
15
15
|
import { getElectronUserDataDir } from "../lib/paths.js";
|
|
16
16
|
import { findProjectRoot } from "../lib/project-detector.js";
|
|
17
|
+
import {
|
|
18
|
+
generateCliPacks,
|
|
19
|
+
checkForUpdates,
|
|
20
|
+
removeCliPacks,
|
|
21
|
+
} from "../lib/skill-packs/generator.js";
|
|
22
|
+
import { CLI_PACK_DOMAINS } from "../lib/skill-packs/schema.js";
|
|
17
23
|
|
|
18
24
|
const LAYER_LABELS = {
|
|
19
25
|
bundled: chalk.blue("[bundled]"),
|
|
@@ -474,6 +480,166 @@ export function registerSkillCommand(program) {
|
|
|
474
480
|
}
|
|
475
481
|
});
|
|
476
482
|
|
|
483
|
+
// skill sync-cli — generate / update CLI command skill packs
|
|
484
|
+
skill
|
|
485
|
+
.command("sync-cli")
|
|
486
|
+
.description(
|
|
487
|
+
"Generate or update CLI command skill packs (9 domain packs wrapping all 62 CLI commands)",
|
|
488
|
+
)
|
|
489
|
+
.option("--force", "Force regenerate all packs even if unchanged")
|
|
490
|
+
.option("--dry-run", "Preview changes without writing files")
|
|
491
|
+
.option("--remove", "Remove all generated CLI packs")
|
|
492
|
+
.option(
|
|
493
|
+
"--output <dir>",
|
|
494
|
+
"Custom output directory (default: managed skills layer)",
|
|
495
|
+
)
|
|
496
|
+
.option("--json", "Output result as JSON")
|
|
497
|
+
.action(async (options) => {
|
|
498
|
+
// Remove mode
|
|
499
|
+
if (options.remove) {
|
|
500
|
+
const spinner = ora("Removing CLI pack skills...").start();
|
|
501
|
+
try {
|
|
502
|
+
const removed = removeCliPacks(options.output);
|
|
503
|
+
spinner.stop();
|
|
504
|
+
if (removed.length === 0) {
|
|
505
|
+
logger.info("No CLI packs found to remove.");
|
|
506
|
+
} else {
|
|
507
|
+
logger.success(`Removed ${removed.length} CLI pack(s):`);
|
|
508
|
+
for (const d of removed) {
|
|
509
|
+
logger.log(` ${chalk.gray("✗")} ${d}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
loader.clearCache();
|
|
513
|
+
} catch (err) {
|
|
514
|
+
spinner.fail(`Failed to remove packs: ${err.message}`);
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Dry-run: preview what would change
|
|
521
|
+
if (options.dryRun) {
|
|
522
|
+
const updates = checkForUpdates(options.output);
|
|
523
|
+
const totalDomains = Object.keys(CLI_PACK_DOMAINS).length;
|
|
524
|
+
const upToDate = totalDomains - updates.length;
|
|
525
|
+
|
|
526
|
+
logger.log(chalk.bold("\nCLI Pack Sync Preview (dry-run):\n"));
|
|
527
|
+
logger.log(
|
|
528
|
+
chalk.gray(
|
|
529
|
+
` Total domains: ${totalDomains} | Up-to-date: ${upToDate} | Need update: ${updates.length}\n`,
|
|
530
|
+
),
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
if (updates.length === 0) {
|
|
534
|
+
logger.success("All CLI packs are up-to-date. Nothing to generate.");
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
for (const u of updates) {
|
|
539
|
+
const icon = u.exists ? chalk.yellow("↻") : chalk.green("+");
|
|
540
|
+
const reason = u.changeReason === "new" ? "new" : "hash changed";
|
|
541
|
+
logger.log(
|
|
542
|
+
` ${icon} ${chalk.cyan(u.domain.padEnd(28))} ${chalk.gray(reason)} — ${u.displayName}`,
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
logger.log(
|
|
546
|
+
chalk.gray(
|
|
547
|
+
`\nRun without --dry-run to generate ${updates.length} pack(s).\n`,
|
|
548
|
+
),
|
|
549
|
+
);
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Generate packs
|
|
554
|
+
const spinner = ora(
|
|
555
|
+
options.force
|
|
556
|
+
? "Regenerating all CLI packs (--force)..."
|
|
557
|
+
: "Syncing CLI command skill packs...",
|
|
558
|
+
).start();
|
|
559
|
+
|
|
560
|
+
try {
|
|
561
|
+
const result = await generateCliPacks({
|
|
562
|
+
force: options.force || false,
|
|
563
|
+
dryRun: false,
|
|
564
|
+
outputDir: options.output,
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
spinner.stop();
|
|
568
|
+
|
|
569
|
+
if (options.json) {
|
|
570
|
+
console.log(JSON.stringify(result, null, 2));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const totalDomains = Object.keys(CLI_PACK_DOMAINS).length;
|
|
575
|
+
|
|
576
|
+
logger.log(chalk.bold("\nCLI Pack Sync Result:\n"));
|
|
577
|
+
logger.log(
|
|
578
|
+
chalk.gray(
|
|
579
|
+
` CLI version: ${result.cliVersion} | Output: ${result.outputDir}\n`,
|
|
580
|
+
),
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
if (result.generated.length > 0) {
|
|
584
|
+
logger.log(
|
|
585
|
+
chalk.green(` Generated / Updated (${result.generated.length}):`),
|
|
586
|
+
);
|
|
587
|
+
for (const g of result.generated) {
|
|
588
|
+
const icon =
|
|
589
|
+
g.changeReason === "new" ? chalk.green("+") : chalk.yellow("↻");
|
|
590
|
+
const mode = chalk.gray(`[${g.executionMode || "direct"}]`);
|
|
591
|
+
const cmds = chalk.gray(`${g.commandCount || 0} commands`);
|
|
592
|
+
logger.log(
|
|
593
|
+
` ${icon} ${chalk.cyan((g.domain || g).padEnd(28))} ${mode} ${cmds}`,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
logger.log("");
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (result.skipped.length > 0) {
|
|
600
|
+
logger.log(chalk.gray(` Skipped (${result.skipped.length}):`));
|
|
601
|
+
for (const s of result.skipped) {
|
|
602
|
+
logger.log(
|
|
603
|
+
` ${chalk.gray("–")} ${chalk.gray((s.domain || s).padEnd(28))} up-to-date`,
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
logger.log("");
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (result.errors.length > 0) {
|
|
610
|
+
logger.log(chalk.red(` Errors (${result.errors.length}):`));
|
|
611
|
+
for (const e of result.errors) {
|
|
612
|
+
logger.log(` ${chalk.red("✗")} ${e.domain}: ${e.error}`);
|
|
613
|
+
}
|
|
614
|
+
logger.log("");
|
|
615
|
+
process.exit(1);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
const summary =
|
|
619
|
+
result.generated.length > 0
|
|
620
|
+
? `${result.generated.length} pack(s) generated, ${result.skipped.length} skipped`
|
|
621
|
+
: "All packs up-to-date";
|
|
622
|
+
|
|
623
|
+
logger.success(
|
|
624
|
+
`${summary} (${totalDomains} total domains, outputDir: ${result.outputDir})`,
|
|
625
|
+
);
|
|
626
|
+
logger.log(
|
|
627
|
+
chalk.gray(
|
|
628
|
+
`\nRun ${chalk.cyan("chainlesschain skill list --category cli-direct")} to see the packs.\n`,
|
|
629
|
+
),
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
// Invalidate loader cache so new packs are visible immediately
|
|
633
|
+
loader.clearCache();
|
|
634
|
+
} catch (err) {
|
|
635
|
+
spinner.fail(`Sync failed: ${err.message}`);
|
|
636
|
+
if (program.opts().verbose) {
|
|
637
|
+
console.error(err.stack);
|
|
638
|
+
}
|
|
639
|
+
process.exit(1);
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
|
|
477
643
|
// skill sources — show layer paths and counts
|
|
478
644
|
skill
|
|
479
645
|
.command("sources")
|
package/src/lib/skill-loader.js
CHANGED
|
@@ -218,6 +218,10 @@ export class CLISkillLoader {
|
|
|
218
218
|
handler: data.handler || null,
|
|
219
219
|
capabilities: data.capabilities || [],
|
|
220
220
|
os: data.os || [],
|
|
221
|
+
// CLI pack extended fields
|
|
222
|
+
executionMode: data.executionMode || null,
|
|
223
|
+
cliDomain: data.cliDomain || null,
|
|
224
|
+
cliVersionHash: data.cliVersionHash || null,
|
|
221
225
|
dirName: entry.name,
|
|
222
226
|
hasHandler: fs.existsSync(path.join(dir, entry.name, "handler.js")),
|
|
223
227
|
body,
|