@cantemizyurek/skillz 0.1.7 → 0.1.9

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/index.cjs CHANGED
@@ -11282,6 +11282,262 @@ var scopeSchema = external_exports.enum(SCOPE_VALUES);
11282
11282
  // src/index.ts
11283
11283
  var import_commander = require("commander");
11284
11284
 
11285
+ // package.json
11286
+ var package_default = {
11287
+ name: "@cantemizyurek/skillz",
11288
+ version: "0.1.9",
11289
+ publishConfig: {
11290
+ access: "public"
11291
+ },
11292
+ files: [
11293
+ "dist"
11294
+ ],
11295
+ type: "module",
11296
+ bin: {
11297
+ skillz: "./dist/index.cjs"
11298
+ },
11299
+ main: "./dist/index.cjs",
11300
+ types: "./dist/index.d.cts",
11301
+ exports: {
11302
+ ".": {
11303
+ types: "./dist/index.d.cts",
11304
+ default: "./dist/index.cjs"
11305
+ }
11306
+ },
11307
+ scripts: {
11308
+ dev: "tsx src/index.ts",
11309
+ build: "tsup src/index.ts --format cjs --dts --sourcemap --clean",
11310
+ lint: "tsc --noEmit",
11311
+ test: "vitest run"
11312
+ },
11313
+ dependencies: {
11314
+ "@inquirer/prompts": "^7.3.2",
11315
+ "@vercel/blob": "^0.27.0",
11316
+ commander: "^13.1.0",
11317
+ tar: "^7.4.3",
11318
+ "tar-stream": "^3.1.7"
11319
+ },
11320
+ devDependencies: {
11321
+ "@cantemizyurek/shared": "workspace:*",
11322
+ "@types/node": "^22.13.9",
11323
+ tsup: "^8.4.0",
11324
+ tsx: "^4.19.3",
11325
+ typescript: "^5.7.0",
11326
+ vitest: "^3.0.7"
11327
+ }
11328
+ };
11329
+
11330
+ // src/auto-update.ts
11331
+ var DEFAULT_AUTO_UPDATE_INTERVAL_HOURS = 24;
11332
+ var MIN_AUTO_UPDATE_INTERVAL_HOURS = 1;
11333
+ var MAX_AUTO_UPDATE_INTERVAL_HOURS = 24 * 30;
11334
+ function resolveAutoUpdateSettings(config) {
11335
+ return {
11336
+ enabled: typeof config.autoUpdateEnabled === "boolean" ? config.autoUpdateEnabled : true,
11337
+ intervalHours: normalizeAutoUpdateInterval(config.autoUpdateIntervalHours),
11338
+ lastCheckedAt: typeof config.autoUpdateLastCheckedAt === "string" ? config.autoUpdateLastCheckedAt : void 0
11339
+ };
11340
+ }
11341
+ function shouldRunAutoUpdateNow(config, now = /* @__PURE__ */ new Date()) {
11342
+ const settings = resolveAutoUpdateSettings(config);
11343
+ if (!settings.enabled) {
11344
+ return false;
11345
+ }
11346
+ if (!settings.lastCheckedAt) {
11347
+ return true;
11348
+ }
11349
+ const lastCheckedAt = new Date(settings.lastCheckedAt);
11350
+ if (Number.isNaN(lastCheckedAt.getTime())) {
11351
+ return true;
11352
+ }
11353
+ const elapsedMs = now.getTime() - lastCheckedAt.getTime();
11354
+ if (elapsedMs < 0) {
11355
+ return true;
11356
+ }
11357
+ return elapsedMs >= settings.intervalHours * 60 * 60 * 1e3;
11358
+ }
11359
+ function parseAutoUpdateIntervalHours(input) {
11360
+ const parsed = Number(input);
11361
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) {
11362
+ throw new Error("Auto-update interval must be an integer number of hours");
11363
+ }
11364
+ if (parsed < MIN_AUTO_UPDATE_INTERVAL_HOURS || parsed > MAX_AUTO_UPDATE_INTERVAL_HOURS) {
11365
+ throw new Error(
11366
+ `Auto-update interval must be between ${MIN_AUTO_UPDATE_INTERVAL_HOURS} and ${MAX_AUTO_UPDATE_INTERVAL_HOURS} hours`
11367
+ );
11368
+ }
11369
+ return parsed;
11370
+ }
11371
+ function normalizeAutoUpdateInterval(input) {
11372
+ if (typeof input !== "number" || !Number.isFinite(input)) {
11373
+ return DEFAULT_AUTO_UPDATE_INTERVAL_HOURS;
11374
+ }
11375
+ const rounded = Math.round(input);
11376
+ if (rounded < MIN_AUTO_UPDATE_INTERVAL_HOURS) {
11377
+ return MIN_AUTO_UPDATE_INTERVAL_HOURS;
11378
+ }
11379
+ if (rounded > MAX_AUTO_UPDATE_INTERVAL_HOURS) {
11380
+ return MAX_AUTO_UPDATE_INTERVAL_HOURS;
11381
+ }
11382
+ return rounded;
11383
+ }
11384
+
11385
+ // src/cli-self-update.ts
11386
+ var import_node_child_process = require("child_process");
11387
+ var NPM_REGISTRY_BASE_URL = "https://registry.npmjs.org";
11388
+ var SUPPORTED_PACKAGE_MANAGERS = ["pnpm", "npm", "yarn", "bun"];
11389
+ async function runCliSelfUpdate(input) {
11390
+ const latestVersion = await fetchLatestPackageVersion(input.packageName);
11391
+ if (!shouldUpdateCli(input.currentVersion, latestVersion)) {
11392
+ return {
11393
+ latestVersion,
11394
+ updated: false
11395
+ };
11396
+ }
11397
+ const manager = await resolveInstalledPackageManager(
11398
+ input.preferredPackageManager ?? null
11399
+ );
11400
+ if (!manager) {
11401
+ throw new Error(
11402
+ "No supported package manager found (pnpm, npm, yarn, bun)"
11403
+ );
11404
+ }
11405
+ const installCommand = buildSelfUpdateInstallCommand(manager, input.packageName);
11406
+ await runCommand(installCommand.command, installCommand.args);
11407
+ return {
11408
+ latestVersion,
11409
+ updated: true,
11410
+ manager
11411
+ };
11412
+ }
11413
+ async function fetchLatestPackageVersion(packageName) {
11414
+ const encodedPackageName = encodeURIComponent(packageName);
11415
+ const response = await fetch(
11416
+ `${NPM_REGISTRY_BASE_URL}/${encodedPackageName}/latest`,
11417
+ {
11418
+ method: "GET",
11419
+ headers: {
11420
+ accept: "application/json"
11421
+ }
11422
+ }
11423
+ );
11424
+ if (!response.ok) {
11425
+ throw new Error(
11426
+ `Failed to check latest CLI version (status ${response.status})`
11427
+ );
11428
+ }
11429
+ const body = await response.json();
11430
+ return typeof body.version === "string" ? body.version : null;
11431
+ }
11432
+ function shouldUpdateCli(currentVersion, latestVersion) {
11433
+ if (!latestVersion) {
11434
+ return false;
11435
+ }
11436
+ return isSemverGreater(latestVersion, currentVersion);
11437
+ }
11438
+ function resolvePreferredPackageManager(env) {
11439
+ const explicit = env.SKILLZ_AUTO_UPDATE_MANAGER?.trim().toLowerCase();
11440
+ if (explicit && isPackageManager(explicit)) {
11441
+ return explicit;
11442
+ }
11443
+ const userAgentManager = parsePackageManagerFromUserAgent(
11444
+ env.npm_config_user_agent
11445
+ );
11446
+ if (userAgentManager) {
11447
+ return userAgentManager;
11448
+ }
11449
+ return null;
11450
+ }
11451
+ function parsePackageManagerFromUserAgent(userAgent) {
11452
+ if (!userAgent) {
11453
+ return null;
11454
+ }
11455
+ const normalized = userAgent.trim().toLowerCase();
11456
+ for (const manager of SUPPORTED_PACKAGE_MANAGERS) {
11457
+ if (normalized.startsWith(`${manager}/`)) {
11458
+ return manager;
11459
+ }
11460
+ }
11461
+ return null;
11462
+ }
11463
+ function buildSelfUpdateInstallCommand(manager, packageName) {
11464
+ const packageSpecifier = `${packageName}@latest`;
11465
+ switch (manager) {
11466
+ case "pnpm":
11467
+ return {
11468
+ command: "pnpm",
11469
+ args: ["add", "-g", packageSpecifier]
11470
+ };
11471
+ case "npm":
11472
+ return {
11473
+ command: "npm",
11474
+ args: ["install", "-g", packageSpecifier]
11475
+ };
11476
+ case "yarn":
11477
+ return {
11478
+ command: "yarn",
11479
+ args: ["global", "add", packageSpecifier]
11480
+ };
11481
+ case "bun":
11482
+ return {
11483
+ command: "bun",
11484
+ args: ["add", "-g", packageSpecifier]
11485
+ };
11486
+ default: {
11487
+ const _exhaustiveCheck = manager;
11488
+ throw new Error(`Unsupported package manager: ${_exhaustiveCheck}`);
11489
+ }
11490
+ }
11491
+ }
11492
+ async function resolveInstalledPackageManager(preferred) {
11493
+ if (preferred && await commandExists(preferred)) {
11494
+ return preferred;
11495
+ }
11496
+ for (const manager of SUPPORTED_PACKAGE_MANAGERS) {
11497
+ if (await commandExists(manager)) {
11498
+ return manager;
11499
+ }
11500
+ }
11501
+ return null;
11502
+ }
11503
+ async function commandExists(command) {
11504
+ return new Promise((resolve) => {
11505
+ const child = (0, import_node_child_process.spawn)(command, ["--version"], {
11506
+ stdio: "ignore"
11507
+ });
11508
+ child.once("error", () => {
11509
+ resolve(false);
11510
+ });
11511
+ child.once("exit", (code) => {
11512
+ resolve(typeof code === "number" && code === 0);
11513
+ });
11514
+ });
11515
+ }
11516
+ async function runCommand(command, args) {
11517
+ return new Promise((resolve, reject) => {
11518
+ const child = (0, import_node_child_process.spawn)(command, args, {
11519
+ stdio: "inherit"
11520
+ });
11521
+ child.once("error", (error) => {
11522
+ reject(error);
11523
+ });
11524
+ child.once("exit", (code) => {
11525
+ if (code === 0) {
11526
+ resolve();
11527
+ return;
11528
+ }
11529
+ reject(
11530
+ new Error(
11531
+ `${command} ${args.join(" ")} failed with exit code ${code ?? "unknown"}`
11532
+ )
11533
+ );
11534
+ });
11535
+ });
11536
+ }
11537
+ function isPackageManager(value) {
11538
+ return SUPPORTED_PACKAGE_MANAGERS.includes(value);
11539
+ }
11540
+
11285
11541
  // src/client.ts
11286
11542
  var RegistryClient = class {
11287
11543
  constructor(baseUrl, token) {
@@ -11421,9 +11677,9 @@ var import_node_process = __toESM(require("process"), 1);
11421
11677
  var import_prompts = require("@inquirer/prompts");
11422
11678
 
11423
11679
  // src/git.ts
11424
- var import_node_child_process = require("child_process");
11680
+ var import_node_child_process2 = require("child_process");
11425
11681
  var import_node_util = require("util");
11426
- var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
11682
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
11427
11683
  async function detectRepoRoot(cwd) {
11428
11684
  try {
11429
11685
  const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
@@ -11763,9 +12019,82 @@ async function upsertManifestEntry(entry) {
11763
12019
  await saveManifest(manifest);
11764
12020
  }
11765
12021
 
12022
+ // src/update.ts
12023
+ async function updateInstalledSkills(input) {
12024
+ if (!input.config.token) {
12025
+ throw new Error("Not logged in. Run skillz login.");
12026
+ }
12027
+ const candidateGroups = groupManifestEntriesBySource(input.entries);
12028
+ let updatedCount = 0;
12029
+ for (const group of candidateGroups) {
12030
+ const installed = group[0];
12031
+ if (installed.registryBaseUrl !== input.expectedRegistryBaseUrl) {
12032
+ if (!input.skipRegistryMismatchLogs) {
12033
+ input.onMessage?.(
12034
+ `Skipping ${installed.namespace}/${installed.name} because it belongs to ${installed.registryBaseUrl}`
12035
+ );
12036
+ }
12037
+ continue;
12038
+ }
12039
+ const client = new RegistryClient(installed.registryBaseUrl, input.config.token);
12040
+ const versions = await client.skillVersions(installed.namespace, installed.name);
12041
+ const latestVersion = versions.versions[0]?.version;
12042
+ if (!latestVersion || !group.some((entry) => isSemverGreater(latestVersion, entry.version))) {
12043
+ continue;
12044
+ }
12045
+ const sourcePath = installed.sourceInstallPath ?? installed.installPath;
12046
+ const writePath = await resolveInstallWritePath(sourcePath);
12047
+ await downloadAndInstallSkill(
12048
+ client,
12049
+ {
12050
+ namespace: installed.namespace,
12051
+ name: installed.name
12052
+ },
12053
+ latestVersion,
12054
+ writePath
12055
+ );
12056
+ const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
12057
+ for (const entry of group) {
12058
+ entry.version = latestVersion;
12059
+ entry.installedAt = updatedAt;
12060
+ }
12061
+ updatedCount += group.length;
12062
+ input.onMessage?.(
12063
+ `Updated ${installed.namespace}/${installed.name} to ${latestVersion} (${group.map((entry) => entry.agent).join(", ")})`
12064
+ );
12065
+ }
12066
+ if (updatedCount > 0) {
12067
+ await saveManifest(input.manifest);
12068
+ }
12069
+ return {
12070
+ updatedCount
12071
+ };
12072
+ }
12073
+ function groupManifestEntriesBySource(entries) {
12074
+ const grouped = /* @__PURE__ */ new Map();
12075
+ for (const entry of entries) {
12076
+ const sourcePath = entry.sourceInstallPath ?? entry.installPath;
12077
+ const key = [
12078
+ entry.registryBaseUrl,
12079
+ entry.namespace,
12080
+ entry.name,
12081
+ sourcePath
12082
+ ].join("::");
12083
+ const group = grouped.get(key);
12084
+ if (group) {
12085
+ group.push(entry);
12086
+ } else {
12087
+ grouped.set(key, [entry]);
12088
+ }
12089
+ }
12090
+ return Array.from(grouped.values());
12091
+ }
12092
+
11766
12093
  // src/index.ts
12094
+ var CLI_VERSION = typeof package_default.version === "string" ? package_default.version : "0.0.0";
12095
+ var CLI_PACKAGE_NAME = typeof package_default.name === "string" ? package_default.name : "@cantemizyurek/skillz";
11767
12096
  var program = new import_commander.Command();
11768
- program.name("skillz").description("Private Skills Registry CLI").option("--registry <url>", "registry base URL");
12097
+ program.name("skillz").description("Private Skills Registry CLI").version(CLI_VERSION, "-V, --version", "display Skillz CLI version").option("--registry <url>", "registry base URL");
11769
12098
  program.command("register").description("Register a user account using an invite code").option("--invite <code>", "invite code").option("--username <username>", "username").option("--password <password>", "password").action(async (options2, command) => {
11770
12099
  const { client } = await makeClient(command, false);
11771
12100
  const inviteCode = options2.invite ?? await (0, import_prompts2.input)({ message: "Invite code" });
@@ -11810,6 +12139,104 @@ program.command("whoami").description("Show current authenticated user").action(
11810
12139
  const me = await client.whoami();
11811
12140
  console.log(`${me.user.username} (${me.user.role})`);
11812
12141
  });
12142
+ program.command("version").description("Show CLI version and auto-update settings").action(async () => {
12143
+ const config = await loadConfig();
12144
+ const autoUpdate = resolveAutoUpdateSettings(config);
12145
+ console.log(`skillz ${CLI_VERSION}`);
12146
+ console.log(
12147
+ `Auto updates: ${autoUpdate.enabled ? "enabled" : "disabled"} (every ${autoUpdate.intervalHours}h)`
12148
+ );
12149
+ console.log(`Last auto-update check: ${autoUpdate.lastCheckedAt ?? "never"}`);
12150
+ });
12151
+ program.command("auto-update").description("Configure automatic CLI self-updates").option("--enable", "enable automatic updates").option("--disable", "disable automatic updates").option(
12152
+ "--interval-hours <hours>",
12153
+ "check interval in hours (1-720)",
12154
+ parseAutoUpdateIntervalHours
12155
+ ).option("--check-now", "run the auto-update check immediately").action(async (options2) => {
12156
+ if (options2.enable && options2.disable) {
12157
+ throw new Error("Use either --enable or --disable, not both");
12158
+ }
12159
+ const config = await loadConfig();
12160
+ const nextConfig = {
12161
+ ...config
12162
+ };
12163
+ let changed = false;
12164
+ if (options2.enable) {
12165
+ nextConfig.autoUpdateEnabled = true;
12166
+ changed = true;
12167
+ } else if (options2.disable) {
12168
+ nextConfig.autoUpdateEnabled = false;
12169
+ changed = true;
12170
+ }
12171
+ if (typeof options2.intervalHours === "number") {
12172
+ nextConfig.autoUpdateIntervalHours = options2.intervalHours;
12173
+ changed = true;
12174
+ }
12175
+ if (changed) {
12176
+ await saveConfig(nextConfig);
12177
+ }
12178
+ let lastCheckedAt = nextConfig.autoUpdateLastCheckedAt;
12179
+ if (options2.checkNow) {
12180
+ const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
12181
+ try {
12182
+ const result = await runCliSelfUpdate({
12183
+ packageName: CLI_PACKAGE_NAME,
12184
+ currentVersion: CLI_VERSION,
12185
+ preferredPackageManager: resolvePreferredPackageManager(import_node_process2.default.env)
12186
+ });
12187
+ if (result.updated) {
12188
+ console.log(
12189
+ `Updated skillz CLI to ${result.latestVersion} using ${result.manager}.`
12190
+ );
12191
+ console.log("Re-run your command to use the new version.");
12192
+ } else {
12193
+ console.log(
12194
+ `skillz CLI is already up to date (${result.latestVersion ?? CLI_VERSION}).`
12195
+ );
12196
+ }
12197
+ } finally {
12198
+ await saveConfig({
12199
+ ...nextConfig,
12200
+ autoUpdateLastCheckedAt: checkedAt
12201
+ });
12202
+ lastCheckedAt = checkedAt;
12203
+ }
12204
+ }
12205
+ const resolved = resolveAutoUpdateSettings({
12206
+ ...nextConfig,
12207
+ autoUpdateLastCheckedAt: lastCheckedAt
12208
+ });
12209
+ console.log(
12210
+ `Auto updates: ${resolved.enabled ? "enabled" : "disabled"} (every ${resolved.intervalHours}h)`
12211
+ );
12212
+ console.log(`Last auto-update check: ${resolved.lastCheckedAt ?? "never"}`);
12213
+ });
12214
+ program.command("self-update").description("Update skillz CLI to the latest published version").action(async () => {
12215
+ const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
12216
+ try {
12217
+ const result = await runCliSelfUpdate({
12218
+ packageName: CLI_PACKAGE_NAME,
12219
+ currentVersion: CLI_VERSION,
12220
+ preferredPackageManager: resolvePreferredPackageManager(import_node_process2.default.env)
12221
+ });
12222
+ if (result.updated) {
12223
+ console.log(
12224
+ `Updated skillz CLI to ${result.latestVersion} using ${result.manager}.`
12225
+ );
12226
+ console.log("Re-run your command to use the new version.");
12227
+ return;
12228
+ }
12229
+ console.log(
12230
+ `skillz CLI is already up to date (${result.latestVersion ?? CLI_VERSION}).`
12231
+ );
12232
+ } finally {
12233
+ const config = await loadConfig();
12234
+ await saveConfig({
12235
+ ...config,
12236
+ autoUpdateLastCheckedAt: checkedAt
12237
+ });
12238
+ }
12239
+ });
11813
12240
  program.command("list").description("List skills by download count (descending)").argument("[namespace]", "optional namespace").action(async (namespaceInput, _options, command) => {
11814
12241
  const { client } = await makeClient(command, true);
11815
12242
  const namespace = namespaceInput ? namespaceSchema.parse(namespaceInput) : void 0;
@@ -11822,7 +12249,7 @@ program.command("list").description("List skills by download count (descending)"
11822
12249
  }
11823
12250
  return;
11824
12251
  }
11825
- printSkillSummaryTable(result.skills);
12252
+ printSkillSummaryList(result.skills);
11826
12253
  });
11827
12254
  program.command("search").description("Search skills").argument("<query>", "search query").action(async (query, _options, command) => {
11828
12255
  const { client } = await makeClient(command, true);
@@ -11831,7 +12258,7 @@ program.command("search").description("Search skills").argument("<query>", "sear
11831
12258
  console.log("No skills found.");
11832
12259
  return;
11833
12260
  }
11834
- printSkillSummaryTable(result.skills);
12261
+ printSkillSummaryList(result.skills);
11835
12262
  });
11836
12263
  program.command("info").description("Show skill metadata and versions").argument("<namespace/skill>", "skill reference").action(async (skillRefInput, _options, command) => {
11837
12264
  namespaceNameSchema.parse(skillRefInput);
@@ -11979,51 +12406,17 @@ program.command("update").description("Update installed skills").argument("[name
11979
12406
  console.log("No matching installed skills to update.");
11980
12407
  return;
11981
12408
  }
11982
- if (!config.token) {
11983
- throw new Error("Not logged in. Run skillz login.");
11984
- }
11985
- const candidateGroups = groupManifestEntriesBySource(candidates);
11986
- let updatedCount = 0;
11987
- for (const group of candidateGroups) {
11988
- const installed = group[0];
11989
- if (installed.registryBaseUrl !== resolveRegistryBaseUrl(command, config)) {
11990
- console.log(
11991
- `Skipping ${installed.namespace}/${installed.name} because it belongs to ${installed.registryBaseUrl}`
11992
- );
11993
- continue;
11994
- }
11995
- const client = new RegistryClient(installed.registryBaseUrl, config.token);
11996
- const versions = await client.skillVersions(installed.namespace, installed.name);
11997
- const latestVersion = versions.versions[0]?.version;
11998
- if (!latestVersion || !group.some((entry) => isSemverGreater(latestVersion, entry.version))) {
11999
- continue;
12000
- }
12001
- const sourcePath = installed.sourceInstallPath ?? installed.installPath;
12002
- const writePath = await resolveInstallWritePath(sourcePath);
12003
- await downloadAndInstallSkill(
12004
- client,
12005
- {
12006
- namespace: installed.namespace,
12007
- name: installed.name
12008
- },
12009
- latestVersion,
12010
- writePath
12011
- );
12012
- const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
12013
- for (const entry of group) {
12014
- entry.version = latestVersion;
12015
- entry.installedAt = updatedAt;
12016
- }
12017
- updatedCount += group.length;
12018
- console.log(
12019
- `Updated ${installed.namespace}/${installed.name} to ${latestVersion} (${group.map((entry) => entry.agent).join(", ")})`
12020
- );
12021
- }
12409
+ const { updatedCount } = await updateInstalledSkills({
12410
+ config,
12411
+ expectedRegistryBaseUrl: resolveRegistryBaseUrl(command, config),
12412
+ manifest,
12413
+ entries: candidates,
12414
+ onMessage: (message) => console.log(message)
12415
+ });
12022
12416
  if (updatedCount === 0) {
12023
12417
  console.log("All matching skills are already up to date.");
12024
12418
  return;
12025
12419
  }
12026
- await saveManifest(manifest);
12027
12420
  console.log(`Updated ${updatedCount} skill(s).`);
12028
12421
  });
12029
12422
  program.command("publish").description("Publish a skill folder").argument("<path-to-skill-folder>", "path to the skill folder").requiredOption("--version <x.y.z>", "version to publish").action(async (skillPath, options2, command) => {
@@ -12045,6 +12438,9 @@ invitesCommand.command("create").description("Create a single-use invite code (a
12045
12438
  const invite = await client.createInvite();
12046
12439
  console.log(invite.inviteCode);
12047
12440
  });
12441
+ program.hook("preAction", async (_thisCommand, actionCommand) => {
12442
+ await maybeRunAutoUpdate(actionCommand);
12443
+ });
12048
12444
  program.parseAsync(import_node_process2.default.argv).catch((error) => {
12049
12445
  const message = error instanceof Error ? error.message : String(error);
12050
12446
  console.error(`Error: ${message}`);
@@ -12095,49 +12491,21 @@ function parseAgentTargetsOption(input) {
12095
12491
  }
12096
12492
  return Array.from(new Set(values));
12097
12493
  }
12098
- function printSkillSummaryTable(skills) {
12494
+ function printSkillSummaryList(skills) {
12099
12495
  const terminalWidth = import_node_process2.default.stdout.columns ?? 120;
12100
- const skillRefs = skills.map((skill) => `${skill.namespace}/${skill.name}`);
12101
- const latestValues = skills.map((skill) => skill.latestVersion ?? "none");
12102
- const downloadValues = skills.map(
12103
- (skill) => skill.downloadCount.toLocaleString("en-US")
12104
- );
12105
- const skillWidth = clamp(
12106
- Math.max("skill".length, ...skillRefs.map((value) => value.length)),
12107
- 20,
12108
- 40
12109
- );
12110
- const latestWidth = clamp(
12111
- Math.max("latest".length, ...latestValues.map((value) => value.length)),
12112
- 6,
12113
- 14
12114
- );
12115
- const downloadsWidth = clamp(
12116
- Math.max("downloads".length, ...downloadValues.map((value) => value.length)),
12117
- "downloads".length,
12118
- 12
12119
- );
12120
- const separatorWidth = 6;
12121
- const descriptionWidth = clamp(
12122
- terminalWidth - (skillWidth + latestWidth + downloadsWidth + separatorWidth),
12123
- 24,
12124
- 72
12125
- );
12126
- console.log(
12127
- `${"skill".padEnd(skillWidth)} ${"latest".padEnd(latestWidth)} ${"downloads".padStart(downloadsWidth)} description`
12128
- );
12129
- console.log(
12130
- `${"-".repeat(skillWidth)} ${"-".repeat(latestWidth)} ${"-".repeat(downloadsWidth)} ${"-".repeat(descriptionWidth)}`
12131
- );
12132
- for (const skill of skills) {
12496
+ const descriptionWidth = clamp(terminalWidth - 4, 36, 96);
12497
+ skills.forEach((skill, index) => {
12133
12498
  const skillRef = `${skill.namespace}/${skill.name}`;
12134
12499
  const latest = skill.latestVersion ?? "none";
12135
12500
  const downloads = skill.downloadCount.toLocaleString("en-US");
12136
12501
  const description = truncateText(skill.description, descriptionWidth);
12137
- console.log(
12138
- `${truncateText(skillRef, skillWidth).padEnd(skillWidth)} ${truncateText(latest, latestWidth).padEnd(latestWidth)} ${truncateText(downloads, downloadsWidth).padStart(downloadsWidth)} ${description}`
12139
- );
12140
- }
12502
+ console.log(skillRef);
12503
+ console.log(` ${latest} | ${downloads} downloads`);
12504
+ console.log(` ${description}`);
12505
+ if (index < skills.length - 1) {
12506
+ console.log("");
12507
+ }
12508
+ });
12141
12509
  }
12142
12510
  function truncateText(value, maxLength) {
12143
12511
  const normalized = value.replace(/\s+/g, " ").trim();
@@ -12152,24 +12520,66 @@ function truncateText(value, maxLength) {
12152
12520
  function clamp(value, min, max) {
12153
12521
  return Math.min(Math.max(value, min), max);
12154
12522
  }
12155
- function groupManifestEntriesBySource(entries) {
12156
- const grouped = /* @__PURE__ */ new Map();
12157
- for (const entry of entries) {
12158
- const sourcePath = entry.sourceInstallPath ?? entry.installPath;
12159
- const key = [
12160
- entry.registryBaseUrl,
12161
- entry.namespace,
12162
- entry.name,
12163
- sourcePath
12164
- ].join("::");
12165
- const group = grouped.get(key);
12166
- if (group) {
12167
- group.push(entry);
12168
- } else {
12169
- grouped.set(key, [entry]);
12523
+ async function maybeRunAutoUpdate(actionCommand) {
12524
+ if (isAutoUpdateDisabledByEnv() || shouldSkipAutoUpdate(actionCommand)) {
12525
+ return;
12526
+ }
12527
+ const config = await loadConfig();
12528
+ if (!shouldRunAutoUpdateNow(config)) {
12529
+ return;
12530
+ }
12531
+ const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
12532
+ try {
12533
+ const result = await runCliSelfUpdate({
12534
+ packageName: CLI_PACKAGE_NAME,
12535
+ currentVersion: CLI_VERSION,
12536
+ preferredPackageManager: resolvePreferredPackageManager(import_node_process2.default.env)
12537
+ });
12538
+ if (result.updated) {
12539
+ console.log(
12540
+ `[auto-update] Updated skillz CLI to ${result.latestVersion} using ${result.manager}.`
12541
+ );
12542
+ console.log("[auto-update] Re-run your command to use the new version.");
12543
+ }
12544
+ } catch (error) {
12545
+ const message = error instanceof Error ? error.message : String(error);
12546
+ console.warn(`Auto-update check failed: ${message}`);
12547
+ } finally {
12548
+ await saveConfig({
12549
+ ...config,
12550
+ autoUpdateLastCheckedAt: checkedAt
12551
+ });
12552
+ }
12553
+ }
12554
+ function shouldSkipAutoUpdate(command) {
12555
+ const blocked = /* @__PURE__ */ new Set([
12556
+ "auto-update",
12557
+ "help",
12558
+ "login",
12559
+ "logout",
12560
+ "register",
12561
+ "self-update",
12562
+ "update",
12563
+ "version"
12564
+ ]);
12565
+ const commandPath = resolveCommandPath(command);
12566
+ return commandPath.some((name) => blocked.has(name));
12567
+ }
12568
+ function resolveCommandPath(command) {
12569
+ const pathParts = [];
12570
+ let cursor = command;
12571
+ while (cursor && cursor.parent) {
12572
+ const name = cursor.name();
12573
+ if (name) {
12574
+ pathParts.push(name);
12170
12575
  }
12576
+ cursor = cursor.parent;
12171
12577
  }
12172
- return Array.from(grouped.values());
12578
+ return pathParts.reverse();
12579
+ }
12580
+ function isAutoUpdateDisabledByEnv() {
12581
+ const rawValue = import_node_process2.default.env.SKILLZ_AUTO_UPDATE?.trim().toLowerCase();
12582
+ return rawValue === "0" || rawValue === "false" || rawValue === "off" || rawValue === "no";
12173
12583
  }
12174
12584
  /*! Bundled license information:
12175
12585