@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 +109 -54
- package/package.json +4 -2
- package/scripts/postinstall.mjs +22 -0
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(
|
|
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(
|
|
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("
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
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
|
|
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);
|