skild 0.2.5 → 0.2.7

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.
Files changed (2) hide show
  1. package/dist/index.js +110 -37
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -6,8 +6,10 @@ import chalk15 from "chalk";
6
6
  import { createRequire } from "module";
7
7
 
8
8
  // src/commands/install.ts
9
+ import fs from "fs";
10
+ import path from "path";
9
11
  import chalk2 from "chalk";
10
- import { fetchWithTimeout, installRegistrySkill, installSkill, loadRegistryAuth, resolveRegistryUrl, SkildError } from "@skild/core";
12
+ import { fetchWithTimeout, installRegistrySkill, installSkill, loadRegistryAuth, resolveRegistryAlias, resolveRegistryUrl, SkildError } from "@skild/core";
11
13
 
12
14
  // src/utils/logger.ts
13
15
  import chalk from "chalk";
@@ -55,10 +57,10 @@ var logger = {
55
57
  /**
56
58
  * Log a skill entry with status indicator.
57
59
  */
58
- skillEntry: (name, path3, hasSkillMd) => {
60
+ skillEntry: (name, path4, hasSkillMd) => {
59
61
  const status = hasSkillMd ? chalk.green("\u2713") : chalk.yellow("\u26A0");
60
62
  console.log(` ${status} ${chalk.cyan(name)}`);
61
- console.log(chalk.dim(` \u2514\u2500 ${path3}`));
63
+ console.log(chalk.dim(` \u2514\u2500 ${path4}`));
62
64
  },
63
65
  /**
64
66
  * Log installation result details.
@@ -70,17 +72,43 @@ var logger = {
70
72
  };
71
73
 
72
74
  // src/commands/install.ts
75
+ function looksLikeAlias(input) {
76
+ const s = input.trim();
77
+ if (!s) return false;
78
+ if (s.startsWith("@")) return false;
79
+ if (s.includes("/") || s.includes("\\")) return false;
80
+ if (/^https?:\/\//i.test(s) || s.includes("github.com")) return false;
81
+ if (fs.existsSync(path.resolve(s))) return false;
82
+ if (s.length < 3 || s.length > 64) return false;
83
+ if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(s)) return false;
84
+ if (s.includes("--")) return false;
85
+ return true;
86
+ }
73
87
  async function install(source, options = {}) {
74
88
  const platform = options.target || "claude";
75
89
  const scope = options.local ? "project" : "global";
76
90
  const auth = loadRegistryAuth();
77
91
  const registryUrlForDeps = options.registry || auth?.registryUrl;
92
+ let resolvedSource = source.trim();
93
+ try {
94
+ if (looksLikeAlias(resolvedSource)) {
95
+ const registryUrl = resolveRegistryUrl(registryUrlForDeps);
96
+ const resolved = await resolveRegistryAlias(registryUrl, resolvedSource);
97
+ if (!options.json) logger.info(`Resolved ${chalk2.cyan(resolvedSource)} \u2192 ${chalk2.cyan(resolved.spec)} (${resolved.type})`);
98
+ resolvedSource = resolved.spec;
99
+ }
100
+ } catch (error) {
101
+ const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
102
+ console.error(chalk2.red(message));
103
+ process.exitCode = 1;
104
+ return;
105
+ }
78
106
  const spinner = createSpinner(`Installing ${chalk2.cyan(source)} to ${chalk2.dim(platform)} (${scope})...`);
79
107
  try {
80
- const record = source.trim().startsWith("@") && source.includes("/") ? await installRegistrySkill(
81
- { spec: source, registryUrl: registryUrlForDeps },
108
+ const record = resolvedSource.startsWith("@") && resolvedSource.includes("/") ? await installRegistrySkill(
109
+ { spec: resolvedSource, registryUrl: registryUrlForDeps },
82
110
  { platform, scope, force: Boolean(options.force) }
83
- ) : await installSkill({ source }, { platform, scope, force: Boolean(options.force), registryUrl: registryUrlForDeps });
111
+ ) : await installSkill({ source: resolvedSource }, { platform, scope, force: Boolean(options.force), registryUrl: registryUrlForDeps });
84
112
  const displayName = record.canonicalName || record.name;
85
113
  spinner.succeed(`Installed ${chalk2.green(displayName)} to ${chalk2.dim(record.installDir)}`);
86
114
  if (options.json) {
@@ -138,8 +166,8 @@ async function reportDownload(record, registryOverride) {
138
166
 
139
167
  // src/commands/list.ts
140
168
  import chalk3 from "chalk";
141
- import fs from "fs";
142
- import path from "path";
169
+ import fs2 from "fs";
170
+ import path2 from "path";
143
171
  import { PLATFORMS, listAllSkills, listSkills } from "@skild/core";
144
172
  function toDisplayName(name, mapping) {
145
173
  return mapping.get(name) || name;
@@ -172,8 +200,8 @@ function buildDisplayEntries(skills) {
172
200
  if (!inlineDeps.length) continue;
173
201
  const ownerName = toDisplayName(skill.name, nameToDisplay);
174
202
  for (const dep of inlineDeps) {
175
- const inlineDir = dep.inlinePath ? path.join(skill.installDir, dep.inlinePath) : path.join(skill.installDir, dep.name);
176
- const hasSkillMd = fs.existsSync(path.join(inlineDir, "SKILL.md"));
203
+ const inlineDir = dep.inlinePath ? path2.join(skill.installDir, dep.inlinePath) : path2.join(skill.installDir, dep.name);
204
+ const hasSkillMd = fs2.existsSync(path2.join(inlineDir, "SKILL.md"));
177
205
  entries.push({
178
206
  name: dep.name,
179
207
  installDir: inlineDir,
@@ -399,25 +427,48 @@ async function promptLine(question, defaultValue) {
399
427
  }
400
428
  }
401
429
  async function promptPassword(question) {
402
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
403
- rl.stdoutMuted = false;
404
- const prompt = `${question}: `;
405
- rl._writeToOutput = function _writeToOutput(stringToWrite) {
406
- if (this.stdoutMuted) {
407
- if (stringToWrite === "\n" || stringToWrite === "\r\n") this.output.write(stringToWrite);
408
- return;
430
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
431
+ return promptLine(question);
432
+ }
433
+ const stdin = process.stdin;
434
+ const stdout = process.stdout;
435
+ stdout.write(`${question}: `);
436
+ const wasRaw = Boolean(stdin.isRaw);
437
+ stdin.setRawMode(true);
438
+ stdin.resume();
439
+ readline.emitKeypressEvents(stdin);
440
+ const buf = [];
441
+ return await new Promise((resolve, reject) => {
442
+ function cleanup() {
443
+ stdin.off("keypress", onKeypress);
444
+ stdin.setRawMode(wasRaw);
445
+ stdin.pause();
409
446
  }
410
- this.output.write(stringToWrite);
411
- };
412
- try {
413
- const answerPromise = new Promise((resolve) => rl.question(prompt, resolve));
414
- rl.stdoutMuted = true;
415
- const answer = await answerPromise;
416
- return String(answer || "");
417
- } finally {
418
- rl.stdoutMuted = false;
419
- rl.close();
420
- }
447
+ function onKeypress(str, key) {
448
+ if (key?.ctrl && key?.name === "c") {
449
+ stdout.write("\n");
450
+ cleanup();
451
+ const err = new Error("Prompt cancelled");
452
+ err.code = "PROMPT_CANCELLED";
453
+ reject(err);
454
+ return;
455
+ }
456
+ if (key?.name === "return" || key?.name === "enter") {
457
+ stdout.write("\n");
458
+ cleanup();
459
+ resolve(buf.join(""));
460
+ return;
461
+ }
462
+ if (key?.name === "backspace" || key?.name === "delete") {
463
+ if (buf.length) buf.pop();
464
+ return;
465
+ }
466
+ if (!str) return;
467
+ if (key?.ctrl || key?.meta) return;
468
+ buf.push(str);
469
+ }
470
+ stdin.on("keypress", onKeypress);
471
+ });
421
472
  }
422
473
 
423
474
  // src/commands/signup.ts
@@ -434,7 +485,18 @@ async function signup(options) {
434
485
  }
435
486
  const finalEmail = email || await promptLine("Email");
436
487
  const finalHandle = handle || (await promptLine("Handle (publisher scope)", void 0)).toLowerCase();
437
- const finalPassword = password || await promptPassword("Password");
488
+ let finalPassword = password;
489
+ if (!finalPassword) {
490
+ try {
491
+ finalPassword = await promptPassword("Password");
492
+ } catch (e) {
493
+ if (e?.code === "PROMPT_CANCELLED") {
494
+ process.exitCode = 130;
495
+ return;
496
+ }
497
+ throw e;
498
+ }
499
+ }
438
500
  let text = "";
439
501
  try {
440
502
  const res = await fetchWithTimeout2(
@@ -501,7 +563,18 @@ async function login(options) {
501
563
  return;
502
564
  }
503
565
  const finalHandleOrEmail = handleOrEmail || await promptLine("Handle or email");
504
- const finalPassword = password || await promptPassword("Password");
566
+ let finalPassword = password;
567
+ if (!finalPassword) {
568
+ try {
569
+ finalPassword = await promptPassword("Password");
570
+ } catch (e) {
571
+ if (e?.code === "PROMPT_CANCELLED") {
572
+ process.exitCode = 130;
573
+ return;
574
+ }
575
+ throw e;
576
+ }
577
+ }
505
578
  const finalTokenName = options.tokenName?.trim() || void 0;
506
579
  let text = "";
507
580
  try {
@@ -591,9 +664,9 @@ async function whoami() {
591
664
  }
592
665
 
593
666
  // src/commands/publish.ts
594
- import fs2 from "fs";
667
+ import fs3 from "fs";
595
668
  import os from "os";
596
- import path2 from "path";
669
+ import path3 from "path";
597
670
  import crypto from "crypto";
598
671
  import * as tar from "tar";
599
672
  import chalk13 from "chalk";
@@ -616,7 +689,7 @@ async function publish(options = {}) {
616
689
  process.exitCode = 1;
617
690
  return;
618
691
  }
619
- const dir = path2.resolve(options.dir || process.cwd());
692
+ const dir = path3.resolve(options.dir || process.cwd());
620
693
  const validation = validateSkillDir(dir);
621
694
  if (!validation.ok) {
622
695
  console.error(chalk13.red("Skill validation failed:"));
@@ -675,8 +748,8 @@ async function publish(options = {}) {
675
748
  return;
676
749
  }
677
750
  const spinner = createSpinner(`Publishing ${chalk13.cyan(`${name}@${version2}`)} to ${chalk13.dim(registry)}...`);
678
- const tempDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "skild-publish-"));
679
- const tarballPath = path2.join(tempDir, "skill.tgz");
751
+ const tempDir = fs3.mkdtempSync(path3.join(os.tmpdir(), "skild-publish-"));
752
+ const tarballPath = path3.join(tempDir, "skill.tgz");
680
753
  try {
681
754
  await tar.c(
682
755
  {
@@ -688,7 +761,7 @@ async function publish(options = {}) {
688
761
  },
689
762
  ["."]
690
763
  );
691
- const buf = fs2.readFileSync(tarballPath);
764
+ const buf = fs3.readFileSync(tarballPath);
692
765
  const integrity = sha256Hex(buf);
693
766
  const form = new FormData();
694
767
  form.set("version", version2);
@@ -732,7 +805,7 @@ async function publish(options = {}) {
732
805
  console.error(chalk13.red(message));
733
806
  process.exitCode = 1;
734
807
  } finally {
735
- fs2.rmSync(tempDir, { recursive: true, force: true });
808
+ fs3.rmSync(tempDir, { recursive: true, force: true });
736
809
  }
737
810
  }
738
811
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skild",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "The npm for Agent Skills — Discover, install, manage, and publish AI Agent Skills with ease.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,7 +37,7 @@
37
37
  "commander": "^12.1.0",
38
38
  "ora": "^8.0.1",
39
39
  "tar": "^7.4.3",
40
- "@skild/core": "^0.2.5"
40
+ "@skild/core": "^0.2.7"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^20.10.0",