@rayul/kordis 0.1.17 → 0.2.0
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 +175 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ var init_primitives = __esm({
|
|
|
45
45
|
|
|
46
46
|
// ../../packages/contracts/src/enums.ts
|
|
47
47
|
import { z as z2 } from "zod";
|
|
48
|
-
var HarnessTypeSchema, PHASE_1_TYPES, TierSchema, TIER_OF_TYPE, SortModeSchema, TimeWindowSchema, VisibilitySchema, ReviewStatusSchema, PublishStatusSchema, DependencyKindSchema, OAuthProviderSchema, UserRoleSchema, ReportReasonSchema;
|
|
48
|
+
var HarnessTypeSchema, PHASE_1_TYPES, TierSchema, TIER_OF_TYPE, CAPABILITIES_OF_TYPE, SortModeSchema, TimeWindowSchema, VisibilitySchema, ReviewStatusSchema, PublishStatusSchema, DependencyKindSchema, OAuthProviderSchema, UserRoleSchema, ReportReasonSchema;
|
|
49
49
|
var init_enums = __esm({
|
|
50
50
|
"../../packages/contracts/src/enums.ts"() {
|
|
51
51
|
"use strict";
|
|
@@ -77,6 +77,16 @@ var init_enums = __esm({
|
|
|
77
77
|
"mdc-rule": "C",
|
|
78
78
|
plugin: "D"
|
|
79
79
|
};
|
|
80
|
+
CAPABILITIES_OF_TYPE = {
|
|
81
|
+
skill: { jit_eligible: true, executable: false },
|
|
82
|
+
"project-rules": { jit_eligible: true, executable: false },
|
|
83
|
+
"custom-agent": { jit_eligible: true, executable: false },
|
|
84
|
+
"scoped-rule": { jit_eligible: true, executable: false },
|
|
85
|
+
"mdc-rule": { jit_eligible: true, executable: false },
|
|
86
|
+
"mcp-server": { jit_eligible: false, executable: true },
|
|
87
|
+
hook: { jit_eligible: false, executable: true },
|
|
88
|
+
plugin: { jit_eligible: false, executable: true }
|
|
89
|
+
};
|
|
80
90
|
SortModeSchema = z2.enum([
|
|
81
91
|
"stars",
|
|
82
92
|
"downloads",
|
|
@@ -281,6 +291,14 @@ var init_package = __esm({
|
|
|
281
291
|
tools_compatible: z6.array(ToolSlugSchema),
|
|
282
292
|
tags: z6.array(TagSchema),
|
|
283
293
|
agent_skills_compliant: z6.boolean().optional(),
|
|
294
|
+
/**
|
|
295
|
+
* Capability flags — explicit declaration of behavior. Defaults derive from
|
|
296
|
+
* `type` via `CAPABILITIES_OF_TYPE`; frontmatter MAY override. Optional in
|
|
297
|
+
* the schema so old API responses (pre-0.2.0) parse cleanly; consumers that
|
|
298
|
+
* need a value should fall back to `CAPABILITIES_OF_TYPE[type]`.
|
|
299
|
+
*/
|
|
300
|
+
jit_eligible: z6.boolean().optional(),
|
|
301
|
+
executable: z6.boolean().optional(),
|
|
284
302
|
review_status: ReviewStatusSchema,
|
|
285
303
|
visibility: VisibilitySchema,
|
|
286
304
|
installed_locally: z6.boolean().optional(),
|
|
@@ -1374,18 +1392,21 @@ function parseFrontmatter(source) {
|
|
|
1374
1392
|
parsed = parseYaml(raw);
|
|
1375
1393
|
} catch (err) {
|
|
1376
1394
|
const msg = err.message;
|
|
1377
|
-
const hint = msg.includes("Nested mapping") || msg.includes("compact mapping") ? '
|
|
1378
|
-
throw new FrontmatterParseError(
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
);
|
|
1395
|
+
const hint = msg.includes("Nested mapping") || msg.includes("compact mapping") ? 'If the value contains ":" wrap it in quotes, e.g. description: "Use when X. Trigger: Y"' : 'Frontmatter must be valid YAML between two "---" fences. Validate at https://yamllint.com';
|
|
1396
|
+
throw new FrontmatterParseError(`YAML frontmatter is malformed: ${msg}`, {
|
|
1397
|
+
cause: err,
|
|
1398
|
+
hint
|
|
1399
|
+
});
|
|
1382
1400
|
}
|
|
1383
1401
|
if (parsed === null || parsed === void 0) {
|
|
1384
1402
|
return { frontmatter: {}, body: stripped.slice(match[0].length), bodyOffset: match[0].length };
|
|
1385
1403
|
}
|
|
1386
1404
|
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1387
1405
|
throw new FrontmatterParseError(
|
|
1388
|
-
"YAML frontmatter must decode to an object, got " + typeof parsed
|
|
1406
|
+
"YAML frontmatter must decode to an object, got " + typeof parsed,
|
|
1407
|
+
{
|
|
1408
|
+
hint: "Frontmatter must be a YAML mapping (key: value pairs), not a list or scalar."
|
|
1409
|
+
}
|
|
1389
1410
|
);
|
|
1390
1411
|
}
|
|
1391
1412
|
return {
|
|
@@ -1395,9 +1416,12 @@ function parseFrontmatter(source) {
|
|
|
1395
1416
|
};
|
|
1396
1417
|
}
|
|
1397
1418
|
var FrontmatterParseError = class extends Error {
|
|
1419
|
+
/** Agent-actionable fix snippet, ready to render under the error. */
|
|
1420
|
+
hint;
|
|
1398
1421
|
constructor(message, options) {
|
|
1399
1422
|
super(message, options);
|
|
1400
1423
|
this.name = "FrontmatterParseError";
|
|
1424
|
+
if (options?.hint) this.hint = options.hint;
|
|
1401
1425
|
}
|
|
1402
1426
|
};
|
|
1403
1427
|
|
|
@@ -1428,7 +1452,7 @@ function pushCommand() {
|
|
|
1428
1452
|
const v = fm["name"];
|
|
1429
1453
|
if (typeof v === "string") nameFromFm = v;
|
|
1430
1454
|
} catch (err) {
|
|
1431
|
-
throw new Error(err
|
|
1455
|
+
throw err instanceof Error ? err : new Error(String(err));
|
|
1432
1456
|
}
|
|
1433
1457
|
let targetUser = null;
|
|
1434
1458
|
let targetSlug = null;
|
|
@@ -1820,37 +1844,43 @@ function validatePackageSource(source) {
|
|
|
1820
1844
|
rawFrontmatter = parsed.frontmatter;
|
|
1821
1845
|
} catch (err) {
|
|
1822
1846
|
if (err instanceof FrontmatterParseError) {
|
|
1823
|
-
|
|
1847
|
+
const extra = err.hint ? { hint: err.hint } : {};
|
|
1848
|
+
return earlyExit(flag("malformed_frontmatter", err.message, extra));
|
|
1824
1849
|
}
|
|
1825
1850
|
throw err;
|
|
1826
1851
|
}
|
|
1827
1852
|
if (!rawFrontmatter) {
|
|
1828
|
-
return earlyExit(
|
|
1853
|
+
return earlyExit(
|
|
1854
|
+
flag("missing_frontmatter", "package must start with a YAML frontmatter block", {
|
|
1855
|
+
hint: "Add a YAML block at the top:\n---\ntype: skill\nname: my-skill\ndescription: ...\n---"
|
|
1856
|
+
})
|
|
1857
|
+
);
|
|
1829
1858
|
}
|
|
1830
1859
|
const typeValue = rawFrontmatter["type"];
|
|
1831
1860
|
if (typeof typeValue !== "string") {
|
|
1832
1861
|
return earlyExit(
|
|
1833
|
-
flag("missing_required_frontmatter", "`type` is required in frontmatter", {
|
|
1862
|
+
flag("missing_required_frontmatter", "`type` is required in frontmatter", {
|
|
1863
|
+
field: "type",
|
|
1864
|
+
hint: "Add type: skill (or one of: mcp-server, project-rules, custom-agent, hook)"
|
|
1865
|
+
})
|
|
1834
1866
|
);
|
|
1835
1867
|
}
|
|
1836
1868
|
const typeParse = HarnessTypeSchema.safeParse(typeValue);
|
|
1837
1869
|
if (!typeParse.success) {
|
|
1838
1870
|
return earlyExit(
|
|
1839
|
-
flag(
|
|
1840
|
-
"
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
)
|
|
1871
|
+
flag("unknown_type", `type "${typeValue}" is not a recognised Harness type`, {
|
|
1872
|
+
field: "type",
|
|
1873
|
+
hint: "Allowed types: skill, mcp-server, project-rules, custom-agent, hook"
|
|
1874
|
+
})
|
|
1844
1875
|
);
|
|
1845
1876
|
}
|
|
1846
1877
|
const type = typeParse.data;
|
|
1847
1878
|
if (!PHASE_1_TYPES.includes(type)) {
|
|
1848
1879
|
flags.push(
|
|
1849
|
-
flag(
|
|
1850
|
-
"
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
)
|
|
1880
|
+
flag("type_not_phase1", `type "${type}" is planned for Phase 2+ and is not yet accepted`, {
|
|
1881
|
+
field: "type",
|
|
1882
|
+
hint: "Use one of the Phase 1 types: skill, mcp-server, project-rules, custom-agent, hook"
|
|
1883
|
+
})
|
|
1854
1884
|
);
|
|
1855
1885
|
return earlyExit(null, { flags, body });
|
|
1856
1886
|
}
|
|
@@ -1858,22 +1888,69 @@ function validatePackageSource(source) {
|
|
|
1858
1888
|
type: _discard_type,
|
|
1859
1889
|
depends: _discard_depends,
|
|
1860
1890
|
recommends: _discard_recommends,
|
|
1891
|
+
jit_eligible: rawJitEligible,
|
|
1892
|
+
executable: rawExecutable,
|
|
1861
1893
|
...typeSpecific
|
|
1862
1894
|
} = rawFrontmatter;
|
|
1863
1895
|
void _discard_type;
|
|
1864
1896
|
void _discard_depends;
|
|
1865
1897
|
void _discard_recommends;
|
|
1898
|
+
let jitOverride;
|
|
1899
|
+
let execOverride;
|
|
1900
|
+
if (rawJitEligible !== void 0) {
|
|
1901
|
+
if (typeof rawJitEligible !== "boolean") {
|
|
1902
|
+
flags.push(
|
|
1903
|
+
flag(
|
|
1904
|
+
"invalid_frontmatter",
|
|
1905
|
+
"jit_eligible must be a boolean (true / false)",
|
|
1906
|
+
{
|
|
1907
|
+
field: "jit_eligible",
|
|
1908
|
+
hint: "Example: jit_eligible: true"
|
|
1909
|
+
}
|
|
1910
|
+
)
|
|
1911
|
+
);
|
|
1912
|
+
} else {
|
|
1913
|
+
jitOverride = rawJitEligible;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
if (rawExecutable !== void 0) {
|
|
1917
|
+
if (typeof rawExecutable !== "boolean") {
|
|
1918
|
+
flags.push(
|
|
1919
|
+
flag("invalid_frontmatter", "executable must be a boolean (true / false)", {
|
|
1920
|
+
field: "executable",
|
|
1921
|
+
hint: "Example: executable: false"
|
|
1922
|
+
})
|
|
1923
|
+
);
|
|
1924
|
+
} else {
|
|
1925
|
+
execOverride = rawExecutable;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1866
1928
|
const result = dispatchValidation(type, typeSpecific);
|
|
1867
1929
|
if (!result.ok) {
|
|
1868
1930
|
flags.push(...result.flags);
|
|
1869
1931
|
return earlyExit(null, { flags, body });
|
|
1870
1932
|
}
|
|
1933
|
+
const defaults = CAPABILITIES_OF_TYPE[type];
|
|
1934
|
+
const capabilities = {
|
|
1935
|
+
jit_eligible: jitOverride ?? defaults.jit_eligible,
|
|
1936
|
+
executable: execOverride ?? defaults.executable
|
|
1937
|
+
};
|
|
1871
1938
|
const common = {
|
|
1872
1939
|
title: typeof rawFrontmatter["title"] === "string" ? rawFrontmatter["title"] : typeof rawFrontmatter["name"] === "string" ? rawFrontmatter["name"] : null,
|
|
1873
1940
|
description: typeof rawFrontmatter["description"] === "string" ? rawFrontmatter["description"] : null
|
|
1874
1941
|
};
|
|
1875
|
-
if (!common.title)
|
|
1876
|
-
|
|
1942
|
+
if (!common.title)
|
|
1943
|
+
flags.push(
|
|
1944
|
+
flag("missing_title", "title (or name) is required", {
|
|
1945
|
+
hint: 'Add title: "Human Readable Title" (or rely on name: ... for skills)'
|
|
1946
|
+
})
|
|
1947
|
+
);
|
|
1948
|
+
if (!common.description)
|
|
1949
|
+
flags.push(
|
|
1950
|
+
flag("missing_description", "description is required", {
|
|
1951
|
+
hint: "Add a description field (1\u20132048 chars) explaining when to invoke this package."
|
|
1952
|
+
})
|
|
1953
|
+
);
|
|
1877
1954
|
let depends = [];
|
|
1878
1955
|
let recommends = [];
|
|
1879
1956
|
try {
|
|
@@ -1883,7 +1960,12 @@ function validatePackageSource(source) {
|
|
|
1883
1960
|
kind: DependencyKindSchema.parse("required")
|
|
1884
1961
|
}));
|
|
1885
1962
|
} catch (err) {
|
|
1886
|
-
flags.push(
|
|
1963
|
+
flags.push(
|
|
1964
|
+
flag("invalid_depends", err.message, {
|
|
1965
|
+
field: "depends",
|
|
1966
|
+
hint: 'Each entry must be "{username}/{slug}" optionally with "@^1.2.0". Example: alice/json-pretty@^1.0.0'
|
|
1967
|
+
})
|
|
1968
|
+
);
|
|
1887
1969
|
}
|
|
1888
1970
|
try {
|
|
1889
1971
|
recommends = normaliseDepList(rawFrontmatter["recommends"]).map((d) => ({
|
|
@@ -1892,13 +1974,26 @@ function validatePackageSource(source) {
|
|
|
1892
1974
|
kind: DependencyKindSchema.parse("recommended")
|
|
1893
1975
|
}));
|
|
1894
1976
|
} catch (err) {
|
|
1895
|
-
flags.push(
|
|
1977
|
+
flags.push(
|
|
1978
|
+
flag("invalid_recommends", err.message, {
|
|
1979
|
+
field: "recommends",
|
|
1980
|
+
hint: 'Each entry must be "{username}/{slug}" optionally with "@^1.2.0".'
|
|
1981
|
+
})
|
|
1982
|
+
);
|
|
1896
1983
|
}
|
|
1897
1984
|
if (body.trim().length < 50) {
|
|
1898
|
-
flags.push(
|
|
1985
|
+
flags.push(
|
|
1986
|
+
flag("content_too_short", "body must be at least 50 non-whitespace characters", {
|
|
1987
|
+
hint: 'Add an "## Instructions" section explaining when and how to use this package.'
|
|
1988
|
+
})
|
|
1989
|
+
);
|
|
1899
1990
|
}
|
|
1900
1991
|
if (body.length > 1e5) {
|
|
1901
|
-
flags.push(
|
|
1992
|
+
flags.push(
|
|
1993
|
+
flag("content_too_long", "body exceeds 100 kB cap", {
|
|
1994
|
+
hint: "Split long examples or transcripts into asset files under references/."
|
|
1995
|
+
})
|
|
1996
|
+
);
|
|
1902
1997
|
}
|
|
1903
1998
|
const ok = flags.every((f) => !BLOCKING_CODES.has(f.code));
|
|
1904
1999
|
return {
|
|
@@ -1908,6 +2003,7 @@ function validatePackageSource(source) {
|
|
|
1908
2003
|
frontmatter: result.frontmatter,
|
|
1909
2004
|
body,
|
|
1910
2005
|
common,
|
|
2006
|
+
capabilities,
|
|
1911
2007
|
depends,
|
|
1912
2008
|
recommends,
|
|
1913
2009
|
flags
|
|
@@ -1938,6 +2034,7 @@ function earlyExit(firstFlag, override = {}) {
|
|
|
1938
2034
|
frontmatter: null,
|
|
1939
2035
|
body: "",
|
|
1940
2036
|
common: { title: null, description: null },
|
|
2037
|
+
capabilities: null,
|
|
1941
2038
|
depends: [],
|
|
1942
2039
|
recommends: [],
|
|
1943
2040
|
flags: firstFlag ? [firstFlag] : [],
|
|
@@ -1976,7 +2073,10 @@ function dispatchValidation(type, raw) {
|
|
|
1976
2073
|
ok: false,
|
|
1977
2074
|
frontmatter: null,
|
|
1978
2075
|
flags: [
|
|
1979
|
-
flag("type_not_phase1", `type "${type}" not accepted in Phase 1`, {
|
|
2076
|
+
flag("type_not_phase1", `type "${type}" not accepted in Phase 1`, {
|
|
2077
|
+
field: "type",
|
|
2078
|
+
hint: "Use one of the Phase 1 types: skill, mcp-server, project-rules, custom-agent, hook"
|
|
2079
|
+
})
|
|
1980
2080
|
]
|
|
1981
2081
|
};
|
|
1982
2082
|
}
|
|
@@ -1985,9 +2085,22 @@ function zodFail(issues) {
|
|
|
1985
2085
|
return {
|
|
1986
2086
|
ok: false,
|
|
1987
2087
|
frontmatter: null,
|
|
1988
|
-
flags: issues.map(
|
|
1989
|
-
|
|
1990
|
-
|
|
2088
|
+
flags: issues.map((i) => {
|
|
2089
|
+
const field = i.path.join(".") || void 0;
|
|
2090
|
+
const msg = i.message.toLowerCase();
|
|
2091
|
+
let hint;
|
|
2092
|
+
if (field === "name" && msg.includes("lowercase")) {
|
|
2093
|
+
hint = 'name must be lowercase-with-hyphens, e.g. "my-cool-skill" not "MyCoolSkill"';
|
|
2094
|
+
} else if (field === "description" && (msg.includes("big") || msg.includes("large") || msg.includes("long"))) {
|
|
2095
|
+
hint = "description must be 1\u20132048 chars; current is too long. Move detail into the body.";
|
|
2096
|
+
} else if (field === "description" && msg.includes("small")) {
|
|
2097
|
+
hint = "description must be 1\u20132048 chars; provide a one-paragraph summary.";
|
|
2098
|
+
}
|
|
2099
|
+
const extra = {};
|
|
2100
|
+
if (field) extra.field = field;
|
|
2101
|
+
if (hint) extra.hint = hint;
|
|
2102
|
+
return flag("invalid_frontmatter", i.message, extra);
|
|
2103
|
+
})
|
|
1991
2104
|
};
|
|
1992
2105
|
}
|
|
1993
2106
|
|
|
@@ -2628,6 +2741,7 @@ function readCommand() {
|
|
|
2628
2741
|
}
|
|
2629
2742
|
|
|
2630
2743
|
// src/commands/info.ts
|
|
2744
|
+
init_src();
|
|
2631
2745
|
import { Command as Command7 } from "commander";
|
|
2632
2746
|
function infoCommand() {
|
|
2633
2747
|
return new Command7("info").description("show details about a package").argument("<full_slug>", "package identifier {username}/{slug}").action(async (fullSlug) => {
|
|
@@ -2635,6 +2749,9 @@ function infoCommand() {
|
|
|
2635
2749
|
if (!username || !slug) throw new Error('full_slug must be "{username}/{slug}"');
|
|
2636
2750
|
const bundle = await useClient();
|
|
2637
2751
|
const detail = await bundle.api.getPackage(username, slug);
|
|
2752
|
+
const typeDefaults = CAPABILITIES_OF_TYPE[detail.type];
|
|
2753
|
+
const jitEligible = detail.jit_eligible ?? typeDefaults.jit_eligible;
|
|
2754
|
+
const executable = detail.executable ?? typeDefaults.executable;
|
|
2638
2755
|
printDual({
|
|
2639
2756
|
json: detail,
|
|
2640
2757
|
human: () => {
|
|
@@ -2642,6 +2759,12 @@ function infoCommand() {
|
|
|
2642
2759
|
printHuman(" " + detail.description);
|
|
2643
2760
|
printHuman("");
|
|
2644
2761
|
printHuman(` ${c.cyan("Type")}: ${detail.type} (tier ${detail.tier})`);
|
|
2762
|
+
printHuman(
|
|
2763
|
+
` ${c.cyan("JIT-readable")}: ${jitEligible ? c.green("yes") : c.red("no")}`
|
|
2764
|
+
);
|
|
2765
|
+
printHuman(
|
|
2766
|
+
` ${c.cyan("Executable")}: ${executable ? c.yellow("yes") : c.gray("no")}`
|
|
2767
|
+
);
|
|
2645
2768
|
printHuman(` ${c.cyan("Author")}: ${detail.author.username}`);
|
|
2646
2769
|
printHuman(` ${c.cyan("Stats")}: \u2605 ${detail.stars} \xB7 \u21E3 ${detail.downloads}`);
|
|
2647
2770
|
if (detail.tools_compatible.length > 0) {
|
|
@@ -3441,6 +3564,11 @@ function handleError(err) {
|
|
|
3441
3564
|
printHuman(c.red(`\u2717 ${err.code}: ${err.message}`));
|
|
3442
3565
|
for (const f of err.flags) {
|
|
3443
3566
|
printHuman(c.red(` - ${f.code}${f.message ? `: ${f.message}` : ""}`));
|
|
3567
|
+
if (f.hint) {
|
|
3568
|
+
for (const line of f.hint.split("\n")) {
|
|
3569
|
+
printHuman(c.gray(` \u2192 ${line}`));
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3444
3572
|
}
|
|
3445
3573
|
if (err.retryAfter !== void 0) {
|
|
3446
3574
|
printHuman(c.yellow(` retry after: ${err.retryAfter}s`));
|
|
@@ -3457,8 +3585,22 @@ function handleError(err) {
|
|
|
3457
3585
|
process.exit(err.exitCode());
|
|
3458
3586
|
}
|
|
3459
3587
|
if (err instanceof Error) {
|
|
3460
|
-
|
|
3461
|
-
|
|
3588
|
+
const hint = err.hint;
|
|
3589
|
+
const hintStr = typeof hint === "string" ? hint : void 0;
|
|
3590
|
+
if (isJsonMode()) {
|
|
3591
|
+
printJson({
|
|
3592
|
+
error: {
|
|
3593
|
+
code: "generic_failure",
|
|
3594
|
+
message: err.message,
|
|
3595
|
+
...hintStr ? { hint: hintStr } : {}
|
|
3596
|
+
}
|
|
3597
|
+
});
|
|
3598
|
+
} else {
|
|
3599
|
+
printHuman(c.red(`\u2717 ${err.message}`));
|
|
3600
|
+
if (hintStr) {
|
|
3601
|
+
for (const line of hintStr.split("\n")) printHuman(c.gray(` \u2192 ${line}`));
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3462
3604
|
process.exit(1);
|
|
3463
3605
|
}
|
|
3464
3606
|
if (isJsonMode()) printJson({ error: { code: "generic_failure", message: String(err) } });
|