@rayul/kordis 0.1.6 → 0.1.8

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.js CHANGED
@@ -253,7 +253,7 @@ var init_package = __esm({
253
253
  });
254
254
  PackageFrontmatterSchema = z6.object({
255
255
  title: z6.string().min(1).max(200),
256
- description: z6.string().min(1).max(500),
256
+ description: z6.string().min(1).max(2048),
257
257
  type: HarnessTypeSchema,
258
258
  tools: z6.array(ToolSlugSchema).optional().default([]),
259
259
  tags: z6.array(TagSchema).max(16).optional().default([]),
@@ -509,7 +509,7 @@ var init_api = __esm({
509
509
  * server-side; existing frontmatter wins if both present.
510
510
  */
511
511
  title: z9.string().min(1).max(200).optional(),
512
- description: z9.string().min(1).max(500).optional(),
512
+ description: z9.string().min(1).max(2048).optional(),
513
513
  type: HarnessTypeSchema.optional(),
514
514
  slug: SlugSchema.optional(),
515
515
  /**
@@ -965,6 +965,7 @@ import { Command as Command12 } from "commander";
965
965
 
966
966
  // src/commands/login.ts
967
967
  import { Command } from "commander";
968
+ import open from "open";
968
969
 
969
970
  // src/client.ts
970
971
  init_src2();
@@ -1150,7 +1151,7 @@ var c = kleur;
1150
1151
 
1151
1152
  // src/commands/login.ts
1152
1153
  function loginCommand() {
1153
- return new Command("login").description("authenticate with the Kordis registry").option("--provider <name>", "OAuth provider", "discord").action(async (opts) => {
1154
+ return new Command("login").description("authenticate with the Kordis registry").option("--provider <name>", "OAuth provider", "discord").option("--no-browser", "don't auto-open the browser; print the URL instead").action(async (opts) => {
1154
1155
  const bundle = await useClient();
1155
1156
  const started = spinner("Requesting device code");
1156
1157
  const device = await bundle.api.startDeviceFlow(
@@ -1158,11 +1159,23 @@ function loginCommand() {
1158
1159
  );
1159
1160
  started.succeed();
1160
1161
  printHuman("");
1161
- printHuman(c.bold("To continue, open this URL in a browser:"));
1162
- printHuman(" " + c.cyan(device.verification_url));
1163
- printHuman(c.bold("And confirm the code:"));
1162
+ printHuman(c.bold("Confirm the code in your browser:"));
1164
1163
  printHuman(" " + c.yellow(device.user_code));
1165
1164
  printHuman("");
1165
+ printHuman(c.gray("Verification URL:"));
1166
+ printHuman(" " + c.cyan(device.verification_url));
1167
+ printHuman("");
1168
+ if (opts.browser !== false) {
1169
+ try {
1170
+ await open(device.verification_url);
1171
+ printHuman(c.gray("Opened in your default browser."));
1172
+ } catch {
1173
+ printHuman(
1174
+ c.gray("Couldn't open the browser automatically \u2014 paste the URL above manually.")
1175
+ );
1176
+ }
1177
+ printHuman("");
1178
+ }
1166
1179
  const poll = spinner("Waiting for browser confirmation");
1167
1180
  const start = Date.now();
1168
1181
  const deadline = start + device.expires_in * 1e3;
@@ -1310,19 +1323,101 @@ function searchCommand() {
1310
1323
  import { Command as Command4 } from "commander";
1311
1324
  import { readFile as readFile3 } from "fs/promises";
1312
1325
  import { resolve } from "path";
1326
+
1327
+ // ../../packages/harness-schema/src/parser.ts
1328
+ import { parse as parseYaml } from "yaml";
1329
+ var FRONTMATTER_FENCE_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
1330
+ function parseFrontmatter(source) {
1331
+ const stripped = source.replace(/^\uFEFF/, "");
1332
+ const match = FRONTMATTER_FENCE_RE.exec(stripped);
1333
+ if (!match) {
1334
+ return { frontmatter: null, body: stripped, bodyOffset: 0 };
1335
+ }
1336
+ const raw = match[1] ?? "";
1337
+ let parsed;
1338
+ try {
1339
+ parsed = parseYaml(raw);
1340
+ } catch (err) {
1341
+ throw new FrontmatterParseError(
1342
+ `YAML frontmatter is malformed: ${err.message}`,
1343
+ { cause: err }
1344
+ );
1345
+ }
1346
+ if (parsed === null || parsed === void 0) {
1347
+ return { frontmatter: {}, body: stripped.slice(match[0].length), bodyOffset: match[0].length };
1348
+ }
1349
+ if (typeof parsed !== "object" || Array.isArray(parsed)) {
1350
+ throw new FrontmatterParseError(
1351
+ "YAML frontmatter must decode to an object, got " + typeof parsed
1352
+ );
1353
+ }
1354
+ return {
1355
+ frontmatter: parsed,
1356
+ body: stripped.slice(match[0].length),
1357
+ bodyOffset: match[0].length
1358
+ };
1359
+ }
1360
+ var FrontmatterParseError = class extends Error {
1361
+ constructor(message, options) {
1362
+ super(message, options);
1363
+ this.name = "FrontmatterParseError";
1364
+ }
1365
+ };
1366
+
1367
+ // src/commands/push.ts
1313
1368
  function pushCommand() {
1314
- return new Command4("push").description("publish a new package or a new version").argument("<file>", "path to the canonical package source").option("--bump <strategy>", "patch|minor|major (update only)", "patch").option("--slug <slug>", "override slug (for first publish)").option("--type <type>", "override type inference").option("--changelog <text>", "optional changelog entry").option("--dry-run", "validate only; do not publish").option("--no-wait", "return immediately without waiting for review").action(
1369
+ return new Command4("push").description("publish a new package or a new version").argument("<file>", "path to the canonical package source").option("--bump <strategy>", "patch|minor|major (update only)", "patch").option(
1370
+ "--slug <slug>",
1371
+ 'override slug; accepts "user/slug" to point at a specific package'
1372
+ ).option("--type <type>", "override type inference").option("--changelog <text>", "optional changelog entry").option("--dry-run", "validate only; do not publish").option("--no-wait", "return immediately without waiting for review").action(
1315
1373
  async (file, opts) => {
1316
1374
  const bundle = await useClient();
1317
1375
  const abs = resolve(process.cwd(), file);
1318
1376
  const content = await readFile3(abs, "utf8");
1319
- const spin = spinner(opts.dryRun ? "Validating" : "Publishing");
1377
+ let targetUser = null;
1378
+ let targetSlug = null;
1379
+ if (opts.slug && opts.slug.includes("/")) {
1380
+ const [u, s] = opts.slug.split("/", 2);
1381
+ if (u && s) {
1382
+ targetUser = u;
1383
+ targetSlug = s;
1384
+ }
1385
+ } else {
1386
+ let nameFromFm = null;
1387
+ try {
1388
+ const fm = parseFrontmatter(content).frontmatter ?? {};
1389
+ const v = fm["name"];
1390
+ if (typeof v === "string") nameFromFm = v;
1391
+ } catch {
1392
+ }
1393
+ if (bundle.username && (opts.slug || nameFromFm)) {
1394
+ targetUser = bundle.username;
1395
+ targetSlug = opts.slug ?? nameFromFm;
1396
+ }
1397
+ }
1398
+ let targetFullSlug;
1399
+ if (targetUser && targetSlug) {
1400
+ try {
1401
+ await bundle.api.getPackage(targetUser, targetSlug);
1402
+ targetFullSlug = `${targetUser}/${targetSlug}`;
1403
+ } catch (err) {
1404
+ if (err instanceof KordisApiError && err.code === "not_found") {
1405
+ targetFullSlug = void 0;
1406
+ } else if (!(err instanceof KordisApiError)) {
1407
+ throw err;
1408
+ }
1409
+ }
1410
+ }
1411
+ const spin = spinner(
1412
+ opts.dryRun ? "Validating" : targetFullSlug ? `Publishing update to ${targetFullSlug}` : "Publishing"
1413
+ );
1320
1414
  const res = await bundle.authedRequest(
1321
1415
  (api) => api.publish(
1322
1416
  {
1323
1417
  content,
1324
1418
  bump: opts.bump,
1325
- slug: opts.slug,
1419
+ slug: opts.slug && !opts.slug.includes("/") ? opts.slug : void 0,
1420
+ target_full_slug: targetFullSlug,
1326
1421
  type: opts.type,
1327
1422
  changelog: opts.changelog,
1328
1423
  dry_run: !!opts.dryRun
@@ -1357,46 +1452,6 @@ import { Command as Command5 } from "commander";
1357
1452
  import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
1358
1453
  import { dirname as dirname2, join as join4 } from "path";
1359
1454
 
1360
- // ../../packages/harness-schema/src/parser.ts
1361
- import { parse as parseYaml } from "yaml";
1362
- var FRONTMATTER_FENCE_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
1363
- function parseFrontmatter(source) {
1364
- const stripped = source.replace(/^\uFEFF/, "");
1365
- const match = FRONTMATTER_FENCE_RE.exec(stripped);
1366
- if (!match) {
1367
- return { frontmatter: null, body: stripped, bodyOffset: 0 };
1368
- }
1369
- const raw = match[1] ?? "";
1370
- let parsed;
1371
- try {
1372
- parsed = parseYaml(raw);
1373
- } catch (err) {
1374
- throw new FrontmatterParseError(
1375
- `YAML frontmatter is malformed: ${err.message}`,
1376
- { cause: err }
1377
- );
1378
- }
1379
- if (parsed === null || parsed === void 0) {
1380
- return { frontmatter: {}, body: stripped.slice(match[0].length), bodyOffset: match[0].length };
1381
- }
1382
- if (typeof parsed !== "object" || Array.isArray(parsed)) {
1383
- throw new FrontmatterParseError(
1384
- "YAML frontmatter must decode to an object, got " + typeof parsed
1385
- );
1386
- }
1387
- return {
1388
- frontmatter: parsed,
1389
- body: stripped.slice(match[0].length),
1390
- bodyOffset: match[0].length
1391
- };
1392
- }
1393
- var FrontmatterParseError = class extends Error {
1394
- constructor(message, options) {
1395
- super(message, options);
1396
- this.name = "FrontmatterParseError";
1397
- }
1398
- };
1399
-
1400
1455
  // ../../packages/harness-schema/src/deps.ts
1401
1456
  init_src();
1402
1457
  import { z as z10 } from "zod";
@@ -1440,7 +1495,7 @@ init_src();
1440
1495
  import { z as z11 } from "zod";
1441
1496
  var SkillFrontmatterSchema = z11.object({
1442
1497
  name: z11.string().min(1).max(64).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, "name must be lowercase-with-hyphens (Agent Skills spec)"),
1443
- description: z11.string().min(1).max(500),
1498
+ description: z11.string().min(1).max(2048),
1444
1499
  version: SemverSchema.optional(),
1445
1500
  // Agent Skills optional metadata
1446
1501
  license: z11.string().max(64).optional(),
@@ -1478,7 +1533,7 @@ var McpCapabilitiesSchema = z12.object({
1478
1533
  });
1479
1534
  var McpServerFrontmatterSchema = z12.object({
1480
1535
  name: z12.string().min(1).max(64).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/),
1481
- description: z12.string().min(1).max(500),
1536
+ description: z12.string().min(1).max(2048),
1482
1537
  version: SemverSchema,
1483
1538
  mcp_spec_version: z12.string().default("2026-03"),
1484
1539
  transport: McpTransportSchema,
@@ -1508,7 +1563,7 @@ init_src();
1508
1563
  import { z as z13 } from "zod";
1509
1564
  var ProjectRulesFrontmatterSchema = z13.object({
1510
1565
  title: z13.string().min(1).max(200),
1511
- description: z13.string().min(1).max(500),
1566
+ description: z13.string().min(1).max(2048),
1512
1567
  version: SemverSchema.optional(),
1513
1568
  scope: z13.enum(["root", "nested", "globs"]).default("root"),
1514
1569
  target_path: z13.string().optional(),
@@ -1530,7 +1585,7 @@ init_src();
1530
1585
  import { z as z14 } from "zod";
1531
1586
  var CustomAgentFrontmatterSchema = z14.object({
1532
1587
  name: z14.string().min(1).max(64).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/),
1533
- description: z14.string().min(1).max(500),
1588
+ description: z14.string().min(1).max(2048),
1534
1589
  title: z14.string().min(1).max(200).optional(),
1535
1590
  version: SemverSchema.optional(),
1536
1591
  /** System prompt that defines the agent's persona + rules. Required. */
@@ -1588,7 +1643,7 @@ var HookBindingSchema = z15.object({
1588
1643
  });
1589
1644
  var HookFrontmatterSchema = z15.object({
1590
1645
  name: z15.string().min(1).max(64).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/),
1591
- description: z15.string().min(1).max(500),
1646
+ description: z15.string().min(1).max(2048),
1592
1647
  title: z15.string().min(1).max(200).optional(),
1593
1648
  version: SemverSchema.optional(),
1594
1649
  /** One or more hook bindings. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rayul/kordis",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
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",
@@ -13,6 +13,7 @@
13
13
  "bin",
14
14
  "dist",
15
15
  "assets",
16
+ "scripts",
16
17
  "README.md"
17
18
  ],
18
19
  "scripts": {
@@ -20,12 +21,13 @@
20
21
  "build": "tsup && rm -rf assets && mkdir -p assets && cp -R ../../packages/skills/. assets/",
21
22
  "typecheck": "tsc --noEmit",
22
23
  "test": "vitest run",
23
- "postinstall": "node ./bin/kordis.js setup --silent"
24
+ "postinstall": "node scripts/postinstall.mjs"
24
25
  },
25
26
  "dependencies": {
26
27
  "@iarna/toml": "^2.2.5",
27
28
  "commander": "^12.1.0",
28
29
  "kleur": "^4.1.5",
30
+ "open": "^10.1.0",
29
31
  "ora": "^8.1.1",
30
32
  "prompts": "^2.4.2",
31
33
  "yaml": "^2.6.0",
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ // Run `kordis setup --silent` only when the CLI is fully built.
3
+ //
4
+ // On end-user installs from the npm tarball, `dist/index.js` is shipped, so
5
+ // setup runs and registers the agent guides. On a fresh `pnpm install` in
6
+ // this monorepo (CI or local dev) the build step hasn't run yet, so dist is
7
+ // missing — bail out silently. Setup is meaningless without a built CLI.
8
+ import { existsSync } from 'node:fs';
9
+ import { spawnSync } from 'node:child_process';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { dirname, join } from 'node:path';
12
+
13
+ const here = dirname(fileURLToPath(import.meta.url));
14
+ const distEntry = join(here, '..', 'dist', 'index.js');
15
+ if (!existsSync(distEntry)) process.exit(0);
16
+
17
+ const r = spawnSync(
18
+ process.execPath,
19
+ [join(here, '..', 'bin', 'kordis.js'), 'setup', '--silent'],
20
+ { stdio: 'inherit' },
21
+ );
22
+ process.exit(r.status ?? 0);