@rayul/kordis 0.6.5 → 0.6.7
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 +185 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1204,6 +1204,7 @@ import { join as join2 } from "path";
|
|
|
1204
1204
|
var SERVICE = "kordis";
|
|
1205
1205
|
var plaintextWarningEmitted = false;
|
|
1206
1206
|
async function loadKeytar() {
|
|
1207
|
+
if (process.env["KORDIS_NO_KEYCHAIN"] === "1") return null;
|
|
1207
1208
|
try {
|
|
1208
1209
|
const mod = await import("keytar");
|
|
1209
1210
|
return mod.default ?? mod;
|
|
@@ -1583,29 +1584,53 @@ async function useClient() {
|
|
|
1583
1584
|
baseUrl: cfg.apiUrl,
|
|
1584
1585
|
userAgent: `kordis-cli/${VERSION} node/${process.version}`
|
|
1585
1586
|
});
|
|
1587
|
+
const debug = process.env["KORDIS_DEBUG"] === "1";
|
|
1588
|
+
let pollResult = null;
|
|
1586
1589
|
try {
|
|
1587
|
-
|
|
1588
|
-
const meClient = new KordisClient({
|
|
1589
|
-
baseUrl: cfg.apiUrl,
|
|
1590
|
-
userAgent: `kordis-cli/${VERSION} node/${process.version}`,
|
|
1591
|
-
getAccessToken: () => tokens.access_token
|
|
1592
|
-
});
|
|
1593
|
-
const me = await meClient.me();
|
|
1594
|
-
username = me.username;
|
|
1595
|
-
currentTokens = {
|
|
1596
|
-
access_token: tokens.access_token,
|
|
1597
|
-
refresh_token: tokens.refresh_token,
|
|
1598
|
-
session_id: tokens.session_id,
|
|
1599
|
-
expires_at_epoch: Math.floor(Date.now() / 1e3) + tokens.expires_in
|
|
1600
|
-
};
|
|
1601
|
-
await keychain.save(username, currentTokens);
|
|
1602
|
-
cfg = { ...cfg, username, sessionId: tokens.session_id };
|
|
1603
|
-
await saveCliConfig(cfg);
|
|
1604
|
-
await clearPending();
|
|
1590
|
+
pollResult = await bootstrapApi.pollDeviceFlow(pending.device_code);
|
|
1605
1591
|
} catch (err) {
|
|
1606
1592
|
const code = err.code;
|
|
1607
|
-
if (code
|
|
1593
|
+
if (code === "authorization_pending") {
|
|
1594
|
+
if (debug) process.stderr.write("[kordis] auto-finalize: authorization_pending (keeping pending)\n");
|
|
1595
|
+
} else {
|
|
1608
1596
|
await clearPending();
|
|
1597
|
+
if (debug) {
|
|
1598
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1599
|
+
process.stderr.write(`[kordis] auto-finalize: poll failed (code=${code ?? "none"}): ${msg}
|
|
1600
|
+
`);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
if (pollResult) {
|
|
1605
|
+
try {
|
|
1606
|
+
const meClient = new KordisClient({
|
|
1607
|
+
baseUrl: cfg.apiUrl,
|
|
1608
|
+
userAgent: `kordis-cli/${VERSION} node/${process.version}`,
|
|
1609
|
+
getAccessToken: () => pollResult.access_token
|
|
1610
|
+
});
|
|
1611
|
+
const me = await meClient.me();
|
|
1612
|
+
username = me.username;
|
|
1613
|
+
currentTokens = {
|
|
1614
|
+
access_token: pollResult.access_token,
|
|
1615
|
+
refresh_token: pollResult.refresh_token,
|
|
1616
|
+
session_id: pollResult.session_id,
|
|
1617
|
+
expires_at_epoch: Math.floor(Date.now() / 1e3) + pollResult.expires_in
|
|
1618
|
+
};
|
|
1619
|
+
await keychain.save(username, currentTokens);
|
|
1620
|
+
cfg = { ...cfg, username, sessionId: pollResult.session_id };
|
|
1621
|
+
await saveCliConfig(cfg);
|
|
1622
|
+
await clearPending();
|
|
1623
|
+
if (debug) process.stderr.write(`[kordis] auto-finalize: persisted tokens for ${username}
|
|
1624
|
+
`);
|
|
1625
|
+
} catch (err) {
|
|
1626
|
+
await clearPending();
|
|
1627
|
+
currentTokens = null;
|
|
1628
|
+
username = null;
|
|
1629
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1630
|
+
process.stderr.write(
|
|
1631
|
+
`[kordis] auto-finalize: server issued tokens but local persistence failed (${msg}). Run \`kordis login --emit-only\` again to retry.
|
|
1632
|
+
`
|
|
1633
|
+
);
|
|
1609
1634
|
}
|
|
1610
1635
|
}
|
|
1611
1636
|
}
|
|
@@ -1894,14 +1919,47 @@ var SORT_MODES = [
|
|
|
1894
1919
|
"rising"
|
|
1895
1920
|
];
|
|
1896
1921
|
var TIME_WINDOWS = ["24h", "7d", "30d"];
|
|
1922
|
+
var TOOL_SLUGS = [
|
|
1923
|
+
"claude-code",
|
|
1924
|
+
"codex",
|
|
1925
|
+
"cursor",
|
|
1926
|
+
"antigravity",
|
|
1927
|
+
"windsurf",
|
|
1928
|
+
"continue",
|
|
1929
|
+
"copilot",
|
|
1930
|
+
"opencode",
|
|
1931
|
+
"gemini-cli"
|
|
1932
|
+
];
|
|
1933
|
+
var TOOL_ALIASES = {
|
|
1934
|
+
claude: "claude-code",
|
|
1935
|
+
gemini: "gemini-cli"
|
|
1936
|
+
};
|
|
1897
1937
|
function searchCommand() {
|
|
1898
|
-
return new Command3("search").description("search the Kordis registry").argument("[query...]", "keywords to match against title/description").option("--type <type>", "filter by harness type (skill|mcp-server|project-rules|custom-agent|hook)").option(
|
|
1938
|
+
return new Command3("search").description("search the Kordis registry").argument("[query...]", "keywords to match against title/description").option("--type <type>", "filter by harness type (skill|mcp-server|project-rules|custom-agent|hook)").option(
|
|
1939
|
+
"--tool <tool>",
|
|
1940
|
+
`filter by compatible tool \u2014 one of: ${TOOL_SLUGS.join("|")} (aliases: ${Object.entries(
|
|
1941
|
+
TOOL_ALIASES
|
|
1942
|
+
).map(([alias, canonical]) => `${alias}\u2192${canonical}`).join(", ")})`
|
|
1943
|
+
).option("--tier <tier>", "filter by portability tier (A|B|C|D)").option("--author <username>", "filter to a single author (server returns exact total when set)").option(
|
|
1944
|
+
"--cursor <token>",
|
|
1945
|
+
"pagination cursor \u2014 pass the next_cursor field from a prior search response to fetch the next page"
|
|
1946
|
+
).option("--sort <mode>", `sort: ${SORT_MODES.join("|")}`).option("--trending", "list trending packages (overrides --sort)", false).option("--rising", "list rising packages by 7d acceleration (overrides --sort)", false).option("--window <w>", `time window for --trending: ${TIME_WINDOWS.join("|")}`, "24h").option("--limit <n>", "max results", (v) => parseInt(v, 10), 20).action(async (query, opts) => {
|
|
1899
1947
|
if (opts.sort && !SORT_MODES.includes(opts.sort)) {
|
|
1900
1948
|
throw new Error(`--sort must be one of ${SORT_MODES.join(", ")}`);
|
|
1901
1949
|
}
|
|
1902
1950
|
if (opts.window && !TIME_WINDOWS.includes(opts.window)) {
|
|
1903
1951
|
throw new Error(`--window must be one of ${TIME_WINDOWS.join(", ")}`);
|
|
1904
1952
|
}
|
|
1953
|
+
let resolvedTool;
|
|
1954
|
+
if (opts.tool) {
|
|
1955
|
+
const candidate = TOOL_ALIASES[opts.tool] ?? opts.tool;
|
|
1956
|
+
if (!TOOL_SLUGS.includes(candidate)) {
|
|
1957
|
+
throw new Error(
|
|
1958
|
+
`--tool must be one of ${TOOL_SLUGS.join(", ")} (you passed "${opts.tool}")`
|
|
1959
|
+
);
|
|
1960
|
+
}
|
|
1961
|
+
resolvedTool = candidate;
|
|
1962
|
+
}
|
|
1905
1963
|
const bundle = await useClient();
|
|
1906
1964
|
let res;
|
|
1907
1965
|
if (opts.rising) {
|
|
@@ -1919,9 +1977,10 @@ function searchCommand() {
|
|
|
1919
1977
|
res = await bundle.api.search({
|
|
1920
1978
|
q: query.join(" ") || void 0,
|
|
1921
1979
|
type: opts.type ? [opts.type] : void 0,
|
|
1922
|
-
tool:
|
|
1980
|
+
tool: resolvedTool ? [resolvedTool] : void 0,
|
|
1923
1981
|
tier: opts.tier,
|
|
1924
1982
|
...opts.author ? { author: opts.author } : {},
|
|
1983
|
+
...opts.cursor ? { cursor: opts.cursor } : {},
|
|
1925
1984
|
sort: opts.sort ?? "relevance",
|
|
1926
1985
|
limit: opts.limit
|
|
1927
1986
|
});
|
|
@@ -3277,18 +3336,23 @@ function getTranslator(type, format) {
|
|
|
3277
3336
|
import { homedir as homedir6 } from "os";
|
|
3278
3337
|
import { join as join8 } from "path";
|
|
3279
3338
|
import { readFile as readFile7, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
3280
|
-
|
|
3339
|
+
function kordisHome2() {
|
|
3340
|
+
return process.env["KORDIS_HOME"] ?? join8(homedir6(), ".kordis");
|
|
3341
|
+
}
|
|
3342
|
+
function lockfilePath() {
|
|
3343
|
+
return join8(kordisHome2(), "installed.json");
|
|
3344
|
+
}
|
|
3281
3345
|
async function readLockfile() {
|
|
3282
3346
|
try {
|
|
3283
|
-
const raw = await readFile7(
|
|
3347
|
+
const raw = await readFile7(lockfilePath(), "utf8");
|
|
3284
3348
|
return JSON.parse(raw);
|
|
3285
3349
|
} catch {
|
|
3286
3350
|
return { packages: {} };
|
|
3287
3351
|
}
|
|
3288
3352
|
}
|
|
3289
3353
|
async function writeLockfile(lf) {
|
|
3290
|
-
await mkdir5(
|
|
3291
|
-
await writeFile5(
|
|
3354
|
+
await mkdir5(kordisHome2(), { recursive: true });
|
|
3355
|
+
await writeFile5(lockfilePath(), JSON.stringify(lf, null, 2) + "\n", "utf8");
|
|
3292
3356
|
}
|
|
3293
3357
|
async function recordInstalled(fullSlug, entry) {
|
|
3294
3358
|
const lf = await readLockfile();
|
|
@@ -3808,6 +3872,8 @@ var KINDS = [
|
|
|
3808
3872
|
"praise",
|
|
3809
3873
|
"question"
|
|
3810
3874
|
];
|
|
3875
|
+
var LIST_SORTS = ["recent", "old"];
|
|
3876
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3811
3877
|
function commentCommand() {
|
|
3812
3878
|
return new Command10("comment").description("post a comment on a package").argument("<full_slug>", "package identifier {username}/{slug}").requiredOption("--body <text>", "comment body (1\u201310000 chars)").option("--kind <kind>", `top-level kind: ${KINDS.join("|")}`, "comment").option("--title <text>", "top-level post title (1\u2013140 chars)").action(
|
|
3813
3879
|
async (rawSlug, opts) => {
|
|
@@ -3838,11 +3904,103 @@ function commentCommand() {
|
|
|
3838
3904
|
if (res.permalink) {
|
|
3839
3905
|
printHuman(c.gray(` view: ${res.permalink}`));
|
|
3840
3906
|
}
|
|
3907
|
+
printHuman(c.gray(` delete: kordis uncomment ${res.id}`));
|
|
3841
3908
|
}
|
|
3842
3909
|
});
|
|
3843
3910
|
}
|
|
3844
3911
|
);
|
|
3845
3912
|
}
|
|
3913
|
+
function commentsCommand() {
|
|
3914
|
+
return new Command10("comments").description("list comments on a package").argument("<full_slug>", "package identifier {username}/{slug}").option("--limit <n>", "max top-level comments (1\u201350)", (v) => parseInt(v, 10), 20).option("--cursor <token>", "pagination cursor returned by a prior call as next_cursor").option(
|
|
3915
|
+
"--kind <kind>",
|
|
3916
|
+
`filter top-level posts by kind: ${KINDS.join("|")}`
|
|
3917
|
+
).option("--sort <mode>", `sort: ${LIST_SORTS.join("|")} (default: recent)`).action(
|
|
3918
|
+
async (rawSlug, opts) => {
|
|
3919
|
+
const [username, slug] = rawSlug.split("/");
|
|
3920
|
+
if (!username || !slug) {
|
|
3921
|
+
throw new Error('full_slug must be "{username}/{slug}"');
|
|
3922
|
+
}
|
|
3923
|
+
if (opts.kind && !KINDS.includes(opts.kind)) {
|
|
3924
|
+
throw new Error(`--kind must be one of ${KINDS.join(", ")}`);
|
|
3925
|
+
}
|
|
3926
|
+
if (opts.sort && !LIST_SORTS.includes(opts.sort)) {
|
|
3927
|
+
throw new Error(`--sort must be one of ${LIST_SORTS.join(", ")}`);
|
|
3928
|
+
}
|
|
3929
|
+
const bundle = await useClient();
|
|
3930
|
+
const res = await bundle.api.listComments(username, slug, {
|
|
3931
|
+
limit: opts.limit,
|
|
3932
|
+
...opts.cursor ? { cursor: opts.cursor } : {},
|
|
3933
|
+
...opts.kind ? { kind: opts.kind } : {},
|
|
3934
|
+
...opts.sort ? { sort: opts.sort } : {}
|
|
3935
|
+
});
|
|
3936
|
+
printDual({
|
|
3937
|
+
json: res,
|
|
3938
|
+
human: () => {
|
|
3939
|
+
if (res.results.length === 0) {
|
|
3940
|
+
printHuman(c.yellow("(no comments)"));
|
|
3941
|
+
printHuman(
|
|
3942
|
+
c.gray(" \u2192 be the first: kordis comment " + rawSlug + ' --body "..."')
|
|
3943
|
+
);
|
|
3944
|
+
return;
|
|
3945
|
+
}
|
|
3946
|
+
printHuman(
|
|
3947
|
+
c.gray(
|
|
3948
|
+
`Showing ${res.results.length} of ${res.total} top-level comment${res.total === 1 ? "" : "s"}`
|
|
3949
|
+
)
|
|
3950
|
+
);
|
|
3951
|
+
printHuman("");
|
|
3952
|
+
for (const node of res.results) {
|
|
3953
|
+
renderCommentNode(node, 0);
|
|
3954
|
+
}
|
|
3955
|
+
if (res.next_cursor) {
|
|
3956
|
+
printHuman(
|
|
3957
|
+
c.gray(
|
|
3958
|
+
`(more available \u2014 kordis comments ${rawSlug} --cursor ${res.next_cursor})`
|
|
3959
|
+
)
|
|
3960
|
+
);
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
});
|
|
3964
|
+
}
|
|
3965
|
+
);
|
|
3966
|
+
}
|
|
3967
|
+
function renderCommentNode(node, depth) {
|
|
3968
|
+
const indent = " ".repeat(depth);
|
|
3969
|
+
const tag = node.kind === "comment" ? "" : c.cyan(`[${node.kind}]`) + " ";
|
|
3970
|
+
const title = node.title ? c.bold(node.title) + " " : "";
|
|
3971
|
+
const author = `${node.author.username}${node.author.display_name ? ` (${node.author.display_name})` : ""}`;
|
|
3972
|
+
printHuman(`${indent}${tag}${title}${c.gray(`\u2014 ${author}`)}`);
|
|
3973
|
+
for (const line of node.body.split("\n")) {
|
|
3974
|
+
printHuman(`${indent} ${line}`);
|
|
3975
|
+
}
|
|
3976
|
+
const trail = [`id: ${node.id}`];
|
|
3977
|
+
if (node.reply_count > 0) trail.push(`${node.reply_count} repl${node.reply_count === 1 ? "y" : "ies"}`);
|
|
3978
|
+
if (node.is_edited) trail.push("edited");
|
|
3979
|
+
if (node.permalink) trail.push(`view: ${node.permalink}`);
|
|
3980
|
+
printHuman(c.gray(`${indent} ${trail.join(" \xB7 ")}`));
|
|
3981
|
+
printHuman("");
|
|
3982
|
+
for (const child of node.replies) {
|
|
3983
|
+
renderCommentNode(child, depth + 1);
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
function uncommentCommand() {
|
|
3987
|
+
return new Command10("uncomment").description("delete one of your comments by id").argument("<id>", "comment id (uuid v4)").action(async (id) => {
|
|
3988
|
+
if (!UUID_RE.test(id)) {
|
|
3989
|
+
throw new Error(
|
|
3990
|
+
"comment id must be a uuid v4 \u2014 get it from `kordis comments <slug>` or the `id` field on `kordis comment`'s response"
|
|
3991
|
+
);
|
|
3992
|
+
}
|
|
3993
|
+
const bundle = await useClient();
|
|
3994
|
+
requireAuth(bundle);
|
|
3995
|
+
await bundle.authedRequest((api) => api.deleteComment(id));
|
|
3996
|
+
printDual({
|
|
3997
|
+
json: { status: "deleted", id },
|
|
3998
|
+
human: () => {
|
|
3999
|
+
printHuman(c.gray(`\u2717 deleted comment ${id}`));
|
|
4000
|
+
}
|
|
4001
|
+
});
|
|
4002
|
+
});
|
|
4003
|
+
}
|
|
3846
4004
|
|
|
3847
4005
|
// src/commands/star.ts
|
|
3848
4006
|
import { Command as Command11 } from "commander";
|
|
@@ -4440,6 +4598,8 @@ function buildProgram() {
|
|
|
4440
4598
|
program.addCommand(readCommand());
|
|
4441
4599
|
program.addCommand(infoCommand());
|
|
4442
4600
|
program.addCommand(commentCommand());
|
|
4601
|
+
program.addCommand(commentsCommand());
|
|
4602
|
+
program.addCommand(uncommentCommand());
|
|
4443
4603
|
program.addCommand(starCommand());
|
|
4444
4604
|
program.addCommand(unstarCommand());
|
|
4445
4605
|
program.addCommand(deleteCommand());
|