@rayul/kordis 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.
Files changed (2) hide show
  1. package/dist/index.js +89 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -984,7 +984,7 @@ var init_src2 = __esm({
984
984
 
985
985
  // src/index.ts
986
986
  init_src2();
987
- import { Command as Command17 } from "commander";
987
+ import { Command as Command18 } from "commander";
988
988
 
989
989
  // src/commands/login.ts
990
990
  import { Command } from "commander";
@@ -2454,13 +2454,16 @@ async function recordInstalled(fullSlug, entry) {
2454
2454
  }
2455
2455
 
2456
2456
  // src/commands/pull.ts
2457
- async function doPullInstall(fullSlug, tool, installRoot) {
2457
+ async function doPullInstall(fullSlug, tool, installRoot, version) {
2458
2458
  const [username, slug] = fullSlug.split("/");
2459
2459
  if (!username || !slug) throw new Error('full_slug must be "{username}/{slug}"');
2460
2460
  const bundle = await useClient();
2461
2461
  const detail = await bundle.api.getPackage(username, slug);
2462
2462
  await bundle.api.pull(username, slug);
2463
- const contentRes = await bundle.api.getContent(username, slug, { format: "canonical" });
2463
+ const contentRes = await bundle.api.getContent(username, slug, {
2464
+ format: "canonical",
2465
+ ...version ? { version } : {}
2466
+ });
2464
2467
  const parsed = validatePackageSource(contentRes.content);
2465
2468
  if (!parsed.ok || !parsed.type || !parsed.frontmatter) {
2466
2469
  throw new Error("package stored content is not currently valid");
@@ -2507,20 +2510,25 @@ async function doPullInstall(fullSlug, tool, installRoot) {
2507
2510
  throw err;
2508
2511
  }
2509
2512
  }
2513
+ const installedVersion = contentRes.version;
2510
2514
  await recordInstalled(fullSlug, {
2511
- version: detail.current_version,
2515
+ version: installedVersion,
2512
2516
  tool,
2513
2517
  target: installRoot,
2514
2518
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
2515
2519
  });
2516
- return { version: detail.current_version, tool, installRoot, written, notes };
2520
+ return { version: installedVersion, tool, installRoot, written, notes };
2517
2521
  }
2518
2522
  function pullCommand() {
2519
- return new Command5("pull").description("install a package into the current project").argument("<full_slug>", "package identifier {username}/{slug}").option("--tool <name>", "target tool format (default: auto-detect)").option("--target <path>", "install into a subdirectory (default: cwd)").option("--with-recommends", "also install recommended dependencies", false).action(
2520
- async (fullSlug, opts) => {
2523
+ return new Command5("pull").description("install a package into the current project").argument("<full_slug>", "package identifier {username}/{slug} or {username}/{slug}@{version}").option("--tool <name>", "target tool format (default: auto-detect)").option("--target <path>", "install into a subdirectory (default: cwd)").option("--with-recommends", "also install recommended dependencies", false).action(
2524
+ async (fullSlugArg, opts) => {
2525
+ const atIdx = fullSlugArg.lastIndexOf("@");
2526
+ const hasPinnedVersion = atIdx > fullSlugArg.indexOf("/");
2527
+ const fullSlug = hasPinnedVersion ? fullSlugArg.slice(0, atIdx) : fullSlugArg;
2528
+ const pinnedVersion = hasPinnedVersion ? fullSlugArg.slice(atIdx + 1) : void 0;
2521
2529
  const [username, slug] = fullSlug.split("/");
2522
2530
  if (!username || !slug) {
2523
- throw new Error('full_slug must be "{username}/{slug}"');
2531
+ throw new Error('full_slug must be "{username}/{slug}" or "{username}/{slug}@{version}"');
2524
2532
  }
2525
2533
  const userCwd = process.env["INIT_CWD"] ?? process.cwd();
2526
2534
  const installRoot = opts.target ?? userCwd;
@@ -2530,8 +2538,9 @@ function pullCommand() {
2530
2538
  "Cannot detect target tool from the current directory.\n Pass --tool <name> explicitly. Valid: claude-code, codex, cursor,\n continue, windsurf, antigravity, copilot.\n Or run `kordis pull` inside a project that already has one of:\n .claude/, .codex/, .cursor/, AGENTS.md, CLAUDE.md, .cursorrules,\n .continue/, .windsurf/, .antigravity/, .github/copilot-instructions.md"
2531
2539
  );
2532
2540
  }
2533
- const spin = spinner(`Pulling ${fullSlug}`);
2534
- const result = await doPullInstall(fullSlug, detected, installRoot);
2541
+ const spinLabel = pinnedVersion ? `Pulling ${fullSlug}@${pinnedVersion}` : `Pulling ${fullSlug}`;
2542
+ const spin = spinner(spinLabel);
2543
+ const result = await doPullInstall(fullSlug, detected, installRoot, pinnedVersion);
2535
2544
  spin.succeed();
2536
2545
  printDual({
2537
2546
  json: {
@@ -3313,9 +3322,77 @@ function updateCommand() {
3313
3322
  });
3314
3323
  }
3315
3324
 
3325
+ // src/commands/diff.ts
3326
+ import { Command as Command17 } from "commander";
3327
+ function diffCommand() {
3328
+ return new Command17("diff").description("show changes between two versions of a package").argument("<full_slug>", "package identifier: {username}/{slug}, or {username}/{slug}@{from}..{to}").argument("[from]", "older version (omit to use second-latest)").argument("[to]", "newer version (omit to use latest)").action(async (fullSlugArg, fromArg, toArg) => {
3329
+ let fullSlug = fullSlugArg;
3330
+ let from = fromArg;
3331
+ let to = toArg;
3332
+ const rangeMatch = /^(.+)@(.+?)\.\.(.+)$/.exec(fullSlugArg);
3333
+ if (rangeMatch) {
3334
+ fullSlug = rangeMatch[1];
3335
+ from = rangeMatch[2];
3336
+ to = rangeMatch[3];
3337
+ }
3338
+ const [username, slug] = fullSlug.split("/");
3339
+ if (!username || !slug) {
3340
+ throw new Error('full_slug must be "{username}/{slug}"');
3341
+ }
3342
+ const bundle = await useClient();
3343
+ if (!from || !to) {
3344
+ const spin2 = spinner(`Fetching versions for ${fullSlug}`);
3345
+ const versionsRes = await bundle.api.versions(username, slug);
3346
+ spin2.stop();
3347
+ const passed = versionsRes.versions.filter((v) => v.review_status === "passed");
3348
+ if (passed.length < 2) {
3349
+ throw new Error(
3350
+ `Need at least 2 published versions to auto-diff. Pass explicit versions: kordis diff ${fullSlug} <from> <to>`
3351
+ );
3352
+ }
3353
+ to = to ?? passed[0].version;
3354
+ from = from ?? passed[1].version;
3355
+ }
3356
+ const spin = spinner(`Diffing ${fullSlug} ${from}..${to}`);
3357
+ const diff = await bundle.api.diff(username, slug, from, to);
3358
+ spin.succeed();
3359
+ printDual({
3360
+ json: diff,
3361
+ human: () => {
3362
+ printHuman(
3363
+ `${c.bold(diff.full_slug)} ${c.gray(diff.from)} ${c.dim("\u2192")} ${c.green(diff.to)}`
3364
+ );
3365
+ printHuman(
3366
+ c.gray(
3367
+ ` +${diff.stats.additions} \u2212${diff.stats.deletions} (${diff.stats.files_changed} file${diff.stats.files_changed !== 1 ? "s" : ""} changed)`
3368
+ )
3369
+ );
3370
+ printHuman("");
3371
+ if (!diff.unified_diff) {
3372
+ printHuman(c.dim("(no content changes between these versions)"));
3373
+ return;
3374
+ }
3375
+ for (const line of diff.unified_diff.split("\n")) {
3376
+ if (line.startsWith("+++") || line.startsWith("---")) {
3377
+ printHuman(c.bold(line));
3378
+ } else if (line.startsWith("+")) {
3379
+ printHuman(c.green(line));
3380
+ } else if (line.startsWith("-")) {
3381
+ printHuman(c.red(line));
3382
+ } else if (line.startsWith("@@")) {
3383
+ printHuman(c.cyan(line));
3384
+ } else {
3385
+ printHuman(c.gray(line));
3386
+ }
3387
+ }
3388
+ }
3389
+ });
3390
+ });
3391
+ }
3392
+
3316
3393
  // src/index.ts
3317
3394
  function buildProgram() {
3318
- const program = new Command17("kordis").version(VERSION).description("Kordis \u2014 registry for agentic-coding packages").option("--json", "emit JSON output to stdout (default: human)", false).hook("preAction", (thisCommand) => {
3395
+ const program = new Command18("kordis").version(VERSION).description("Kordis \u2014 registry for agentic-coding packages").option("--json", "emit JSON output to stdout (default: human)", false).hook("preAction", (thisCommand) => {
3319
3396
  const opts = thisCommand.optsWithGlobals();
3320
3397
  if (opts.json) setJsonMode(true);
3321
3398
  });
@@ -3335,6 +3412,7 @@ function buildProgram() {
3335
3412
  program.addCommand(versionsCommand());
3336
3413
  program.addCommand(outdatedCommand());
3337
3414
  program.addCommand(updateCommand());
3415
+ program.addCommand(diffCommand());
3338
3416
  program.addCommand(setupCommand());
3339
3417
  return program;
3340
3418
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rayul/kordis",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "private": false,
5
5
  "description": "Command-line client for the Kordis registry — discover, install, and publish agentic-coding packages.",
6
6
  "license": "MIT",