@islamihab/kds 0.4.0 → 0.6.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/index.js +143 -11
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -14597,7 +14597,7 @@ import { join } from "path";
|
|
|
14597
14597
|
// package.json
|
|
14598
14598
|
var package_default = {
|
|
14599
14599
|
name: "cli",
|
|
14600
|
-
version: "0.
|
|
14600
|
+
version: "0.6.0",
|
|
14601
14601
|
private: true,
|
|
14602
14602
|
type: "module",
|
|
14603
14603
|
bin: {
|
|
@@ -15188,6 +15188,14 @@ var ISSUE_OPEN_STATUSES = [
|
|
|
15188
15188
|
"changes_requested",
|
|
15189
15189
|
"approved"
|
|
15190
15190
|
];
|
|
15191
|
+
var REVIEW_FINDING_CATEGORIES = [
|
|
15192
|
+
"functional_correctness",
|
|
15193
|
+
"maintainability",
|
|
15194
|
+
"security",
|
|
15195
|
+
"performance"
|
|
15196
|
+
];
|
|
15197
|
+
var REVIEW_FINDING_SEVERITIES = ["critical", "major", "minor", "trivial"];
|
|
15198
|
+
var MAX_REVIEW_FINDINGS = 50;
|
|
15191
15199
|
var ISSUE_LABEL_COLORS = [
|
|
15192
15200
|
"gray",
|
|
15193
15201
|
"red",
|
|
@@ -18005,6 +18013,19 @@ var logout = command({
|
|
|
18005
18013
|
}
|
|
18006
18014
|
});
|
|
18007
18015
|
|
|
18016
|
+
// src/commands/auth/reviewer-token.ts
|
|
18017
|
+
var reviewerToken = command({
|
|
18018
|
+
name: "reviewer-token",
|
|
18019
|
+
description: "Print a short-lived GitHub token for the reviewer App identity",
|
|
18020
|
+
options: {
|
|
18021
|
+
json: exports_external.boolean().default(false).describe("Print as JSON")
|
|
18022
|
+
},
|
|
18023
|
+
run: async ({ options: { json: json2 } }) => {
|
|
18024
|
+
const minted = await (await backendClient()).action(api2.githubReviewer.mintToken, {});
|
|
18025
|
+
console.log(json2 ? JSON.stringify(minted, null, 2) : minted.token);
|
|
18026
|
+
}
|
|
18027
|
+
});
|
|
18028
|
+
|
|
18008
18029
|
// src/lib/activity.ts
|
|
18009
18030
|
var SOURCE_LABELS = { github: "GitHub", agent: "Agent" };
|
|
18010
18031
|
var actorLabel = (via, agent) => {
|
|
@@ -18091,7 +18112,7 @@ var status = command({
|
|
|
18091
18112
|
var auth = group({
|
|
18092
18113
|
name: "auth",
|
|
18093
18114
|
description: "Manage backend authentication",
|
|
18094
|
-
commands: [login, logout, status]
|
|
18115
|
+
commands: [login, logout, status, reviewerToken]
|
|
18095
18116
|
});
|
|
18096
18117
|
|
|
18097
18118
|
// src/lib/output.ts
|
|
@@ -18146,9 +18167,10 @@ var runInbox = async (options) => {
|
|
|
18146
18167
|
};
|
|
18147
18168
|
|
|
18148
18169
|
// src/lib/input.ts
|
|
18149
|
-
var assertSize = (size) => {
|
|
18150
|
-
if (size > MAX_PAGE_HTML_BYTES)
|
|
18151
|
-
throw new Error(
|
|
18170
|
+
var assertSize = (size, subject = "Page") => {
|
|
18171
|
+
if (size > MAX_PAGE_HTML_BYTES) {
|
|
18172
|
+
throw new Error(`${subject} is too large (${size} bytes; max ${MAX_PAGE_HTML_BYTES}).`);
|
|
18173
|
+
}
|
|
18152
18174
|
};
|
|
18153
18175
|
var readBody = async (path) => {
|
|
18154
18176
|
if (path === "-") {
|
|
@@ -18161,6 +18183,18 @@ var readBody = async (path) => {
|
|
|
18161
18183
|
return await file2.text();
|
|
18162
18184
|
};
|
|
18163
18185
|
var readTextOption = async (value) => value === "-" ? await Bun.stdin.text() : value;
|
|
18186
|
+
var readFileOption = async (path) => {
|
|
18187
|
+
if (path === "-") {
|
|
18188
|
+
const text = await Bun.stdin.text();
|
|
18189
|
+
assertSize(new TextEncoder().encode(text).length, "Input");
|
|
18190
|
+
return text;
|
|
18191
|
+
}
|
|
18192
|
+
const file2 = Bun.file(path);
|
|
18193
|
+
if (!await file2.exists())
|
|
18194
|
+
throw new Error(`No file at ${path}.`);
|
|
18195
|
+
assertSize(file2.size, "Input");
|
|
18196
|
+
return await file2.text();
|
|
18197
|
+
};
|
|
18164
18198
|
var readIssueRef = (value) => {
|
|
18165
18199
|
const trimmed = value.trim();
|
|
18166
18200
|
if (/^\d+$/.test(trimmed))
|
|
@@ -18476,7 +18510,7 @@ var get = command({
|
|
|
18476
18510
|
]);
|
|
18477
18511
|
if (json2)
|
|
18478
18512
|
return console.log(JSON.stringify({ ...issue2, relations, attachments, tasks, feed }, null, 2));
|
|
18479
|
-
const project = issue2.
|
|
18513
|
+
const project = issue2.project;
|
|
18480
18514
|
const milestone = issue2.milestoneId ? await client3.query(api2.milestones.get, { id: issue2.milestoneId, today: localToday() }) : null;
|
|
18481
18515
|
console.log(`${issue2.identifier} ${issue2.title}`);
|
|
18482
18516
|
console.log(`Status: ${issue2.status} \xB7 Priority: ${issue2.priority} \xB7 Disposition: ${issue2.disposition}`);
|
|
@@ -18685,6 +18719,37 @@ More issues match; raise --limit past ${options.limit}.`);
|
|
|
18685
18719
|
}
|
|
18686
18720
|
});
|
|
18687
18721
|
|
|
18722
|
+
// src/commands/issues/mark-addressed.ts
|
|
18723
|
+
var parseFindingRef = (value) => {
|
|
18724
|
+
const match = /^(.+):([1-9]\d*)$/.exec(value);
|
|
18725
|
+
if (!match?.[1] || !match[2])
|
|
18726
|
+
throw new Error(`--finding takes path:line, got "${value}".`);
|
|
18727
|
+
return { path: match[1], line: Number(match[2]) };
|
|
18728
|
+
};
|
|
18729
|
+
var markAddressed = command({
|
|
18730
|
+
name: "mark-addressed",
|
|
18731
|
+
description: "Mark review findings addressed by a commit and resolve their conversations",
|
|
18732
|
+
positionals: {
|
|
18733
|
+
id: exports_external.string().describe("Issue identifier, number, or URL")
|
|
18734
|
+
},
|
|
18735
|
+
options: {
|
|
18736
|
+
commit: exports_external.string().describe("The commit sha that addressed the findings").meta({ short: "c" }),
|
|
18737
|
+
finding: exports_external.array(exports_external.string()).optional().describe("Mark only this finding, as path:line (repeatable; default all)")
|
|
18738
|
+
},
|
|
18739
|
+
run: async ({ positionals: { id }, options: { commit, finding } }) => {
|
|
18740
|
+
const client3 = await backendClient();
|
|
18741
|
+
const issue2 = await resolveIssue(client3, id);
|
|
18742
|
+
const result = await client3.action(api2.githubReviewer.markAddressed, {
|
|
18743
|
+
id: issue2._id,
|
|
18744
|
+
commitSha: commit,
|
|
18745
|
+
findings: finding?.map(parseFindingRef)
|
|
18746
|
+
});
|
|
18747
|
+
const already = result.alreadyMarked.length ? ` (${result.alreadyMarked.length} already marked)` : "";
|
|
18748
|
+
console.log(`Marked ${result.marked.length} on ${result.identifier} as addressed in ${commit}${already}.`);
|
|
18749
|
+
console.log(result.resolved ? `Resolved ${result.resolved} conversation${result.resolved === 1 ? "" : "s"}.` : "All conversations already resolved.");
|
|
18750
|
+
}
|
|
18751
|
+
});
|
|
18752
|
+
|
|
18688
18753
|
// src/commands/issues/relate.ts
|
|
18689
18754
|
var relate = command({
|
|
18690
18755
|
name: "relate",
|
|
@@ -18777,10 +18842,10 @@ var set2 = command({
|
|
|
18777
18842
|
throw new Error("Nothing to set. Pass --status, --priority, --estimate, --due, --project, --milestone, --parent, --agent-config, or --label.");
|
|
18778
18843
|
const client3 = await backendClient();
|
|
18779
18844
|
const issue2 = await resolveIssue(client3, id);
|
|
18780
|
-
const projectId = project === undefined ? issue2.
|
|
18845
|
+
const projectId = project === undefined ? issue2.project?._id : project === null ? undefined : (await resolveProject(client3, project))._id;
|
|
18781
18846
|
let milestoneId;
|
|
18782
18847
|
if (milestone === undefined) {
|
|
18783
|
-
milestoneId = projectId === issue2.
|
|
18848
|
+
milestoneId = projectId === issue2.project?._id ? issue2.milestoneId : undefined;
|
|
18784
18849
|
} else if (milestone !== null) {
|
|
18785
18850
|
if (projectId === undefined)
|
|
18786
18851
|
throw new Error("A milestone needs a project. Pass --project too.");
|
|
@@ -18846,15 +18911,16 @@ var start = command({
|
|
|
18846
18911
|
// src/commands/issues/start-review.ts
|
|
18847
18912
|
var startReview = command({
|
|
18848
18913
|
name: "start-review",
|
|
18849
|
-
description: "Claim review work: move a ready_for_review issue to in_review",
|
|
18914
|
+
description: "Claim review work: move a ready_for_review issue to in_review and announce the review on its pull request",
|
|
18850
18915
|
positionals: {
|
|
18851
18916
|
id: exports_external.string().describe("Issue identifier, number, or URL")
|
|
18852
18917
|
},
|
|
18853
18918
|
run: async ({ positionals: { id } }) => {
|
|
18854
18919
|
const client3 = await backendClient();
|
|
18855
18920
|
const issue2 = await resolveIssue(client3, id);
|
|
18856
|
-
await client3.
|
|
18857
|
-
console.log(`Reviewing ${
|
|
18921
|
+
const started = await client3.action(api2.githubReviewer.startReview, { id: issue2._id });
|
|
18922
|
+
console.log(`Reviewing ${started.identifier}: in_review`);
|
|
18923
|
+
console.log(`Announced on ${started.prUrl}; check run open.`);
|
|
18858
18924
|
}
|
|
18859
18925
|
});
|
|
18860
18926
|
|
|
@@ -18873,6 +18939,70 @@ var submit = command({
|
|
|
18873
18939
|
}
|
|
18874
18940
|
});
|
|
18875
18941
|
|
|
18942
|
+
// src/commands/issues/submit-review.ts
|
|
18943
|
+
var findingsSchema = exports_external.array(exports_external.object({
|
|
18944
|
+
path: exports_external.string().min(1),
|
|
18945
|
+
line: exports_external.number().int().positive(),
|
|
18946
|
+
startLine: exports_external.number().int().positive().optional(),
|
|
18947
|
+
category: exports_external.enum(REVIEW_FINDING_CATEGORIES),
|
|
18948
|
+
severity: exports_external.enum(REVIEW_FINDING_SEVERITIES),
|
|
18949
|
+
summary: exports_external.string().min(1),
|
|
18950
|
+
body: exports_external.string().min(1),
|
|
18951
|
+
diff: exports_external.string().optional()
|
|
18952
|
+
})).min(1).max(MAX_REVIEW_FINDINGS);
|
|
18953
|
+
var readFindings = async (path) => {
|
|
18954
|
+
const text = await readFileOption(path);
|
|
18955
|
+
let json2;
|
|
18956
|
+
try {
|
|
18957
|
+
json2 = JSON.parse(text);
|
|
18958
|
+
} catch {
|
|
18959
|
+
throw new Error("The findings file is not valid JSON.");
|
|
18960
|
+
}
|
|
18961
|
+
const parsed = findingsSchema.safeParse(json2);
|
|
18962
|
+
if (!parsed.success)
|
|
18963
|
+
throw new Error(`The findings file is invalid:
|
|
18964
|
+
${exports_external.prettifyError(parsed.error)}`);
|
|
18965
|
+
return parsed.data;
|
|
18966
|
+
};
|
|
18967
|
+
var submitReview = command({
|
|
18968
|
+
name: "submit-review",
|
|
18969
|
+
description: "Submit the review verdict on an issue's linked pull request as the reviewer App",
|
|
18970
|
+
positionals: {
|
|
18971
|
+
id: exports_external.string().describe("Issue identifier, number, or URL")
|
|
18972
|
+
},
|
|
18973
|
+
options: {
|
|
18974
|
+
approve: exports_external.boolean().default(false).describe("Approve: bare APPROVE plus a clean bill"),
|
|
18975
|
+
"request-changes": exports_external.boolean().default(false).describe("Request changes from a findings file"),
|
|
18976
|
+
findings: exports_external.string().optional().describe("Findings JSON file, or - for stdin (with --request-changes)"),
|
|
18977
|
+
bill: exports_external.string().optional().describe("Clean-bill text, or - for stdin (with --approve)")
|
|
18978
|
+
},
|
|
18979
|
+
run: async ({ positionals: { id }, options }) => {
|
|
18980
|
+
if (options.approve === options["request-changes"]) {
|
|
18981
|
+
throw new Error("Pass exactly one of --approve or --request-changes.");
|
|
18982
|
+
}
|
|
18983
|
+
if (options.approve && options.findings !== undefined)
|
|
18984
|
+
throw new Error("--findings goes with --request-changes.");
|
|
18985
|
+
if (options["request-changes"] && options.bill !== undefined)
|
|
18986
|
+
throw new Error("--bill goes with --approve.");
|
|
18987
|
+
let verdict;
|
|
18988
|
+
if (options.approve) {
|
|
18989
|
+
if (options.bill === undefined)
|
|
18990
|
+
throw new Error("--approve needs the clean bill: --bill <text>, or - for stdin.");
|
|
18991
|
+
verdict = { kind: "approve", bill: await readTextOption(options.bill) };
|
|
18992
|
+
} else {
|
|
18993
|
+
if (options.findings === undefined) {
|
|
18994
|
+
throw new Error("--request-changes needs the findings: --findings <file>, or - for stdin.");
|
|
18995
|
+
}
|
|
18996
|
+
verdict = { kind: "request_changes", findings: await readFindings(options.findings) };
|
|
18997
|
+
}
|
|
18998
|
+
const client3 = await backendClient();
|
|
18999
|
+
const issue2 = await resolveIssue(client3, id);
|
|
19000
|
+
const submitted = await client3.action(api2.githubReviewer.submitReview, { id: issue2._id, verdict });
|
|
19001
|
+
console.log(`Submitted review on ${submitted.identifier}: ${submitted.prUrl}`);
|
|
19002
|
+
console.log(submitted.summary);
|
|
19003
|
+
}
|
|
19004
|
+
});
|
|
19005
|
+
|
|
18876
19006
|
// src/commands/issues/tasks.ts
|
|
18877
19007
|
var position = exports_external.array(exports_external.coerce.number().int().positive());
|
|
18878
19008
|
var tasks = command({
|
|
@@ -19008,6 +19138,8 @@ var issues = group({
|
|
|
19008
19138
|
start,
|
|
19009
19139
|
submit,
|
|
19010
19140
|
startReview,
|
|
19141
|
+
submitReview,
|
|
19142
|
+
markAddressed,
|
|
19011
19143
|
tasks,
|
|
19012
19144
|
relate,
|
|
19013
19145
|
unrelate,
|