@oss-autopilot/core 0.41.0 → 0.42.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/cli.bundle.cjs +1300 -1020
- package/dist/cli.js +591 -55
- package/dist/commands/check-integration.d.ts +3 -3
- package/dist/commands/check-integration.js +5 -39
- package/dist/commands/comments.d.ts +6 -9
- package/dist/commands/comments.js +78 -228
- package/dist/commands/config.d.ts +8 -2
- package/dist/commands/config.js +6 -28
- package/dist/commands/daily.d.ts +28 -4
- package/dist/commands/daily.js +19 -32
- package/dist/commands/dashboard-server.d.ts +14 -0
- package/dist/commands/dashboard-server.js +361 -0
- package/dist/commands/dashboard.d.ts +5 -0
- package/dist/commands/dashboard.js +49 -0
- package/dist/commands/dismiss.d.ts +13 -5
- package/dist/commands/dismiss.js +4 -24
- package/dist/commands/index.d.ts +33 -0
- package/dist/commands/index.js +22 -0
- package/dist/commands/init.d.ts +5 -4
- package/dist/commands/init.js +4 -14
- package/dist/commands/local-repos.d.ts +4 -5
- package/dist/commands/local-repos.js +4 -32
- package/dist/commands/parse-list.d.ts +3 -4
- package/dist/commands/parse-list.js +6 -38
- package/dist/commands/read.d.ts +11 -5
- package/dist/commands/read.js +4 -18
- package/dist/commands/search.d.ts +3 -3
- package/dist/commands/search.js +39 -65
- package/dist/commands/setup.d.ts +34 -5
- package/dist/commands/setup.js +75 -166
- package/dist/commands/shelve.d.ts +13 -5
- package/dist/commands/shelve.js +4 -24
- package/dist/commands/snooze.d.ts +15 -9
- package/dist/commands/snooze.js +16 -59
- package/dist/commands/startup.d.ts +11 -6
- package/dist/commands/startup.js +39 -67
- package/dist/commands/status.d.ts +3 -3
- package/dist/commands/status.js +10 -29
- package/dist/commands/track.d.ts +10 -9
- package/dist/commands/track.js +17 -39
- package/dist/commands/validation.d.ts +2 -2
- package/dist/commands/validation.js +3 -11
- package/dist/commands/vet.d.ts +3 -3
- package/dist/commands/vet.js +16 -26
- package/dist/formatters/json.d.ts +58 -0
- package/package.json +5 -1
package/dist/cli.bundle.cjs
CHANGED
|
@@ -1196,8 +1196,8 @@ var require_command = __commonJS({
|
|
|
1196
1196
|
"../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/lib/command.js"(exports2) {
|
|
1197
1197
|
var EventEmitter = require("node:events").EventEmitter;
|
|
1198
1198
|
var childProcess = require("node:child_process");
|
|
1199
|
-
var
|
|
1200
|
-
var
|
|
1199
|
+
var path11 = require("node:path");
|
|
1200
|
+
var fs10 = require("node:fs");
|
|
1201
1201
|
var process2 = require("node:process");
|
|
1202
1202
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1203
1203
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2191,7 +2191,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2191
2191
|
* @param {string} subcommandName
|
|
2192
2192
|
*/
|
|
2193
2193
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2194
|
-
if (
|
|
2194
|
+
if (fs10.existsSync(executableFile)) return;
|
|
2195
2195
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2196
2196
|
const executableMissing = `'${executableFile}' does not exist
|
|
2197
2197
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2209,11 +2209,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2209
2209
|
let launchWithNode = false;
|
|
2210
2210
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2211
2211
|
function findFile(baseDir, baseName) {
|
|
2212
|
-
const localBin =
|
|
2213
|
-
if (
|
|
2214
|
-
if (sourceExt.includes(
|
|
2212
|
+
const localBin = path11.resolve(baseDir, baseName);
|
|
2213
|
+
if (fs10.existsSync(localBin)) return localBin;
|
|
2214
|
+
if (sourceExt.includes(path11.extname(baseName))) return void 0;
|
|
2215
2215
|
const foundExt = sourceExt.find(
|
|
2216
|
-
(ext) =>
|
|
2216
|
+
(ext) => fs10.existsSync(`${localBin}${ext}`)
|
|
2217
2217
|
);
|
|
2218
2218
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2219
2219
|
return void 0;
|
|
@@ -2225,21 +2225,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2225
2225
|
if (this._scriptPath) {
|
|
2226
2226
|
let resolvedScriptPath;
|
|
2227
2227
|
try {
|
|
2228
|
-
resolvedScriptPath =
|
|
2228
|
+
resolvedScriptPath = fs10.realpathSync(this._scriptPath);
|
|
2229
2229
|
} catch {
|
|
2230
2230
|
resolvedScriptPath = this._scriptPath;
|
|
2231
2231
|
}
|
|
2232
|
-
executableDir =
|
|
2233
|
-
|
|
2232
|
+
executableDir = path11.resolve(
|
|
2233
|
+
path11.dirname(resolvedScriptPath),
|
|
2234
2234
|
executableDir
|
|
2235
2235
|
);
|
|
2236
2236
|
}
|
|
2237
2237
|
if (executableDir) {
|
|
2238
2238
|
let localFile = findFile(executableDir, executableFile);
|
|
2239
2239
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2240
|
-
const legacyName =
|
|
2240
|
+
const legacyName = path11.basename(
|
|
2241
2241
|
this._scriptPath,
|
|
2242
|
-
|
|
2242
|
+
path11.extname(this._scriptPath)
|
|
2243
2243
|
);
|
|
2244
2244
|
if (legacyName !== this._name) {
|
|
2245
2245
|
localFile = findFile(
|
|
@@ -2250,7 +2250,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2250
2250
|
}
|
|
2251
2251
|
executableFile = localFile || executableFile;
|
|
2252
2252
|
}
|
|
2253
|
-
launchWithNode = sourceExt.includes(
|
|
2253
|
+
launchWithNode = sourceExt.includes(path11.extname(executableFile));
|
|
2254
2254
|
let proc;
|
|
2255
2255
|
if (process2.platform !== "win32") {
|
|
2256
2256
|
if (launchWithNode) {
|
|
@@ -3165,7 +3165,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3165
3165
|
* @return {Command}
|
|
3166
3166
|
*/
|
|
3167
3167
|
nameFromFilename(filename) {
|
|
3168
|
-
this._name =
|
|
3168
|
+
this._name = path11.basename(filename, path11.extname(filename));
|
|
3169
3169
|
return this;
|
|
3170
3170
|
}
|
|
3171
3171
|
/**
|
|
@@ -3179,9 +3179,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3179
3179
|
* @param {string} [path]
|
|
3180
3180
|
* @return {(string|null|Command)}
|
|
3181
3181
|
*/
|
|
3182
|
-
executableDir(
|
|
3183
|
-
if (
|
|
3184
|
-
this._executableDir =
|
|
3182
|
+
executableDir(path12) {
|
|
3183
|
+
if (path12 === void 0) return this._executableDir;
|
|
3184
|
+
this._executableDir = path12;
|
|
3185
3185
|
return this;
|
|
3186
3186
|
}
|
|
3187
3187
|
/**
|
|
@@ -3681,6 +3681,15 @@ function getGitHubToken() {
|
|
|
3681
3681
|
}
|
|
3682
3682
|
return null;
|
|
3683
3683
|
}
|
|
3684
|
+
function requireGitHubToken() {
|
|
3685
|
+
const token = getGitHubToken();
|
|
3686
|
+
if (!token) {
|
|
3687
|
+
throw new ConfigurationError(
|
|
3688
|
+
"GitHub authentication required.\n\nOptions:\n 1. Use gh CLI: gh auth login\n 2. Set GITHUB_TOKEN environment variable\n\nThe gh CLI is recommended - install from https://cli.github.com"
|
|
3689
|
+
);
|
|
3690
|
+
}
|
|
3691
|
+
return token;
|
|
3692
|
+
}
|
|
3684
3693
|
async function getGitHubTokenAsync() {
|
|
3685
3694
|
if (cachedGitHubToken) {
|
|
3686
3695
|
return cachedGitHubToken;
|
|
@@ -3694,12 +3703,12 @@ async function getGitHubTokenAsync() {
|
|
|
3694
3703
|
return cachedGitHubToken;
|
|
3695
3704
|
}
|
|
3696
3705
|
try {
|
|
3697
|
-
const token = await new Promise((
|
|
3706
|
+
const token = await new Promise((resolve5, reject) => {
|
|
3698
3707
|
(0, import_child_process.execFile)("gh", ["auth", "token"], { encoding: "utf-8", timeout: 2e3 }, (error, stdout) => {
|
|
3699
3708
|
if (error) {
|
|
3700
3709
|
reject(error);
|
|
3701
3710
|
} else {
|
|
3702
|
-
|
|
3711
|
+
resolve5(stdout.trim());
|
|
3703
3712
|
}
|
|
3704
3713
|
});
|
|
3705
3714
|
});
|
|
@@ -5891,17 +5900,17 @@ function requestLog(octokit) {
|
|
|
5891
5900
|
octokit.log.debug("request", options);
|
|
5892
5901
|
const start = Date.now();
|
|
5893
5902
|
const requestOptions = octokit.request.endpoint.parse(options);
|
|
5894
|
-
const
|
|
5903
|
+
const path11 = requestOptions.url.replace(options.baseUrl, "");
|
|
5895
5904
|
return request2(options).then((response) => {
|
|
5896
5905
|
const requestId = response.headers["x-github-request-id"];
|
|
5897
5906
|
octokit.log.info(
|
|
5898
|
-
`${requestOptions.method} ${
|
|
5907
|
+
`${requestOptions.method} ${path11} - ${response.status} with id ${requestId} in ${Date.now() - start}ms`
|
|
5899
5908
|
);
|
|
5900
5909
|
return response;
|
|
5901
5910
|
}).catch((error) => {
|
|
5902
5911
|
const requestId = error.response?.headers["x-github-request-id"] || "UNKNOWN";
|
|
5903
5912
|
octokit.log.error(
|
|
5904
|
-
`${requestOptions.method} ${
|
|
5913
|
+
`${requestOptions.method} ${path11} - ${error.status} with id ${requestId} in ${Date.now() - start}ms`
|
|
5905
5914
|
);
|
|
5906
5915
|
throw error;
|
|
5907
5916
|
});
|
|
@@ -8970,8 +8979,8 @@ var require_light = __commonJS({
|
|
|
8970
8979
|
return this.Promise.resolve();
|
|
8971
8980
|
}
|
|
8972
8981
|
yieldLoop(t = 0) {
|
|
8973
|
-
return new this.Promise(function(
|
|
8974
|
-
return setTimeout(
|
|
8982
|
+
return new this.Promise(function(resolve5, reject) {
|
|
8983
|
+
return setTimeout(resolve5, t);
|
|
8975
8984
|
});
|
|
8976
8985
|
}
|
|
8977
8986
|
computePenalty() {
|
|
@@ -9182,15 +9191,15 @@ var require_light = __commonJS({
|
|
|
9182
9191
|
return this._queue.length === 0;
|
|
9183
9192
|
}
|
|
9184
9193
|
async _tryToRun() {
|
|
9185
|
-
var args, cb, error, reject,
|
|
9194
|
+
var args, cb, error, reject, resolve5, returned, task;
|
|
9186
9195
|
if (this._running < 1 && this._queue.length > 0) {
|
|
9187
9196
|
this._running++;
|
|
9188
|
-
({ task, args, resolve:
|
|
9197
|
+
({ task, args, resolve: resolve5, reject } = this._queue.shift());
|
|
9189
9198
|
cb = await (async function() {
|
|
9190
9199
|
try {
|
|
9191
9200
|
returned = await task(...args);
|
|
9192
9201
|
return function() {
|
|
9193
|
-
return
|
|
9202
|
+
return resolve5(returned);
|
|
9194
9203
|
};
|
|
9195
9204
|
} catch (error1) {
|
|
9196
9205
|
error = error1;
|
|
@@ -9205,13 +9214,13 @@ var require_light = __commonJS({
|
|
|
9205
9214
|
}
|
|
9206
9215
|
}
|
|
9207
9216
|
schedule(task, ...args) {
|
|
9208
|
-
var promise, reject,
|
|
9209
|
-
|
|
9217
|
+
var promise, reject, resolve5;
|
|
9218
|
+
resolve5 = reject = null;
|
|
9210
9219
|
promise = new this.Promise(function(_resolve, _reject) {
|
|
9211
|
-
|
|
9220
|
+
resolve5 = _resolve;
|
|
9212
9221
|
return reject = _reject;
|
|
9213
9222
|
});
|
|
9214
|
-
this._queue.push({ task, args, resolve:
|
|
9223
|
+
this._queue.push({ task, args, resolve: resolve5, reject });
|
|
9215
9224
|
this._tryToRun();
|
|
9216
9225
|
return promise;
|
|
9217
9226
|
}
|
|
@@ -9612,14 +9621,14 @@ var require_light = __commonJS({
|
|
|
9612
9621
|
counts = this._states.counts;
|
|
9613
9622
|
return counts[0] + counts[1] + counts[2] + counts[3] === at;
|
|
9614
9623
|
};
|
|
9615
|
-
return new this.Promise((
|
|
9624
|
+
return new this.Promise((resolve5, reject) => {
|
|
9616
9625
|
if (finished()) {
|
|
9617
|
-
return
|
|
9626
|
+
return resolve5();
|
|
9618
9627
|
} else {
|
|
9619
9628
|
return this.on("done", () => {
|
|
9620
9629
|
if (finished()) {
|
|
9621
9630
|
this.removeAllListeners("done");
|
|
9622
|
-
return
|
|
9631
|
+
return resolve5();
|
|
9623
9632
|
}
|
|
9624
9633
|
});
|
|
9625
9634
|
}
|
|
@@ -9712,9 +9721,9 @@ var require_light = __commonJS({
|
|
|
9712
9721
|
options = parser$5.load(options, this.jobDefaults);
|
|
9713
9722
|
}
|
|
9714
9723
|
task = (...args2) => {
|
|
9715
|
-
return new this.Promise(function(
|
|
9724
|
+
return new this.Promise(function(resolve5, reject) {
|
|
9716
9725
|
return fn(...args2, function(...args3) {
|
|
9717
|
-
return (args3[0] != null ? reject :
|
|
9726
|
+
return (args3[0] != null ? reject : resolve5)(args3);
|
|
9718
9727
|
});
|
|
9719
9728
|
});
|
|
9720
9729
|
};
|
|
@@ -9882,7 +9891,7 @@ function isAuthRequest(method, pathname) {
|
|
|
9882
9891
|
}
|
|
9883
9892
|
function routeMatcher(paths) {
|
|
9884
9893
|
const regexes = paths.map(
|
|
9885
|
-
(
|
|
9894
|
+
(path11) => path11.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
|
|
9886
9895
|
);
|
|
9887
9896
|
const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
|
|
9888
9897
|
return new RegExp(regex2, "i");
|
|
@@ -13455,25 +13464,9 @@ __export(daily_exports, {
|
|
|
13455
13464
|
groupPRsByRepo: () => groupPRsByRepo,
|
|
13456
13465
|
printDigest: () => printDigest,
|
|
13457
13466
|
runDaily: () => runDaily,
|
|
13467
|
+
runDailyForDisplay: () => runDailyForDisplay,
|
|
13458
13468
|
toShelvedPRRef: () => toShelvedPRRef
|
|
13459
13469
|
});
|
|
13460
|
-
async function runDaily(options) {
|
|
13461
|
-
const token = getGitHubToken();
|
|
13462
|
-
try {
|
|
13463
|
-
await runDailyInner(token, options);
|
|
13464
|
-
} catch (error) {
|
|
13465
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
13466
|
-
if (options.json) {
|
|
13467
|
-
outputJsonError(`Daily check failed: ${msg}`);
|
|
13468
|
-
} else {
|
|
13469
|
-
console.error(`[FATAL] Daily check failed: ${msg}`);
|
|
13470
|
-
if (error instanceof Error && error.stack) {
|
|
13471
|
-
console.error(error.stack);
|
|
13472
|
-
}
|
|
13473
|
-
}
|
|
13474
|
-
process.exit(1);
|
|
13475
|
-
}
|
|
13476
|
-
}
|
|
13477
13470
|
async function fetchPRData(prMonitor, token) {
|
|
13478
13471
|
const { prs, failures } = await prMonitor.fetchUserOpenPRs();
|
|
13479
13472
|
if (failures.length > 0) {
|
|
@@ -13796,14 +13789,13 @@ async function executeDailyCheckInternal(token) {
|
|
|
13796
13789
|
const { activePRs, shelvedPRs, digest } = partitionPRs(prMonitor, prs, recentlyClosedPRs, recentlyMergedPRs);
|
|
13797
13790
|
return generateDigestOutput(digest, activePRs, shelvedPRs, commentedIssues, failures);
|
|
13798
13791
|
}
|
|
13799
|
-
async function
|
|
13800
|
-
|
|
13801
|
-
|
|
13802
|
-
|
|
13803
|
-
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
}
|
|
13792
|
+
async function runDaily() {
|
|
13793
|
+
const token = requireGitHubToken();
|
|
13794
|
+
return executeDailyCheck(token);
|
|
13795
|
+
}
|
|
13796
|
+
async function runDailyForDisplay() {
|
|
13797
|
+
const token = requireGitHubToken();
|
|
13798
|
+
return executeDailyCheckInternal(token);
|
|
13807
13799
|
}
|
|
13808
13800
|
var init_daily = __esm({
|
|
13809
13801
|
"src/commands/daily.ts"() {
|
|
@@ -13824,39 +13816,21 @@ async function runStatus(options) {
|
|
|
13824
13816
|
const stats = stateManager2.getStats();
|
|
13825
13817
|
const state = stateManager2.getState();
|
|
13826
13818
|
const lastUpdated = state.lastDigestAt || state.lastRunAt;
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
output.lastUpdated = lastUpdated;
|
|
13836
|
-
}
|
|
13837
|
-
outputJson(output);
|
|
13838
|
-
} else {
|
|
13839
|
-
console.log("\n\u{1F4CA} OSS Status\n");
|
|
13840
|
-
console.log(`Merged PRs: ${stats.mergedPRs}`);
|
|
13841
|
-
console.log(`Closed PRs: ${stats.closedPRs}`);
|
|
13842
|
-
console.log(`Merge Rate: ${stats.mergeRate}`);
|
|
13843
|
-
console.log(`Needs Response: ${stats.needsResponse}`);
|
|
13844
|
-
if (options.offline) {
|
|
13845
|
-
console.log(`
|
|
13846
|
-
Last Updated: ${lastUpdated || "Never"}`);
|
|
13847
|
-
console.log("(Offline mode: showing cached data)");
|
|
13848
|
-
} else {
|
|
13849
|
-
console.log(`
|
|
13850
|
-
Last Run: ${state.lastRunAt || "Never"}`);
|
|
13851
|
-
}
|
|
13852
|
-
console.log("\nRun with --json for structured output");
|
|
13819
|
+
const { totalTracked: _totalTracked, ...outputStats } = stats;
|
|
13820
|
+
const output = {
|
|
13821
|
+
stats: outputStats,
|
|
13822
|
+
lastRunAt: state.lastRunAt
|
|
13823
|
+
};
|
|
13824
|
+
if (options.offline) {
|
|
13825
|
+
output.offline = true;
|
|
13826
|
+
output.lastUpdated = lastUpdated;
|
|
13853
13827
|
}
|
|
13828
|
+
return output;
|
|
13854
13829
|
}
|
|
13855
13830
|
var init_status = __esm({
|
|
13856
13831
|
"src/commands/status.ts"() {
|
|
13857
13832
|
"use strict";
|
|
13858
13833
|
init_core();
|
|
13859
|
-
init_json();
|
|
13860
13834
|
}
|
|
13861
13835
|
});
|
|
13862
13836
|
|
|
@@ -13866,94 +13840,58 @@ __export(search_exports, {
|
|
|
13866
13840
|
runSearch: () => runSearch
|
|
13867
13841
|
});
|
|
13868
13842
|
async function runSearch(options) {
|
|
13869
|
-
const token =
|
|
13843
|
+
const token = requireGitHubToken();
|
|
13870
13844
|
const discovery = new IssueDiscovery(token);
|
|
13871
|
-
if (!options.json) {
|
|
13872
|
-
console.log(`
|
|
13873
|
-
\u{1F50D} Searching for issues (max ${options.maxResults})...
|
|
13874
|
-
`);
|
|
13875
|
-
}
|
|
13876
13845
|
const candidates = await discovery.searchIssues({ maxResults: options.maxResults });
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
searchOutput.rateLimitWarning = discovery.rateLimitWarning;
|
|
13912
|
-
}
|
|
13913
|
-
outputJson(searchOutput);
|
|
13914
|
-
} else {
|
|
13915
|
-
if (candidates.length === 0) {
|
|
13916
|
-
if (discovery.rateLimitWarning) {
|
|
13917
|
-
console.warn(`
|
|
13918
|
-
\u26A0 ${discovery.rateLimitWarning}
|
|
13919
|
-
`);
|
|
13920
|
-
} else {
|
|
13921
|
-
console.log("No matching issues found.");
|
|
13922
|
-
}
|
|
13923
|
-
return;
|
|
13924
|
-
}
|
|
13925
|
-
if (discovery.rateLimitWarning) {
|
|
13926
|
-
console.warn(`
|
|
13927
|
-
\u26A0 ${discovery.rateLimitWarning}
|
|
13928
|
-
`);
|
|
13929
|
-
}
|
|
13930
|
-
console.log(`Found ${candidates.length} candidates:
|
|
13931
|
-
`);
|
|
13932
|
-
for (const candidate of candidates) {
|
|
13933
|
-
console.log(discovery.formatCandidate(candidate));
|
|
13934
|
-
console.log("---");
|
|
13935
|
-
}
|
|
13846
|
+
const stateManager2 = getStateManager();
|
|
13847
|
+
const { config } = stateManager2.getState();
|
|
13848
|
+
const excludedRepos = config.excludeRepos || [];
|
|
13849
|
+
const aiPolicyBlocklist = config.aiPolicyBlocklist ?? DEFAULT_CONFIG.aiPolicyBlocklist ?? [];
|
|
13850
|
+
const searchOutput = {
|
|
13851
|
+
candidates: candidates.map((c) => {
|
|
13852
|
+
const repoScoreRecord = stateManager2.getRepoScore(c.issue.repo);
|
|
13853
|
+
return {
|
|
13854
|
+
issue: {
|
|
13855
|
+
repo: c.issue.repo,
|
|
13856
|
+
number: c.issue.number,
|
|
13857
|
+
title: c.issue.title,
|
|
13858
|
+
url: c.issue.url,
|
|
13859
|
+
labels: c.issue.labels
|
|
13860
|
+
},
|
|
13861
|
+
recommendation: c.recommendation,
|
|
13862
|
+
reasonsToApprove: c.reasonsToApprove,
|
|
13863
|
+
reasonsToSkip: c.reasonsToSkip,
|
|
13864
|
+
searchPriority: c.searchPriority,
|
|
13865
|
+
viabilityScore: c.viabilityScore,
|
|
13866
|
+
repoScore: repoScoreRecord ? {
|
|
13867
|
+
score: repoScoreRecord.score,
|
|
13868
|
+
mergedPRCount: repoScoreRecord.mergedPRCount,
|
|
13869
|
+
closedWithoutMergeCount: repoScoreRecord.closedWithoutMergeCount,
|
|
13870
|
+
isResponsive: repoScoreRecord.signals?.isResponsive ?? false,
|
|
13871
|
+
lastMergedAt: repoScoreRecord.lastMergedAt
|
|
13872
|
+
} : void 0
|
|
13873
|
+
};
|
|
13874
|
+
}),
|
|
13875
|
+
excludedRepos,
|
|
13876
|
+
aiPolicyBlocklist
|
|
13877
|
+
};
|
|
13878
|
+
if (discovery.rateLimitWarning) {
|
|
13879
|
+
searchOutput.rateLimitWarning = discovery.rateLimitWarning;
|
|
13936
13880
|
}
|
|
13881
|
+
return searchOutput;
|
|
13937
13882
|
}
|
|
13938
13883
|
var init_search = __esm({
|
|
13939
13884
|
"src/commands/search.ts"() {
|
|
13940
13885
|
"use strict";
|
|
13941
13886
|
init_core();
|
|
13942
|
-
init_json();
|
|
13943
13887
|
}
|
|
13944
13888
|
});
|
|
13945
13889
|
|
|
13946
13890
|
// src/commands/validation.ts
|
|
13947
|
-
function validateGitHubUrl(url, pattern, entityType
|
|
13891
|
+
function validateGitHubUrl(url, pattern, entityType) {
|
|
13948
13892
|
if (pattern.test(url)) return;
|
|
13949
13893
|
const example = entityType === "PR" ? "https://github.com/owner/repo/pull/123" : "https://github.com/owner/repo/issues/123";
|
|
13950
|
-
|
|
13951
|
-
if (json) {
|
|
13952
|
-
outputJsonError(msg);
|
|
13953
|
-
} else {
|
|
13954
|
-
console.error(`Error: ${msg}`);
|
|
13955
|
-
}
|
|
13956
|
-
process.exit(1);
|
|
13894
|
+
throw new Error(`Invalid ${entityType} URL: ${url}. Expected format: ${example}`);
|
|
13957
13895
|
}
|
|
13958
13896
|
function validateUrl(url) {
|
|
13959
13897
|
if (url.length > MAX_URL_LENGTH) {
|
|
@@ -13996,7 +13934,6 @@ var init_validation = __esm({
|
|
|
13996
13934
|
"src/commands/validation.ts"() {
|
|
13997
13935
|
"use strict";
|
|
13998
13936
|
init_errors();
|
|
13999
|
-
init_json();
|
|
14000
13937
|
PR_URL_PATTERN = /^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+$/;
|
|
14001
13938
|
ISSUE_URL_PATTERN = /^https:\/\/github\.com\/[^/]+\/[^/]+\/issues\/\d+$/;
|
|
14002
13939
|
MAX_URL_LENGTH = 2048;
|
|
@@ -14014,38 +13951,28 @@ __export(vet_exports, {
|
|
|
14014
13951
|
});
|
|
14015
13952
|
async function runVet(options) {
|
|
14016
13953
|
validateUrl(options.issueUrl);
|
|
14017
|
-
const token =
|
|
13954
|
+
const token = requireGitHubToken();
|
|
14018
13955
|
const discovery = new IssueDiscovery(token);
|
|
14019
|
-
if (!options.json) {
|
|
14020
|
-
console.log(`
|
|
14021
|
-
\u{1F50D} Vetting issue: ${options.issueUrl}
|
|
14022
|
-
`);
|
|
14023
|
-
}
|
|
14024
13956
|
const candidate = await discovery.vetIssue(options.issueUrl);
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
14039
|
-
});
|
|
14040
|
-
} else {
|
|
14041
|
-
console.log(discovery.formatCandidate(candidate));
|
|
14042
|
-
}
|
|
13957
|
+
return {
|
|
13958
|
+
issue: {
|
|
13959
|
+
repo: candidate.issue.repo,
|
|
13960
|
+
number: candidate.issue.number,
|
|
13961
|
+
title: candidate.issue.title,
|
|
13962
|
+
url: candidate.issue.url,
|
|
13963
|
+
labels: candidate.issue.labels
|
|
13964
|
+
},
|
|
13965
|
+
recommendation: candidate.recommendation,
|
|
13966
|
+
reasonsToApprove: candidate.reasonsToApprove,
|
|
13967
|
+
reasonsToSkip: candidate.reasonsToSkip,
|
|
13968
|
+
projectHealth: candidate.projectHealth,
|
|
13969
|
+
vettingResult: candidate.vettingResult
|
|
13970
|
+
};
|
|
14043
13971
|
}
|
|
14044
13972
|
var init_vet = __esm({
|
|
14045
13973
|
"src/commands/vet.ts"() {
|
|
14046
13974
|
"use strict";
|
|
14047
13975
|
init_core();
|
|
14048
|
-
init_json();
|
|
14049
13976
|
init_validation();
|
|
14050
13977
|
}
|
|
14051
13978
|
});
|
|
@@ -14058,59 +13985,37 @@ __export(track_exports, {
|
|
|
14058
13985
|
});
|
|
14059
13986
|
async function runTrack(options) {
|
|
14060
13987
|
validateUrl(options.prUrl);
|
|
14061
|
-
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR"
|
|
14062
|
-
const token =
|
|
13988
|
+
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR");
|
|
13989
|
+
const token = requireGitHubToken();
|
|
14063
13990
|
const octokit = getOctokit(token);
|
|
14064
13991
|
const parsed = parseGitHubUrl(options.prUrl);
|
|
14065
13992
|
if (!parsed || parsed.type !== "pull") {
|
|
14066
|
-
|
|
14067
|
-
outputJsonError(`Invalid PR URL: ${options.prUrl}`);
|
|
14068
|
-
} else {
|
|
14069
|
-
console.error(`Error: Invalid PR URL: ${options.prUrl}`);
|
|
14070
|
-
}
|
|
14071
|
-
process.exit(1);
|
|
13993
|
+
throw new Error(`Invalid PR URL: ${options.prUrl}`);
|
|
14072
13994
|
}
|
|
14073
13995
|
const { owner, repo, number } = parsed;
|
|
14074
|
-
if (!options.json) {
|
|
14075
|
-
console.log(`
|
|
14076
|
-
\u{1F4CC} Fetching PR: ${options.prUrl}
|
|
14077
|
-
`);
|
|
14078
|
-
}
|
|
14079
13996
|
const { data: ghPR } = await octokit.pulls.get({ owner, repo, pull_number: number });
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
|
|
14083
|
-
|
|
14084
|
-
|
|
13997
|
+
return {
|
|
13998
|
+
pr: {
|
|
13999
|
+
repo: `${owner}/${repo}`,
|
|
14000
|
+
number,
|
|
14001
|
+
title: ghPR.title,
|
|
14002
|
+
url: options.prUrl
|
|
14003
|
+
}
|
|
14085
14004
|
};
|
|
14086
|
-
if (options.json) {
|
|
14087
|
-
outputJson({ pr });
|
|
14088
|
-
} else {
|
|
14089
|
-
console.log(`PR: ${pr.repo}#${pr.number} - ${pr.title}`);
|
|
14090
|
-
console.log("Note: In v2, PRs are tracked automatically via the daily run.");
|
|
14091
|
-
}
|
|
14092
14005
|
}
|
|
14093
14006
|
async function runUntrack(options) {
|
|
14094
14007
|
validateUrl(options.prUrl);
|
|
14095
|
-
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR"
|
|
14096
|
-
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
});
|
|
14102
|
-
} else {
|
|
14103
|
-
console.log(
|
|
14104
|
-
"Note: In v2, PRs are fetched fresh on each daily run \u2014 there is no local tracking list to remove from."
|
|
14105
|
-
);
|
|
14106
|
-
console.log("Use `shelve` to temporarily hide a PR from the daily summary.");
|
|
14107
|
-
}
|
|
14008
|
+
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR");
|
|
14009
|
+
return {
|
|
14010
|
+
removed: false,
|
|
14011
|
+
url: options.prUrl,
|
|
14012
|
+
message: "In v2, PRs are fetched fresh on each daily run \u2014 there is no local tracking list to remove from."
|
|
14013
|
+
};
|
|
14108
14014
|
}
|
|
14109
14015
|
var init_track = __esm({
|
|
14110
14016
|
"src/commands/track.ts"() {
|
|
14111
14017
|
"use strict";
|
|
14112
14018
|
init_core();
|
|
14113
|
-
init_json();
|
|
14114
14019
|
init_validation();
|
|
14115
14020
|
init_utils();
|
|
14116
14021
|
}
|
|
@@ -14123,30 +14028,19 @@ __export(read_exports, {
|
|
|
14123
14028
|
});
|
|
14124
14029
|
async function runRead(options) {
|
|
14125
14030
|
if (!options.all && !options.prUrl) {
|
|
14126
|
-
|
|
14127
|
-
outputJsonError("PR URL or --all flag required");
|
|
14128
|
-
} else {
|
|
14129
|
-
console.error("Usage: oss-autopilot read <pr-url> or oss-autopilot read --all");
|
|
14130
|
-
}
|
|
14131
|
-
process.exit(1);
|
|
14031
|
+
throw new Error("PR URL or --all flag required");
|
|
14132
14032
|
}
|
|
14133
14033
|
if (options.prUrl) {
|
|
14134
14034
|
validateUrl(options.prUrl);
|
|
14135
14035
|
}
|
|
14136
|
-
if (options.
|
|
14137
|
-
|
|
14138
|
-
outputJson({ markedAsRead: 0, all: true, message: "In v2, PR read state is not tracked locally." });
|
|
14139
|
-
} else {
|
|
14140
|
-
outputJson({ marked: false, url: options.prUrl, message: "In v2, PR read state is not tracked locally." });
|
|
14141
|
-
}
|
|
14142
|
-
} else {
|
|
14143
|
-
console.log("Note: In v2, PR read state is not tracked locally. PRs are fetched fresh on each daily run.");
|
|
14036
|
+
if (options.all) {
|
|
14037
|
+
return { markedAsRead: 0, all: true, message: "In v2, PR read state is not tracked locally." };
|
|
14144
14038
|
}
|
|
14039
|
+
return { marked: false, url: options.prUrl, message: "In v2, PR read state is not tracked locally." };
|
|
14145
14040
|
}
|
|
14146
14041
|
var init_read = __esm({
|
|
14147
14042
|
"src/commands/read.ts"() {
|
|
14148
14043
|
"use strict";
|
|
14149
|
-
init_json();
|
|
14150
14044
|
init_validation();
|
|
14151
14045
|
}
|
|
14152
14046
|
});
|
|
@@ -14160,17 +14054,12 @@ __export(comments_exports, {
|
|
|
14160
14054
|
});
|
|
14161
14055
|
async function runComments(options) {
|
|
14162
14056
|
validateUrl(options.prUrl);
|
|
14163
|
-
const token =
|
|
14057
|
+
const token = requireGitHubToken();
|
|
14164
14058
|
const stateManager2 = getStateManager();
|
|
14165
14059
|
const octokit = getOctokit(token);
|
|
14166
14060
|
const parsed = parseGitHubUrl(options.prUrl);
|
|
14167
14061
|
if (!parsed || parsed.type !== "pull") {
|
|
14168
|
-
|
|
14169
|
-
outputJsonError("Invalid PR URL format");
|
|
14170
|
-
} else {
|
|
14171
|
-
console.error("Invalid PR URL format");
|
|
14172
|
-
}
|
|
14173
|
-
process.exit(1);
|
|
14062
|
+
throw new Error("Invalid PR URL format");
|
|
14174
14063
|
}
|
|
14175
14064
|
const { owner, repo, number: pull_number } = parsed;
|
|
14176
14065
|
const { data: pr } = await octokit.pulls.get({ owner, repo, pull_number });
|
|
@@ -14211,240 +14100,104 @@ async function runComments(options) {
|
|
|
14211
14100
|
const relevantReviewComments = reviewComments.filter(filterComment).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
14212
14101
|
const relevantIssueComments = issueComments.filter(filterComment).sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
14213
14102
|
const relevantReviews = reviews.filter((r) => filterComment(r) && r.body && r.body.trim()).sort((a, b) => new Date(b.submitted_at || 0).getTime() - new Date(a.submitted_at || 0).getTime());
|
|
14214
|
-
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
discussionCommentCount: relevantIssueComments.length
|
|
14245
|
-
}
|
|
14246
|
-
});
|
|
14247
|
-
return;
|
|
14248
|
-
}
|
|
14249
|
-
console.log(`
|
|
14250
|
-
\u{1F4AC} Fetching comments for: ${options.prUrl}
|
|
14251
|
-
`);
|
|
14252
|
-
console.log(`## ${pr.title}
|
|
14253
|
-
`);
|
|
14254
|
-
console.log(`**Status:** ${pr.state} | **Mergeable:** ${pr.mergeable ?? "checking..."}`);
|
|
14255
|
-
console.log(`**Branch:** ${pr.head.ref} \u2192 ${pr.base.ref}`);
|
|
14256
|
-
console.log(`**URL:** ${pr.html_url}
|
|
14257
|
-
`);
|
|
14258
|
-
if (relevantReviews.length > 0) {
|
|
14259
|
-
console.log("### Reviews (newest first)\n");
|
|
14260
|
-
for (const review of relevantReviews) {
|
|
14261
|
-
const state = review.state === "APPROVED" ? "\u2705" : review.state === "CHANGES_REQUESTED" ? "\u274C" : "\u{1F4AC}";
|
|
14262
|
-
const time = review.submitted_at ? formatRelativeTime(review.submitted_at) : "";
|
|
14263
|
-
console.log(`${state} **@${review.user?.login}** (${review.state}) - ${time}`);
|
|
14264
|
-
if (review.body) {
|
|
14265
|
-
console.log(`> ${review.body.split("\n").join("\n> ")}
|
|
14266
|
-
`);
|
|
14267
|
-
}
|
|
14268
|
-
}
|
|
14269
|
-
}
|
|
14270
|
-
if (relevantReviewComments.length > 0) {
|
|
14271
|
-
console.log("### Inline Comments (newest first)\n");
|
|
14272
|
-
for (const comment of relevantReviewComments) {
|
|
14273
|
-
const time = formatRelativeTime(comment.created_at);
|
|
14274
|
-
console.log(`**@${comment.user?.login}** on \`${comment.path}\` - ${time}`);
|
|
14275
|
-
console.log(`> ${comment.body.split("\n").join("\n> ")}`);
|
|
14276
|
-
if (comment.diff_hunk) {
|
|
14277
|
-
console.log(`\`\`\`diff
|
|
14278
|
-
${comment.diff_hunk.slice(-500)}
|
|
14279
|
-
\`\`\``);
|
|
14280
|
-
}
|
|
14281
|
-
console.log("");
|
|
14282
|
-
}
|
|
14283
|
-
}
|
|
14284
|
-
if (relevantIssueComments.length > 0) {
|
|
14285
|
-
console.log("### Discussion (newest first)\n");
|
|
14286
|
-
for (const comment of relevantIssueComments) {
|
|
14287
|
-
const time = formatRelativeTime(comment.created_at);
|
|
14288
|
-
console.log(`**@${comment.user?.login}** - ${time}`);
|
|
14289
|
-
console.log(`> ${comment.body?.split("\n").join("\n> ")}
|
|
14290
|
-
`);
|
|
14103
|
+
return {
|
|
14104
|
+
pr: {
|
|
14105
|
+
title: pr.title,
|
|
14106
|
+
state: pr.state,
|
|
14107
|
+
mergeable: pr.mergeable,
|
|
14108
|
+
head: pr.head.ref,
|
|
14109
|
+
base: pr.base.ref,
|
|
14110
|
+
url: pr.html_url
|
|
14111
|
+
},
|
|
14112
|
+
reviews: relevantReviews.map((r) => ({
|
|
14113
|
+
user: r.user?.login,
|
|
14114
|
+
state: r.state,
|
|
14115
|
+
body: r.body ?? null,
|
|
14116
|
+
submittedAt: r.submitted_at ?? null
|
|
14117
|
+
})),
|
|
14118
|
+
reviewComments: relevantReviewComments.map((c) => ({
|
|
14119
|
+
user: c.user?.login,
|
|
14120
|
+
body: c.body,
|
|
14121
|
+
path: c.path,
|
|
14122
|
+
createdAt: c.created_at
|
|
14123
|
+
})),
|
|
14124
|
+
issueComments: relevantIssueComments.map((c) => ({
|
|
14125
|
+
user: c.user?.login,
|
|
14126
|
+
body: c.body,
|
|
14127
|
+
createdAt: c.created_at
|
|
14128
|
+
})),
|
|
14129
|
+
summary: {
|
|
14130
|
+
reviewCount: relevantReviews.length,
|
|
14131
|
+
inlineCommentCount: relevantReviewComments.length,
|
|
14132
|
+
discussionCommentCount: relevantIssueComments.length
|
|
14291
14133
|
}
|
|
14292
|
-
}
|
|
14293
|
-
if (relevantReviewComments.length === 0 && relevantIssueComments.length === 0 && relevantReviews.length === 0) {
|
|
14294
|
-
console.log("No comments from other users.\n");
|
|
14295
|
-
}
|
|
14296
|
-
console.log("---");
|
|
14297
|
-
console.log(
|
|
14298
|
-
`**Summary:** ${relevantReviews.length} reviews, ${relevantReviewComments.length} inline comments, ${relevantIssueComments.length} discussion comments`
|
|
14299
|
-
);
|
|
14134
|
+
};
|
|
14300
14135
|
}
|
|
14301
14136
|
async function runPost(options) {
|
|
14302
14137
|
validateUrl(options.url);
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
if (options.stdin) {
|
|
14306
|
-
const chunks = [];
|
|
14307
|
-
for await (const chunk of process.stdin) {
|
|
14308
|
-
chunks.push(chunk);
|
|
14309
|
-
}
|
|
14310
|
-
message = Buffer.concat(chunks).toString("utf-8").trim();
|
|
14311
|
-
}
|
|
14312
|
-
if (!message) {
|
|
14313
|
-
if (options.json) {
|
|
14314
|
-
outputJsonError("No message provided");
|
|
14315
|
-
} else {
|
|
14316
|
-
console.error("Error: No message provided");
|
|
14317
|
-
}
|
|
14318
|
-
process.exit(1);
|
|
14319
|
-
}
|
|
14320
|
-
try {
|
|
14321
|
-
validateMessage(message);
|
|
14322
|
-
} catch (error) {
|
|
14323
|
-
if (options.json) {
|
|
14324
|
-
outputJsonError(error instanceof Error ? error.message : "Invalid message");
|
|
14325
|
-
} else {
|
|
14326
|
-
console.error(`Error: ${error instanceof Error ? error.message : "Invalid message"}`);
|
|
14327
|
-
}
|
|
14328
|
-
process.exit(1);
|
|
14138
|
+
if (!options.message.trim()) {
|
|
14139
|
+
throw new Error("No message provided");
|
|
14329
14140
|
}
|
|
14141
|
+
validateMessage(options.message);
|
|
14142
|
+
const token = requireGitHubToken();
|
|
14330
14143
|
const parsed = parseGitHubUrl(options.url);
|
|
14331
14144
|
if (!parsed) {
|
|
14332
|
-
|
|
14333
|
-
outputJsonError("Invalid GitHub URL format");
|
|
14334
|
-
} else {
|
|
14335
|
-
console.error("Invalid GitHub URL format");
|
|
14336
|
-
}
|
|
14337
|
-
process.exit(1);
|
|
14145
|
+
throw new Error("Invalid GitHub URL format");
|
|
14338
14146
|
}
|
|
14339
14147
|
const { owner, repo, number } = parsed;
|
|
14340
14148
|
const octokit = getOctokit(token);
|
|
14341
|
-
|
|
14342
|
-
|
|
14343
|
-
|
|
14344
|
-
|
|
14345
|
-
|
|
14346
|
-
}
|
|
14347
|
-
|
|
14348
|
-
|
|
14349
|
-
|
|
14350
|
-
|
|
14351
|
-
issue_number: number,
|
|
14352
|
-
body: message
|
|
14353
|
-
});
|
|
14354
|
-
if (options.json) {
|
|
14355
|
-
outputJson({
|
|
14356
|
-
commentUrl: comment.html_url,
|
|
14357
|
-
url: options.url
|
|
14358
|
-
});
|
|
14359
|
-
} else {
|
|
14360
|
-
console.log("\u2705 Comment posted successfully!");
|
|
14361
|
-
console.log(` ${comment.html_url}`);
|
|
14362
|
-
}
|
|
14363
|
-
} catch (error) {
|
|
14364
|
-
if (options.json) {
|
|
14365
|
-
outputJsonError(error instanceof Error ? error.message : "Unknown error");
|
|
14366
|
-
} else {
|
|
14367
|
-
console.error("\u274C Failed to post comment:", error instanceof Error ? error.message : error);
|
|
14368
|
-
}
|
|
14369
|
-
process.exit(1);
|
|
14370
|
-
}
|
|
14149
|
+
const { data: comment } = await octokit.issues.createComment({
|
|
14150
|
+
owner,
|
|
14151
|
+
repo,
|
|
14152
|
+
issue_number: number,
|
|
14153
|
+
body: options.message
|
|
14154
|
+
});
|
|
14155
|
+
return {
|
|
14156
|
+
commentUrl: comment.html_url,
|
|
14157
|
+
url: options.url
|
|
14158
|
+
};
|
|
14371
14159
|
}
|
|
14372
14160
|
async function runClaim(options) {
|
|
14373
14161
|
validateUrl(options.issueUrl);
|
|
14374
|
-
const token =
|
|
14162
|
+
const token = requireGitHubToken();
|
|
14375
14163
|
const message = options.message || "Hi! I'd like to work on this issue. Could you assign it to me?";
|
|
14376
|
-
|
|
14377
|
-
validateMessage(message);
|
|
14378
|
-
} catch (error) {
|
|
14379
|
-
if (options.json) {
|
|
14380
|
-
outputJsonError(error instanceof Error ? error.message : "Invalid message");
|
|
14381
|
-
} else {
|
|
14382
|
-
console.error(`Error: ${error instanceof Error ? error.message : "Invalid message"}`);
|
|
14383
|
-
}
|
|
14384
|
-
process.exit(1);
|
|
14385
|
-
}
|
|
14164
|
+
validateMessage(message);
|
|
14386
14165
|
const parsed = parseGitHubUrl(options.issueUrl);
|
|
14387
14166
|
if (!parsed || parsed.type !== "issues") {
|
|
14388
|
-
|
|
14389
|
-
outputJsonError("Invalid issue URL format (must be an issue, not a PR)");
|
|
14390
|
-
} else {
|
|
14391
|
-
console.error("Invalid issue URL format (must be an issue, not a PR)");
|
|
14392
|
-
}
|
|
14393
|
-
process.exit(1);
|
|
14167
|
+
throw new Error("Invalid issue URL format (must be an issue, not a PR)");
|
|
14394
14168
|
}
|
|
14395
14169
|
const { owner, repo, number } = parsed;
|
|
14396
|
-
if (!options.json) {
|
|
14397
|
-
console.log("\n\u{1F64B} Claiming issue:", options.issueUrl);
|
|
14398
|
-
console.log("---");
|
|
14399
|
-
console.log(message);
|
|
14400
|
-
console.log("---\n");
|
|
14401
|
-
}
|
|
14402
14170
|
const octokit = getOctokit(token);
|
|
14403
|
-
|
|
14404
|
-
|
|
14405
|
-
|
|
14406
|
-
|
|
14407
|
-
|
|
14408
|
-
|
|
14409
|
-
|
|
14410
|
-
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
issueUrl: options.issueUrl
|
|
14428
|
-
});
|
|
14429
|
-
} else {
|
|
14430
|
-
console.log("\u2705 Issue claimed!");
|
|
14431
|
-
console.log(` ${comment.html_url}`);
|
|
14432
|
-
}
|
|
14433
|
-
} catch (error) {
|
|
14434
|
-
if (options.json) {
|
|
14435
|
-
outputJsonError(error instanceof Error ? error.message : "Unknown error");
|
|
14436
|
-
} else {
|
|
14437
|
-
console.error("\u274C Failed to claim issue:", error instanceof Error ? error.message : error);
|
|
14438
|
-
}
|
|
14439
|
-
process.exit(1);
|
|
14440
|
-
}
|
|
14171
|
+
const { data: comment } = await octokit.issues.createComment({
|
|
14172
|
+
owner,
|
|
14173
|
+
repo,
|
|
14174
|
+
issue_number: number,
|
|
14175
|
+
body: message
|
|
14176
|
+
});
|
|
14177
|
+
const stateManager2 = getStateManager();
|
|
14178
|
+
stateManager2.addIssue({
|
|
14179
|
+
id: number,
|
|
14180
|
+
url: options.issueUrl,
|
|
14181
|
+
repo: `${owner}/${repo}`,
|
|
14182
|
+
number,
|
|
14183
|
+
title: "(claimed)",
|
|
14184
|
+
status: "claimed",
|
|
14185
|
+
labels: [],
|
|
14186
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14187
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14188
|
+
vetted: false
|
|
14189
|
+
});
|
|
14190
|
+
stateManager2.save();
|
|
14191
|
+
return {
|
|
14192
|
+
commentUrl: comment.html_url,
|
|
14193
|
+
issueUrl: options.issueUrl
|
|
14194
|
+
};
|
|
14441
14195
|
}
|
|
14442
14196
|
var init_comments = __esm({
|
|
14443
14197
|
"src/commands/comments.ts"() {
|
|
14444
14198
|
"use strict";
|
|
14445
14199
|
init_core();
|
|
14446
14200
|
init_pagination();
|
|
14447
|
-
init_json();
|
|
14448
14201
|
init_validation();
|
|
14449
14202
|
}
|
|
14450
14203
|
});
|
|
@@ -14454,28 +14207,14 @@ var config_exports = {};
|
|
|
14454
14207
|
__export(config_exports, {
|
|
14455
14208
|
runConfig: () => runConfig
|
|
14456
14209
|
});
|
|
14457
|
-
function exitWithError(msg, json) {
|
|
14458
|
-
if (json) {
|
|
14459
|
-
outputJsonError(msg);
|
|
14460
|
-
} else {
|
|
14461
|
-
console.error(msg);
|
|
14462
|
-
}
|
|
14463
|
-
process.exit(1);
|
|
14464
|
-
}
|
|
14465
14210
|
async function runConfig(options) {
|
|
14466
14211
|
const stateManager2 = getStateManager();
|
|
14467
14212
|
const currentConfig = stateManager2.getState().config;
|
|
14468
14213
|
if (!options.key) {
|
|
14469
|
-
|
|
14470
|
-
outputJson({ config: currentConfig });
|
|
14471
|
-
} else {
|
|
14472
|
-
console.log("\n\u2699\uFE0F Current Configuration:\n");
|
|
14473
|
-
console.log(JSON.stringify(currentConfig, null, 2));
|
|
14474
|
-
}
|
|
14475
|
-
return;
|
|
14214
|
+
return { config: currentConfig };
|
|
14476
14215
|
}
|
|
14477
14216
|
if (!options.value) {
|
|
14478
|
-
|
|
14217
|
+
throw new Error("Value required");
|
|
14479
14218
|
}
|
|
14480
14219
|
const value = options.value;
|
|
14481
14220
|
switch (options.key) {
|
|
@@ -14495,9 +14234,8 @@ async function runConfig(options) {
|
|
|
14495
14234
|
case "exclude-repo": {
|
|
14496
14235
|
const parts = value.split("/");
|
|
14497
14236
|
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
14498
|
-
|
|
14499
|
-
`Invalid repo format "${value}". Use "owner/repo" format. To exclude an entire org, use: config exclude-org ${value}
|
|
14500
|
-
options.json
|
|
14237
|
+
throw new Error(
|
|
14238
|
+
`Invalid repo format "${value}". Use "owner/repo" format. To exclude an entire org, use: config exclude-org ${value}`
|
|
14501
14239
|
);
|
|
14502
14240
|
}
|
|
14503
14241
|
const valueLower = value.toLowerCase();
|
|
@@ -14509,9 +14247,8 @@ async function runConfig(options) {
|
|
|
14509
14247
|
}
|
|
14510
14248
|
case "exclude-org": {
|
|
14511
14249
|
if (value.includes("/")) {
|
|
14512
|
-
|
|
14513
|
-
`Invalid org name "${value}". Use just the org name (e.g., "facebook"), not "owner/repo" format. To exclude a specific repo, use: config exclude-repo ${value}
|
|
14514
|
-
options.json
|
|
14250
|
+
throw new Error(
|
|
14251
|
+
`Invalid org name "${value}". Use just the org name (e.g., "facebook"), not "owner/repo" format. To exclude a specific repo, use: config exclude-repo ${value}`
|
|
14515
14252
|
);
|
|
14516
14253
|
}
|
|
14517
14254
|
const currentOrgs = currentConfig.excludeOrgs ?? [];
|
|
@@ -14522,20 +14259,15 @@ async function runConfig(options) {
|
|
|
14522
14259
|
break;
|
|
14523
14260
|
}
|
|
14524
14261
|
default:
|
|
14525
|
-
|
|
14262
|
+
throw new Error(`Unknown config key: ${options.key}`);
|
|
14526
14263
|
}
|
|
14527
14264
|
stateManager2.save();
|
|
14528
|
-
|
|
14529
|
-
outputJson({ success: true, key: options.key, value });
|
|
14530
|
-
} else {
|
|
14531
|
-
console.log(`Set ${options.key} to: ${value}`);
|
|
14532
|
-
}
|
|
14265
|
+
return { success: true, key: options.key, value };
|
|
14533
14266
|
}
|
|
14534
14267
|
var init_config = __esm({
|
|
14535
14268
|
"src/commands/config.ts"() {
|
|
14536
14269
|
"use strict";
|
|
14537
14270
|
init_core();
|
|
14538
|
-
init_json();
|
|
14539
14271
|
}
|
|
14540
14272
|
});
|
|
14541
14273
|
|
|
@@ -14547,28 +14279,17 @@ __export(init_exports, {
|
|
|
14547
14279
|
async function runInit(options) {
|
|
14548
14280
|
validateGitHubUsername(options.username);
|
|
14549
14281
|
const stateManager2 = getStateManager();
|
|
14550
|
-
if (!options.json) {
|
|
14551
|
-
console.log(`
|
|
14552
|
-
\u{1F680} Initializing for @${options.username}...
|
|
14553
|
-
`);
|
|
14554
|
-
}
|
|
14555
14282
|
stateManager2.updateConfig({ githubUsername: options.username });
|
|
14556
14283
|
stateManager2.save();
|
|
14557
|
-
|
|
14558
|
-
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
});
|
|
14562
|
-
} else {
|
|
14563
|
-
console.log(`Username set to @${options.username}.`);
|
|
14564
|
-
console.log("Run `oss-autopilot daily` to fetch your open PRs from GitHub.");
|
|
14565
|
-
}
|
|
14284
|
+
return {
|
|
14285
|
+
username: options.username,
|
|
14286
|
+
message: "Username saved. Run `daily` to fetch your open PRs from GitHub."
|
|
14287
|
+
};
|
|
14566
14288
|
}
|
|
14567
14289
|
var init_init = __esm({
|
|
14568
14290
|
"src/commands/init.ts"() {
|
|
14569
14291
|
"use strict";
|
|
14570
14292
|
init_core();
|
|
14571
|
-
init_json();
|
|
14572
14293
|
init_validation();
|
|
14573
14294
|
}
|
|
14574
14295
|
});
|
|
@@ -14584,6 +14305,7 @@ async function runSetup(options) {
|
|
|
14584
14305
|
const config = stateManager2.getState().config;
|
|
14585
14306
|
if (options.set && options.set.length > 0) {
|
|
14586
14307
|
const results = {};
|
|
14308
|
+
const warnings = [];
|
|
14587
14309
|
for (const setting of options.set) {
|
|
14588
14310
|
const [key, ...valueParts] = setting.split("=");
|
|
14589
14311
|
const value = valueParts.join("=");
|
|
@@ -14649,15 +14371,11 @@ async function runSetup(options) {
|
|
|
14649
14371
|
}
|
|
14650
14372
|
}
|
|
14651
14373
|
if (invalid.length > 0) {
|
|
14652
|
-
|
|
14653
|
-
console.warn(`Warning: Skipping invalid entries (expected "owner/repo" format): ${invalid.join(", ")}`);
|
|
14654
|
-
}
|
|
14374
|
+
warnings.push(`Warning: Skipping invalid entries (expected "owner/repo" format): ${invalid.join(", ")}`);
|
|
14655
14375
|
results["aiPolicyBlocklist_invalidEntries"] = invalid.join(", ");
|
|
14656
14376
|
}
|
|
14657
14377
|
if (valid.length === 0 && entries.length > 0) {
|
|
14658
|
-
|
|
14659
|
-
console.warn("Warning: All entries were invalid. Blocklist not updated.");
|
|
14660
|
-
}
|
|
14378
|
+
warnings.push("Warning: All entries were invalid. Blocklist not updated.");
|
|
14661
14379
|
results[key] = "(all entries invalid)";
|
|
14662
14380
|
break;
|
|
14663
14381
|
}
|
|
@@ -14672,175 +14390,91 @@ async function runSetup(options) {
|
|
|
14672
14390
|
}
|
|
14673
14391
|
break;
|
|
14674
14392
|
default:
|
|
14675
|
-
|
|
14676
|
-
console.warn(`Unknown setting: ${key}`);
|
|
14677
|
-
}
|
|
14393
|
+
warnings.push(`Unknown setting: ${key}`);
|
|
14678
14394
|
}
|
|
14679
14395
|
}
|
|
14680
14396
|
stateManager2.save();
|
|
14681
|
-
|
|
14682
|
-
outputJson({ success: true, settings: results });
|
|
14683
|
-
} else {
|
|
14684
|
-
for (const [key, value] of Object.entries(results)) {
|
|
14685
|
-
console.log(`\u2713 ${key}: ${value}`);
|
|
14686
|
-
}
|
|
14687
|
-
}
|
|
14688
|
-
return;
|
|
14397
|
+
return { success: true, settings: results, warnings: warnings.length > 0 ? warnings : void 0 };
|
|
14689
14398
|
}
|
|
14690
14399
|
if (config.setupComplete && !options.reset) {
|
|
14691
|
-
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14696
|
-
|
|
14697
|
-
|
|
14698
|
-
|
|
14699
|
-
|
|
14700
|
-
|
|
14701
|
-
|
|
14702
|
-
});
|
|
14703
|
-
} else {
|
|
14704
|
-
console.log("\n\u2699\uFE0F OSS Autopilot Setup\n");
|
|
14705
|
-
console.log("\u2713 Setup already complete!\n");
|
|
14706
|
-
console.log("Current settings:");
|
|
14707
|
-
console.log(` GitHub username: ${config.githubUsername || "(not set)"}`);
|
|
14708
|
-
console.log(` Max active PRs: ${config.maxActivePRs}`);
|
|
14709
|
-
console.log(` Dormant threshold: ${config.dormantThresholdDays} days`);
|
|
14710
|
-
console.log(` Approaching dormant: ${config.approachingDormantDays} days`);
|
|
14711
|
-
console.log(` Languages: ${config.languages.join(", ")}`);
|
|
14712
|
-
console.log(` Labels: ${config.labels.join(", ")}`);
|
|
14713
|
-
console.log(`
|
|
14714
|
-
Run 'setup --reset' to reconfigure.`);
|
|
14715
|
-
}
|
|
14716
|
-
return;
|
|
14717
|
-
}
|
|
14718
|
-
if (options.json) {
|
|
14719
|
-
outputJson({
|
|
14720
|
-
setupRequired: true,
|
|
14721
|
-
prompts: [
|
|
14722
|
-
{
|
|
14723
|
-
setting: "username",
|
|
14724
|
-
prompt: "What is your GitHub username?",
|
|
14725
|
-
current: config.githubUsername || null,
|
|
14726
|
-
required: true,
|
|
14727
|
-
type: "string"
|
|
14728
|
-
},
|
|
14729
|
-
{
|
|
14730
|
-
setting: "maxActivePRs",
|
|
14731
|
-
prompt: "How many PRs do you want to work on at once?",
|
|
14732
|
-
current: config.maxActivePRs,
|
|
14733
|
-
default: 10,
|
|
14734
|
-
type: "number"
|
|
14735
|
-
},
|
|
14736
|
-
{
|
|
14737
|
-
setting: "dormantDays",
|
|
14738
|
-
prompt: "After how many days of inactivity should a PR be considered dormant?",
|
|
14739
|
-
current: config.dormantThresholdDays,
|
|
14740
|
-
default: 30,
|
|
14741
|
-
type: "number"
|
|
14742
|
-
},
|
|
14743
|
-
{
|
|
14744
|
-
setting: "approachingDays",
|
|
14745
|
-
prompt: "At how many days should we warn about approaching dormancy?",
|
|
14746
|
-
current: config.approachingDormantDays,
|
|
14747
|
-
default: 25,
|
|
14748
|
-
type: "number"
|
|
14749
|
-
},
|
|
14750
|
-
{
|
|
14751
|
-
setting: "languages",
|
|
14752
|
-
prompt: "What programming languages do you want to contribute to?",
|
|
14753
|
-
current: config.languages,
|
|
14754
|
-
default: ["typescript", "javascript"],
|
|
14755
|
-
type: "list"
|
|
14756
|
-
},
|
|
14757
|
-
{
|
|
14758
|
-
setting: "labels",
|
|
14759
|
-
prompt: "What issue labels should we search for?",
|
|
14760
|
-
current: config.labels,
|
|
14761
|
-
default: ["good first issue", "help wanted"],
|
|
14762
|
-
type: "list"
|
|
14763
|
-
},
|
|
14764
|
-
{
|
|
14765
|
-
setting: "aiPolicyBlocklist",
|
|
14766
|
-
prompt: "Repos with anti-AI contribution policies to block (owner/repo, comma-separated)?",
|
|
14767
|
-
current: config.aiPolicyBlocklist ?? DEFAULT_CONFIG.aiPolicyBlocklist,
|
|
14768
|
-
default: ["matplotlib/matplotlib"],
|
|
14769
|
-
type: "list"
|
|
14770
|
-
}
|
|
14771
|
-
]
|
|
14772
|
-
});
|
|
14773
|
-
} else {
|
|
14774
|
-
console.log("\n\u2699\uFE0F OSS Autopilot Setup\n");
|
|
14775
|
-
console.log("SETUP_REQUIRED");
|
|
14776
|
-
console.log("---");
|
|
14777
|
-
console.log("Please configure the following settings:\n");
|
|
14778
|
-
console.log("SETTING: username");
|
|
14779
|
-
console.log("PROMPT: What is your GitHub username?");
|
|
14780
|
-
console.log(`CURRENT: ${config.githubUsername || "(not set)"}`);
|
|
14781
|
-
console.log("REQUIRED: true");
|
|
14782
|
-
console.log("");
|
|
14783
|
-
console.log("SETTING: maxActivePRs");
|
|
14784
|
-
console.log("PROMPT: How many PRs do you want to work on at once?");
|
|
14785
|
-
console.log(`CURRENT: ${config.maxActivePRs}`);
|
|
14786
|
-
console.log("DEFAULT: 10");
|
|
14787
|
-
console.log("TYPE: number");
|
|
14788
|
-
console.log("");
|
|
14789
|
-
console.log("SETTING: dormantDays");
|
|
14790
|
-
console.log("PROMPT: After how many days of inactivity should a PR be considered dormant?");
|
|
14791
|
-
console.log(`CURRENT: ${config.dormantThresholdDays}`);
|
|
14792
|
-
console.log("DEFAULT: 30");
|
|
14793
|
-
console.log("TYPE: number");
|
|
14794
|
-
console.log("");
|
|
14795
|
-
console.log("SETTING: approachingDays");
|
|
14796
|
-
console.log("PROMPT: At how many days should we warn about approaching dormancy?");
|
|
14797
|
-
console.log(`CURRENT: ${config.approachingDormantDays}`);
|
|
14798
|
-
console.log("DEFAULT: 25");
|
|
14799
|
-
console.log("TYPE: number");
|
|
14800
|
-
console.log("");
|
|
14801
|
-
console.log("SETTING: languages");
|
|
14802
|
-
console.log("PROMPT: What programming languages do you want to contribute to? (comma-separated)");
|
|
14803
|
-
console.log(`CURRENT: ${config.languages.join(", ")}`);
|
|
14804
|
-
console.log("DEFAULT: typescript, javascript");
|
|
14805
|
-
console.log("TYPE: list");
|
|
14806
|
-
console.log("");
|
|
14807
|
-
console.log("SETTING: labels");
|
|
14808
|
-
console.log("PROMPT: What issue labels should we search for? (comma-separated)");
|
|
14809
|
-
console.log(`CURRENT: ${config.labels.join(", ")}`);
|
|
14810
|
-
console.log("DEFAULT: good first issue, help wanted");
|
|
14811
|
-
console.log("TYPE: list");
|
|
14812
|
-
console.log("");
|
|
14813
|
-
console.log("SETTING: aiPolicyBlocklist");
|
|
14814
|
-
console.log("PROMPT: Repos with anti-AI contribution policies to block? (owner/repo, comma-separated)");
|
|
14815
|
-
console.log(`CURRENT: ${(config.aiPolicyBlocklist ?? DEFAULT_CONFIG.aiPolicyBlocklist ?? []).join(", ")}`);
|
|
14816
|
-
console.log("DEFAULT: matplotlib/matplotlib");
|
|
14817
|
-
console.log("TYPE: list");
|
|
14818
|
-
console.log("");
|
|
14819
|
-
console.log("---");
|
|
14820
|
-
console.log("END_SETUP_PROMPTS");
|
|
14400
|
+
return {
|
|
14401
|
+
setupComplete: true,
|
|
14402
|
+
config: {
|
|
14403
|
+
githubUsername: config.githubUsername,
|
|
14404
|
+
maxActivePRs: config.maxActivePRs,
|
|
14405
|
+
dormantThresholdDays: config.dormantThresholdDays,
|
|
14406
|
+
approachingDormantDays: config.approachingDormantDays,
|
|
14407
|
+
languages: config.languages,
|
|
14408
|
+
labels: config.labels
|
|
14409
|
+
}
|
|
14410
|
+
};
|
|
14821
14411
|
}
|
|
14412
|
+
return {
|
|
14413
|
+
setupRequired: true,
|
|
14414
|
+
prompts: [
|
|
14415
|
+
{
|
|
14416
|
+
setting: "username",
|
|
14417
|
+
prompt: "What is your GitHub username?",
|
|
14418
|
+
current: config.githubUsername || null,
|
|
14419
|
+
required: true,
|
|
14420
|
+
type: "string"
|
|
14421
|
+
},
|
|
14422
|
+
{
|
|
14423
|
+
setting: "maxActivePRs",
|
|
14424
|
+
prompt: "How many PRs do you want to work on at once?",
|
|
14425
|
+
current: config.maxActivePRs,
|
|
14426
|
+
default: 10,
|
|
14427
|
+
type: "number"
|
|
14428
|
+
},
|
|
14429
|
+
{
|
|
14430
|
+
setting: "dormantDays",
|
|
14431
|
+
prompt: "After how many days of inactivity should a PR be considered dormant?",
|
|
14432
|
+
current: config.dormantThresholdDays,
|
|
14433
|
+
default: 30,
|
|
14434
|
+
type: "number"
|
|
14435
|
+
},
|
|
14436
|
+
{
|
|
14437
|
+
setting: "approachingDays",
|
|
14438
|
+
prompt: "At how many days should we warn about approaching dormancy?",
|
|
14439
|
+
current: config.approachingDormantDays,
|
|
14440
|
+
default: 25,
|
|
14441
|
+
type: "number"
|
|
14442
|
+
},
|
|
14443
|
+
{
|
|
14444
|
+
setting: "languages",
|
|
14445
|
+
prompt: "What programming languages do you want to contribute to?",
|
|
14446
|
+
current: config.languages,
|
|
14447
|
+
default: ["typescript", "javascript"],
|
|
14448
|
+
type: "list"
|
|
14449
|
+
},
|
|
14450
|
+
{
|
|
14451
|
+
setting: "labels",
|
|
14452
|
+
prompt: "What issue labels should we search for?",
|
|
14453
|
+
current: config.labels,
|
|
14454
|
+
default: ["good first issue", "help wanted"],
|
|
14455
|
+
type: "list"
|
|
14456
|
+
},
|
|
14457
|
+
{
|
|
14458
|
+
setting: "aiPolicyBlocklist",
|
|
14459
|
+
prompt: "Repos with anti-AI contribution policies to block (owner/repo, comma-separated)?",
|
|
14460
|
+
current: config.aiPolicyBlocklist ?? DEFAULT_CONFIG.aiPolicyBlocklist ?? null,
|
|
14461
|
+
default: ["matplotlib/matplotlib"],
|
|
14462
|
+
type: "list"
|
|
14463
|
+
}
|
|
14464
|
+
]
|
|
14465
|
+
};
|
|
14822
14466
|
}
|
|
14823
|
-
async function runCheckSetup(
|
|
14467
|
+
async function runCheckSetup() {
|
|
14824
14468
|
const stateManager2 = getStateManager();
|
|
14825
|
-
|
|
14826
|
-
|
|
14827
|
-
|
|
14828
|
-
|
|
14829
|
-
});
|
|
14830
|
-
} else {
|
|
14831
|
-
if (stateManager2.isSetupComplete()) {
|
|
14832
|
-
console.log("SETUP_COMPLETE");
|
|
14833
|
-
console.log(`username=${stateManager2.getState().config.githubUsername}`);
|
|
14834
|
-
} else {
|
|
14835
|
-
console.log("SETUP_INCOMPLETE");
|
|
14836
|
-
}
|
|
14837
|
-
}
|
|
14469
|
+
return {
|
|
14470
|
+
setupComplete: stateManager2.isSetupComplete(),
|
|
14471
|
+
username: stateManager2.getState().config.githubUsername
|
|
14472
|
+
};
|
|
14838
14473
|
}
|
|
14839
14474
|
var init_setup = __esm({
|
|
14840
14475
|
"src/commands/setup.ts"() {
|
|
14841
14476
|
"use strict";
|
|
14842
14477
|
init_core();
|
|
14843
|
-
init_json();
|
|
14844
14478
|
init_validation();
|
|
14845
14479
|
}
|
|
14846
14480
|
});
|
|
@@ -16532,10 +16166,325 @@ var init_dashboard_templates = __esm({
|
|
|
16532
16166
|
}
|
|
16533
16167
|
});
|
|
16534
16168
|
|
|
16169
|
+
// src/commands/dashboard-server.ts
|
|
16170
|
+
var dashboard_server_exports = {};
|
|
16171
|
+
__export(dashboard_server_exports, {
|
|
16172
|
+
startDashboardServer: () => startDashboardServer
|
|
16173
|
+
});
|
|
16174
|
+
function buildDashboardJson(digest, state, commentedIssues) {
|
|
16175
|
+
const prsByRepo = computePRsByRepo(digest, state);
|
|
16176
|
+
const topRepos = computeTopRepos(prsByRepo);
|
|
16177
|
+
const { monthlyMerged } = getMonthlyData(state);
|
|
16178
|
+
const stats = buildDashboardStats(digest, state);
|
|
16179
|
+
const issueResponses = commentedIssues.filter((i) => i.status === "new_response");
|
|
16180
|
+
return {
|
|
16181
|
+
stats,
|
|
16182
|
+
prsByRepo,
|
|
16183
|
+
topRepos: topRepos.map(([repo, data]) => ({ repo, ...data })),
|
|
16184
|
+
monthlyMerged,
|
|
16185
|
+
activePRs: digest.openPRs || [],
|
|
16186
|
+
shelvedPRUrls: state.config.shelvedPRUrls || [],
|
|
16187
|
+
commentedIssues,
|
|
16188
|
+
issueResponses
|
|
16189
|
+
};
|
|
16190
|
+
}
|
|
16191
|
+
function readBody(req, maxBytes = MAX_BODY_BYTES) {
|
|
16192
|
+
return new Promise((resolve5, reject) => {
|
|
16193
|
+
const chunks = [];
|
|
16194
|
+
let totalLength = 0;
|
|
16195
|
+
let aborted = false;
|
|
16196
|
+
req.on("data", (chunk) => {
|
|
16197
|
+
if (aborted) return;
|
|
16198
|
+
totalLength += chunk.length;
|
|
16199
|
+
if (totalLength > maxBytes) {
|
|
16200
|
+
aborted = true;
|
|
16201
|
+
req.destroy();
|
|
16202
|
+
reject(new Error("Body too large"));
|
|
16203
|
+
return;
|
|
16204
|
+
}
|
|
16205
|
+
chunks.push(chunk);
|
|
16206
|
+
});
|
|
16207
|
+
req.on("end", () => {
|
|
16208
|
+
if (!aborted) resolve5(Buffer.concat(chunks).toString("utf-8"));
|
|
16209
|
+
});
|
|
16210
|
+
req.on("error", (err) => {
|
|
16211
|
+
if (!aborted) reject(err);
|
|
16212
|
+
});
|
|
16213
|
+
});
|
|
16214
|
+
}
|
|
16215
|
+
function sendJson(res, statusCode, data) {
|
|
16216
|
+
const body = JSON.stringify(data);
|
|
16217
|
+
res.writeHead(statusCode, {
|
|
16218
|
+
"Content-Type": "application/json",
|
|
16219
|
+
"Content-Length": Buffer.byteLength(body)
|
|
16220
|
+
});
|
|
16221
|
+
res.end(body);
|
|
16222
|
+
}
|
|
16223
|
+
function sendError(res, statusCode, message) {
|
|
16224
|
+
sendJson(res, statusCode, { error: message });
|
|
16225
|
+
}
|
|
16226
|
+
async function startDashboardServer(options) {
|
|
16227
|
+
const { port: requestedPort, assetsDir, token, open } = options;
|
|
16228
|
+
const stateManager2 = getStateManager();
|
|
16229
|
+
const resolvedAssetsDir = path5.resolve(assetsDir);
|
|
16230
|
+
let cachedDigest;
|
|
16231
|
+
let cachedCommentedIssues = [];
|
|
16232
|
+
if (token) {
|
|
16233
|
+
try {
|
|
16234
|
+
console.error("Fetching dashboard data from GitHub...");
|
|
16235
|
+
const result = await fetchDashboardData(token);
|
|
16236
|
+
cachedDigest = result.digest;
|
|
16237
|
+
cachedCommentedIssues = result.commentedIssues;
|
|
16238
|
+
} catch (error) {
|
|
16239
|
+
console.error("Failed to fetch data from GitHub:", error);
|
|
16240
|
+
console.error("Falling back to cached data...");
|
|
16241
|
+
cachedDigest = stateManager2.getState().lastDigest;
|
|
16242
|
+
}
|
|
16243
|
+
} else {
|
|
16244
|
+
cachedDigest = stateManager2.getState().lastDigest;
|
|
16245
|
+
}
|
|
16246
|
+
if (!cachedDigest) {
|
|
16247
|
+
console.error("No dashboard data available. Run the daily check first:");
|
|
16248
|
+
console.error(" GITHUB_TOKEN=$(gh auth token) npm start -- daily");
|
|
16249
|
+
process.exit(1);
|
|
16250
|
+
}
|
|
16251
|
+
let cachedJsonData;
|
|
16252
|
+
try {
|
|
16253
|
+
cachedJsonData = buildDashboardJson(cachedDigest, stateManager2.getState(), cachedCommentedIssues);
|
|
16254
|
+
} catch (error) {
|
|
16255
|
+
console.error("Failed to build dashboard data from cached digest:", error);
|
|
16256
|
+
console.error("Your state data may be corrupted. Try running: daily --json");
|
|
16257
|
+
process.exit(1);
|
|
16258
|
+
}
|
|
16259
|
+
const server = http.createServer(async (req, res) => {
|
|
16260
|
+
const method = req.method || "GET";
|
|
16261
|
+
const url = req.url || "/";
|
|
16262
|
+
try {
|
|
16263
|
+
if (url === "/api/data" && method === "GET") {
|
|
16264
|
+
sendJson(res, 200, cachedJsonData);
|
|
16265
|
+
return;
|
|
16266
|
+
}
|
|
16267
|
+
if (url === "/api/action" && method === "POST") {
|
|
16268
|
+
await handleAction(req, res);
|
|
16269
|
+
return;
|
|
16270
|
+
}
|
|
16271
|
+
if (url === "/api/refresh" && method === "POST") {
|
|
16272
|
+
await handleRefresh(req, res);
|
|
16273
|
+
return;
|
|
16274
|
+
}
|
|
16275
|
+
if (method === "GET") {
|
|
16276
|
+
serveStaticFile(url, res);
|
|
16277
|
+
return;
|
|
16278
|
+
}
|
|
16279
|
+
sendError(res, 405, "Method not allowed");
|
|
16280
|
+
} catch (error) {
|
|
16281
|
+
console.error("Unhandled request error:", method, url, error);
|
|
16282
|
+
if (!res.headersSent) {
|
|
16283
|
+
sendError(res, 500, "Internal server error");
|
|
16284
|
+
}
|
|
16285
|
+
}
|
|
16286
|
+
});
|
|
16287
|
+
async function handleAction(req, res) {
|
|
16288
|
+
let body;
|
|
16289
|
+
try {
|
|
16290
|
+
const raw = await readBody(req);
|
|
16291
|
+
body = JSON.parse(raw);
|
|
16292
|
+
} catch (e) {
|
|
16293
|
+
const isBodyTooLarge = e instanceof Error && e.message === "Body too large";
|
|
16294
|
+
sendError(res, isBodyTooLarge ? 413 : 400, isBodyTooLarge ? "Request body too large" : "Invalid JSON body");
|
|
16295
|
+
return;
|
|
16296
|
+
}
|
|
16297
|
+
if (!body.action || !VALID_ACTIONS.has(body.action)) {
|
|
16298
|
+
sendError(res, 400, `Invalid action. Must be one of: ${[...VALID_ACTIONS].join(", ")}`);
|
|
16299
|
+
return;
|
|
16300
|
+
}
|
|
16301
|
+
if (!body.url || typeof body.url !== "string") {
|
|
16302
|
+
sendError(res, 400, 'Missing or invalid "url" field');
|
|
16303
|
+
return;
|
|
16304
|
+
}
|
|
16305
|
+
try {
|
|
16306
|
+
switch (body.action) {
|
|
16307
|
+
case "shelve":
|
|
16308
|
+
stateManager2.shelvePR(body.url);
|
|
16309
|
+
break;
|
|
16310
|
+
case "unshelve":
|
|
16311
|
+
stateManager2.unshelvePR(body.url);
|
|
16312
|
+
break;
|
|
16313
|
+
case "snooze":
|
|
16314
|
+
stateManager2.snoozePR(body.url, body.reason || "Snoozed via dashboard", body.days || 7);
|
|
16315
|
+
break;
|
|
16316
|
+
case "unsnooze":
|
|
16317
|
+
stateManager2.unsnoozePR(body.url);
|
|
16318
|
+
break;
|
|
16319
|
+
}
|
|
16320
|
+
stateManager2.save();
|
|
16321
|
+
} catch (error) {
|
|
16322
|
+
console.error("Action failed:", body.action, body.url, error);
|
|
16323
|
+
sendError(res, 500, `Action failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
16324
|
+
return;
|
|
16325
|
+
}
|
|
16326
|
+
if (cachedDigest) {
|
|
16327
|
+
cachedJsonData = buildDashboardJson(cachedDigest, stateManager2.getState(), cachedCommentedIssues);
|
|
16328
|
+
}
|
|
16329
|
+
sendJson(res, 200, cachedJsonData);
|
|
16330
|
+
}
|
|
16331
|
+
async function handleRefresh(_req, res) {
|
|
16332
|
+
const currentToken = token || getGitHubToken();
|
|
16333
|
+
if (!currentToken) {
|
|
16334
|
+
sendError(res, 401, "No GitHub token available. Cannot refresh data.");
|
|
16335
|
+
return;
|
|
16336
|
+
}
|
|
16337
|
+
try {
|
|
16338
|
+
console.error("Refreshing dashboard data from GitHub...");
|
|
16339
|
+
const result = await fetchDashboardData(currentToken);
|
|
16340
|
+
cachedDigest = result.digest;
|
|
16341
|
+
cachedCommentedIssues = result.commentedIssues;
|
|
16342
|
+
cachedJsonData = buildDashboardJson(cachedDigest, stateManager2.getState(), cachedCommentedIssues);
|
|
16343
|
+
sendJson(res, 200, cachedJsonData);
|
|
16344
|
+
} catch (error) {
|
|
16345
|
+
console.error("Dashboard refresh failed:", error);
|
|
16346
|
+
sendError(res, 500, `Refresh failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
16347
|
+
}
|
|
16348
|
+
}
|
|
16349
|
+
function serveStaticFile(requestUrl, res) {
|
|
16350
|
+
let urlPath;
|
|
16351
|
+
try {
|
|
16352
|
+
urlPath = decodeURIComponent(requestUrl.split("?")[0]);
|
|
16353
|
+
} catch (err) {
|
|
16354
|
+
console.error("Malformed URL received:", requestUrl, err);
|
|
16355
|
+
sendError(res, 400, "Malformed URL");
|
|
16356
|
+
return;
|
|
16357
|
+
}
|
|
16358
|
+
if (urlPath.includes("..")) {
|
|
16359
|
+
sendError(res, 403, "Forbidden");
|
|
16360
|
+
return;
|
|
16361
|
+
}
|
|
16362
|
+
const relativePath = urlPath === "/" ? "index.html" : urlPath.replace(/^\/+/, "");
|
|
16363
|
+
let filePath = path5.join(resolvedAssetsDir, relativePath);
|
|
16364
|
+
if (!filePath.startsWith(resolvedAssetsDir + path5.sep) && filePath !== resolvedAssetsDir) {
|
|
16365
|
+
sendError(res, 403, "Forbidden");
|
|
16366
|
+
return;
|
|
16367
|
+
}
|
|
16368
|
+
try {
|
|
16369
|
+
const stat = fs5.statSync(filePath);
|
|
16370
|
+
if (stat.isDirectory()) {
|
|
16371
|
+
filePath = path5.join(resolvedAssetsDir, "index.html");
|
|
16372
|
+
}
|
|
16373
|
+
} catch (err) {
|
|
16374
|
+
const nodeErr = err;
|
|
16375
|
+
if (nodeErr.code === "ENOENT") {
|
|
16376
|
+
filePath = path5.join(resolvedAssetsDir, "index.html");
|
|
16377
|
+
} else {
|
|
16378
|
+
console.error("Failed to stat file:", filePath, err);
|
|
16379
|
+
sendError(res, 500, "Internal server error");
|
|
16380
|
+
return;
|
|
16381
|
+
}
|
|
16382
|
+
}
|
|
16383
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
16384
|
+
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
16385
|
+
try {
|
|
16386
|
+
const content = fs5.readFileSync(filePath);
|
|
16387
|
+
res.writeHead(200, {
|
|
16388
|
+
"Content-Type": contentType,
|
|
16389
|
+
"Content-Length": content.length
|
|
16390
|
+
});
|
|
16391
|
+
res.end(content);
|
|
16392
|
+
} catch (error) {
|
|
16393
|
+
const nodeErr = error;
|
|
16394
|
+
if (nodeErr.code === "ENOENT") {
|
|
16395
|
+
sendError(res, 404, "Not found");
|
|
16396
|
+
} else {
|
|
16397
|
+
console.error("Failed to serve static file:", filePath, error);
|
|
16398
|
+
sendError(res, 500, "Failed to read file");
|
|
16399
|
+
}
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
16402
|
+
const MAX_PORT_ATTEMPTS = 10;
|
|
16403
|
+
let actualPort = requestedPort;
|
|
16404
|
+
for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt++) {
|
|
16405
|
+
try {
|
|
16406
|
+
await new Promise((resolve5, reject) => {
|
|
16407
|
+
server.once("error", reject);
|
|
16408
|
+
server.listen(actualPort, "127.0.0.1", () => resolve5());
|
|
16409
|
+
});
|
|
16410
|
+
break;
|
|
16411
|
+
} catch (err) {
|
|
16412
|
+
const nodeErr = err;
|
|
16413
|
+
if (nodeErr.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS - 1) {
|
|
16414
|
+
console.error(`Port ${actualPort} is in use, trying ${actualPort + 1}...`);
|
|
16415
|
+
actualPort++;
|
|
16416
|
+
continue;
|
|
16417
|
+
}
|
|
16418
|
+
console.error(`Failed to start server: ${nodeErr.message}`);
|
|
16419
|
+
process.exit(1);
|
|
16420
|
+
}
|
|
16421
|
+
}
|
|
16422
|
+
const serverUrl = `http://localhost:${actualPort}`;
|
|
16423
|
+
console.error(`Dashboard server running at ${serverUrl}`);
|
|
16424
|
+
if (open) {
|
|
16425
|
+
const { execFile: execFile4 } = await import("child_process");
|
|
16426
|
+
let openCmd;
|
|
16427
|
+
let args;
|
|
16428
|
+
switch (process.platform) {
|
|
16429
|
+
case "darwin":
|
|
16430
|
+
openCmd = "open";
|
|
16431
|
+
args = [serverUrl];
|
|
16432
|
+
break;
|
|
16433
|
+
case "win32":
|
|
16434
|
+
openCmd = "cmd";
|
|
16435
|
+
args = ["/c", "start", "", serverUrl];
|
|
16436
|
+
break;
|
|
16437
|
+
default:
|
|
16438
|
+
openCmd = "xdg-open";
|
|
16439
|
+
args = [serverUrl];
|
|
16440
|
+
break;
|
|
16441
|
+
}
|
|
16442
|
+
execFile4(openCmd, args, (error) => {
|
|
16443
|
+
if (error) {
|
|
16444
|
+
console.error("Failed to open browser:", error.message);
|
|
16445
|
+
console.error(`Open manually: ${serverUrl}`);
|
|
16446
|
+
}
|
|
16447
|
+
});
|
|
16448
|
+
}
|
|
16449
|
+
const shutdown = () => {
|
|
16450
|
+
console.error("\nShutting down dashboard server...");
|
|
16451
|
+
server.close(() => {
|
|
16452
|
+
process.exit(0);
|
|
16453
|
+
});
|
|
16454
|
+
setTimeout(() => process.exit(0), 3e3).unref();
|
|
16455
|
+
};
|
|
16456
|
+
process.on("SIGINT", shutdown);
|
|
16457
|
+
process.on("SIGTERM", shutdown);
|
|
16458
|
+
}
|
|
16459
|
+
var http, fs5, path5, VALID_ACTIONS, MAX_BODY_BYTES, MIME_TYPES;
|
|
16460
|
+
var init_dashboard_server = __esm({
|
|
16461
|
+
"src/commands/dashboard-server.ts"() {
|
|
16462
|
+
"use strict";
|
|
16463
|
+
http = __toESM(require("http"), 1);
|
|
16464
|
+
fs5 = __toESM(require("fs"), 1);
|
|
16465
|
+
path5 = __toESM(require("path"), 1);
|
|
16466
|
+
init_core();
|
|
16467
|
+
init_dashboard_data();
|
|
16468
|
+
init_dashboard_templates();
|
|
16469
|
+
VALID_ACTIONS = /* @__PURE__ */ new Set(["shelve", "unshelve", "snooze", "unsnooze"]);
|
|
16470
|
+
MAX_BODY_BYTES = 10240;
|
|
16471
|
+
MIME_TYPES = {
|
|
16472
|
+
".html": "text/html",
|
|
16473
|
+
".js": "application/javascript",
|
|
16474
|
+
".css": "text/css",
|
|
16475
|
+
".svg": "image/svg+xml",
|
|
16476
|
+
".json": "application/json",
|
|
16477
|
+
".png": "image/png",
|
|
16478
|
+
".ico": "image/x-icon"
|
|
16479
|
+
};
|
|
16480
|
+
}
|
|
16481
|
+
});
|
|
16482
|
+
|
|
16535
16483
|
// src/commands/dashboard.ts
|
|
16536
16484
|
var dashboard_exports = {};
|
|
16537
16485
|
__export(dashboard_exports, {
|
|
16538
16486
|
runDashboard: () => runDashboard,
|
|
16487
|
+
serveDashboard: () => serveDashboard,
|
|
16539
16488
|
writeDashboardFromState: () => writeDashboardFromState
|
|
16540
16489
|
});
|
|
16541
16490
|
async function runDashboard(options) {
|
|
@@ -16605,8 +16554,8 @@ async function runDashboard(options) {
|
|
|
16605
16554
|
const issueResponses = commentedIssues.filter((i) => i.status === "new_response");
|
|
16606
16555
|
const html = generateDashboardHtml(stats, monthlyMerged, monthlyClosed, monthlyOpened, digest, state, issueResponses);
|
|
16607
16556
|
const dashboardPath = getDashboardPath();
|
|
16608
|
-
|
|
16609
|
-
|
|
16557
|
+
fs6.writeFileSync(dashboardPath, html, { mode: 420 });
|
|
16558
|
+
fs6.chmodSync(dashboardPath, 420);
|
|
16610
16559
|
if (options.offline) {
|
|
16611
16560
|
const lastUpdated = digest.generatedAt || state.lastDigestAt || state.lastRunAt;
|
|
16612
16561
|
console.log(`
|
|
@@ -16641,15 +16590,56 @@ function writeDashboardFromState() {
|
|
|
16641
16590
|
const stats = buildDashboardStats(digest, state);
|
|
16642
16591
|
const html = generateDashboardHtml(stats, monthlyMerged, monthlyClosed, monthlyOpened, digest, state);
|
|
16643
16592
|
const dashboardPath = getDashboardPath();
|
|
16644
|
-
|
|
16645
|
-
|
|
16593
|
+
fs6.writeFileSync(dashboardPath, html, { mode: 420 });
|
|
16594
|
+
fs6.chmodSync(dashboardPath, 420);
|
|
16646
16595
|
return dashboardPath;
|
|
16647
16596
|
}
|
|
16648
|
-
|
|
16597
|
+
function resolveAssetsDir() {
|
|
16598
|
+
const devPath = path6.resolve(__dirname, "../../dashboard/dist");
|
|
16599
|
+
if (fs6.existsSync(path6.join(devPath, "index.html"))) {
|
|
16600
|
+
return devPath;
|
|
16601
|
+
}
|
|
16602
|
+
const bundlePath = path6.resolve(path6.dirname(process.argv[1]), "../../dashboard/dist");
|
|
16603
|
+
if (fs6.existsSync(path6.join(bundlePath, "index.html"))) {
|
|
16604
|
+
return bundlePath;
|
|
16605
|
+
}
|
|
16606
|
+
try {
|
|
16607
|
+
const dashboardPkgPath = require.resolve("@oss-autopilot/dashboard/package.json");
|
|
16608
|
+
const dashboardDist = path6.join(path6.dirname(dashboardPkgPath), "dist");
|
|
16609
|
+
if (fs6.existsSync(path6.join(dashboardDist, "index.html"))) {
|
|
16610
|
+
return dashboardDist;
|
|
16611
|
+
}
|
|
16612
|
+
} catch (error) {
|
|
16613
|
+
const code = error.code;
|
|
16614
|
+
if (code !== "MODULE_NOT_FOUND") {
|
|
16615
|
+
console.error("Error resolving dashboard package:", error);
|
|
16616
|
+
}
|
|
16617
|
+
}
|
|
16618
|
+
return null;
|
|
16619
|
+
}
|
|
16620
|
+
async function serveDashboard(options) {
|
|
16621
|
+
const assetsDir = resolveAssetsDir();
|
|
16622
|
+
if (!assetsDir) {
|
|
16623
|
+
console.error("Could not find dashboard SPA assets.");
|
|
16624
|
+
console.error("Make sure packages/dashboard has been built:");
|
|
16625
|
+
console.error(" cd packages/dashboard && pnpm run build");
|
|
16626
|
+
process.exit(1);
|
|
16627
|
+
}
|
|
16628
|
+
const token = getGitHubToken();
|
|
16629
|
+
const { startDashboardServer: startDashboardServer2 } = await Promise.resolve().then(() => (init_dashboard_server(), dashboard_server_exports));
|
|
16630
|
+
await startDashboardServer2({
|
|
16631
|
+
port: options.port,
|
|
16632
|
+
assetsDir,
|
|
16633
|
+
token,
|
|
16634
|
+
open: options.open
|
|
16635
|
+
});
|
|
16636
|
+
}
|
|
16637
|
+
var fs6, path6, import_child_process2;
|
|
16649
16638
|
var init_dashboard = __esm({
|
|
16650
16639
|
"src/commands/dashboard.ts"() {
|
|
16651
16640
|
"use strict";
|
|
16652
|
-
|
|
16641
|
+
fs6 = __toESM(require("fs"), 1);
|
|
16642
|
+
path6 = __toESM(require("path"), 1);
|
|
16653
16643
|
import_child_process2 = require("child_process");
|
|
16654
16644
|
init_core();
|
|
16655
16645
|
init_json();
|
|
@@ -16682,7 +16672,7 @@ function extractTitle(line) {
|
|
|
16682
16672
|
cleaned = cleaned.replace(/\[[ xX]\]\s*/, "");
|
|
16683
16673
|
cleaned = cleaned.replace(/~~/g, "");
|
|
16684
16674
|
cleaned = cleaned.replace(/\b(Done|DONE|done)\b/g, "");
|
|
16685
|
-
cleaned = cleaned.replace(/^[\s
|
|
16675
|
+
cleaned = cleaned.replace(/^[\s\-\u2013\u2014:]+/, "").replace(/[\s\-\u2013\u2014:]+$/, "");
|
|
16686
16676
|
return cleaned.trim();
|
|
16687
16677
|
}
|
|
16688
16678
|
function isCompleted(line) {
|
|
@@ -16729,57 +16719,25 @@ function parseIssueList(content) {
|
|
|
16729
16719
|
};
|
|
16730
16720
|
}
|
|
16731
16721
|
async function runParseList(options) {
|
|
16732
|
-
const filePath =
|
|
16733
|
-
if (!
|
|
16734
|
-
|
|
16735
|
-
outputJsonError(`File not found: ${filePath}`);
|
|
16736
|
-
} else {
|
|
16737
|
-
console.error(`Error: File not found: ${filePath}`);
|
|
16738
|
-
}
|
|
16739
|
-
process.exit(1);
|
|
16722
|
+
const filePath = path7.resolve(options.filePath);
|
|
16723
|
+
if (!fs7.existsSync(filePath)) {
|
|
16724
|
+
throw new Error(`File not found: ${filePath}`);
|
|
16740
16725
|
}
|
|
16741
16726
|
let content;
|
|
16742
16727
|
try {
|
|
16743
|
-
content =
|
|
16728
|
+
content = fs7.readFileSync(filePath, "utf-8");
|
|
16744
16729
|
} catch (error) {
|
|
16745
16730
|
const msg = error instanceof Error ? error.message : String(error);
|
|
16746
|
-
|
|
16747
|
-
outputJsonError(`Failed to read file: ${msg}`);
|
|
16748
|
-
} else {
|
|
16749
|
-
console.error(`Error: Failed to read file: ${msg}`);
|
|
16750
|
-
}
|
|
16751
|
-
process.exit(1);
|
|
16752
|
-
}
|
|
16753
|
-
const result = parseIssueList(content);
|
|
16754
|
-
if (options.json) {
|
|
16755
|
-
outputJson(result);
|
|
16756
|
-
} else {
|
|
16757
|
-
console.log(`
|
|
16758
|
-
\u{1F4CB} Issue List: ${filePath}
|
|
16759
|
-
`);
|
|
16760
|
-
console.log(`Available: ${result.availableCount} | Completed: ${result.completedCount}
|
|
16761
|
-
`);
|
|
16762
|
-
if (result.available.length > 0) {
|
|
16763
|
-
console.log("--- Available ---");
|
|
16764
|
-
for (const item of result.available) {
|
|
16765
|
-
console.log(` [${item.tier}] ${item.repo}#${item.number}: ${item.title}`);
|
|
16766
|
-
}
|
|
16767
|
-
}
|
|
16768
|
-
if (result.completed.length > 0) {
|
|
16769
|
-
console.log("\n--- Completed ---");
|
|
16770
|
-
for (const item of result.completed) {
|
|
16771
|
-
console.log(` [${item.tier}] ${item.repo}#${item.number}: ${item.title}`);
|
|
16772
|
-
}
|
|
16773
|
-
}
|
|
16731
|
+
throw new Error(`Failed to read file: ${msg}`, { cause: error });
|
|
16774
16732
|
}
|
|
16733
|
+
return parseIssueList(content);
|
|
16775
16734
|
}
|
|
16776
|
-
var
|
|
16735
|
+
var fs7, path7;
|
|
16777
16736
|
var init_parse_list = __esm({
|
|
16778
16737
|
"src/commands/parse-list.ts"() {
|
|
16779
16738
|
"use strict";
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
init_json();
|
|
16739
|
+
fs7 = __toESM(require("fs"), 1);
|
|
16740
|
+
path7 = __toESM(require("path"), 1);
|
|
16783
16741
|
}
|
|
16784
16742
|
});
|
|
16785
16743
|
|
|
@@ -16789,25 +16747,25 @@ __export(check_integration_exports, {
|
|
|
16789
16747
|
runCheckIntegration: () => runCheckIntegration
|
|
16790
16748
|
});
|
|
16791
16749
|
function getImportName(filePath) {
|
|
16792
|
-
const ext =
|
|
16793
|
-
const base =
|
|
16750
|
+
const ext = path8.extname(filePath);
|
|
16751
|
+
const base = path8.basename(filePath, ext);
|
|
16794
16752
|
if (base === "index") {
|
|
16795
|
-
return
|
|
16753
|
+
return path8.basename(path8.dirname(filePath));
|
|
16796
16754
|
}
|
|
16797
16755
|
return base;
|
|
16798
16756
|
}
|
|
16799
16757
|
function suggestEntryPoints(newFile, existingFiles) {
|
|
16800
|
-
const dir =
|
|
16758
|
+
const dir = path8.dirname(newFile);
|
|
16801
16759
|
const suggestions = [];
|
|
16802
16760
|
for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
|
|
16803
|
-
const indexFile =
|
|
16761
|
+
const indexFile = path8.join(dir, `index${ext}`);
|
|
16804
16762
|
if (existingFiles.includes(indexFile)) {
|
|
16805
16763
|
suggestions.push(indexFile);
|
|
16806
16764
|
}
|
|
16807
16765
|
}
|
|
16808
|
-
const parentDir =
|
|
16766
|
+
const parentDir = path8.dirname(dir);
|
|
16809
16767
|
for (const ext of [".ts", ".tsx", ".js", ".jsx"]) {
|
|
16810
|
-
const parentIndex =
|
|
16768
|
+
const parentIndex = path8.join(parentDir, `index${ext}`);
|
|
16811
16769
|
if (existingFiles.includes(parentIndex)) {
|
|
16812
16770
|
suggestions.push(parentIndex);
|
|
16813
16771
|
}
|
|
@@ -16818,33 +16776,22 @@ async function runCheckIntegration(options) {
|
|
|
16818
16776
|
const base = options.base;
|
|
16819
16777
|
let newFiles;
|
|
16820
16778
|
try {
|
|
16821
|
-
const
|
|
16779
|
+
const output = (0, import_child_process3.execFileSync)("git", ["diff", "--name-only", "--diff-filter=A", `${base}...HEAD`], {
|
|
16822
16780
|
encoding: "utf-8",
|
|
16823
16781
|
timeout: 1e4
|
|
16824
16782
|
}).trim();
|
|
16825
|
-
newFiles =
|
|
16783
|
+
newFiles = output ? output.split("\n").filter(Boolean) : [];
|
|
16826
16784
|
} catch (error) {
|
|
16827
16785
|
const msg = error instanceof Error ? error.message : String(error);
|
|
16828
|
-
|
|
16829
|
-
outputJsonError(`Failed to run git diff: ${msg}`);
|
|
16830
|
-
} else {
|
|
16831
|
-
console.error(`Error: Failed to run git diff: ${msg}`);
|
|
16832
|
-
}
|
|
16833
|
-
process.exit(1);
|
|
16786
|
+
throw new Error(`Failed to run git diff: ${msg}`, { cause: error });
|
|
16834
16787
|
}
|
|
16835
16788
|
const codeFiles = newFiles.filter((f) => {
|
|
16836
|
-
const ext =
|
|
16789
|
+
const ext = path8.extname(f);
|
|
16837
16790
|
if (!CODE_EXTENSIONS.has(ext)) return false;
|
|
16838
16791
|
return !IGNORED_PATTERNS.some((p) => p.test(f));
|
|
16839
16792
|
});
|
|
16840
16793
|
if (codeFiles.length === 0) {
|
|
16841
|
-
|
|
16842
|
-
if (options.json) {
|
|
16843
|
-
outputJson(result);
|
|
16844
|
-
} else {
|
|
16845
|
-
console.log("\nNo new code files to check.");
|
|
16846
|
-
}
|
|
16847
|
-
return;
|
|
16794
|
+
return { newFiles: [], unreferencedCount: 0 };
|
|
16848
16795
|
}
|
|
16849
16796
|
let allFiles;
|
|
16850
16797
|
try {
|
|
@@ -16882,7 +16829,7 @@ async function runCheckIntegration(options) {
|
|
|
16882
16829
|
const exitCode = error && typeof error === "object" && "status" in error ? error.status : null;
|
|
16883
16830
|
if (exitCode !== null && exitCode !== 1) {
|
|
16884
16831
|
const msg = error instanceof Error ? error.message : String(error);
|
|
16885
|
-
|
|
16832
|
+
debug("check-integration", `git grep failed for "${pattern}": ${msg}`);
|
|
16886
16833
|
}
|
|
16887
16834
|
}
|
|
16888
16835
|
}
|
|
@@ -16899,36 +16846,14 @@ async function runCheckIntegration(options) {
|
|
|
16899
16846
|
results.push(info);
|
|
16900
16847
|
}
|
|
16901
16848
|
const unreferencedCount = results.filter((r) => !r.isIntegrated).length;
|
|
16902
|
-
|
|
16903
|
-
if (options.json) {
|
|
16904
|
-
outputJson(output);
|
|
16905
|
-
} else {
|
|
16906
|
-
console.log(`
|
|
16907
|
-
\u{1F50D} Integration Check (base: ${base})
|
|
16908
|
-
`);
|
|
16909
|
-
console.log(`New files: ${results.length} | Unreferenced: ${unreferencedCount}
|
|
16910
|
-
`);
|
|
16911
|
-
for (const file of results) {
|
|
16912
|
-
const status = file.isIntegrated ? "\u2705" : "\u26A0\uFE0F";
|
|
16913
|
-
console.log(`${status} ${file.path}`);
|
|
16914
|
-
if (file.isIntegrated) {
|
|
16915
|
-
console.log(` Referenced by: ${file.referencedBy.join(", ")}`);
|
|
16916
|
-
} else {
|
|
16917
|
-
console.log(" Not referenced by any file");
|
|
16918
|
-
if (file.suggestedEntryPoints && file.suggestedEntryPoints.length > 0) {
|
|
16919
|
-
console.log(` Suggested entry points: ${file.suggestedEntryPoints.join(", ")}`);
|
|
16920
|
-
}
|
|
16921
|
-
}
|
|
16922
|
-
}
|
|
16923
|
-
}
|
|
16849
|
+
return { newFiles: results, unreferencedCount };
|
|
16924
16850
|
}
|
|
16925
|
-
var
|
|
16851
|
+
var path8, import_child_process3, CODE_EXTENSIONS, IGNORED_PATTERNS;
|
|
16926
16852
|
var init_check_integration = __esm({
|
|
16927
16853
|
"src/commands/check-integration.ts"() {
|
|
16928
16854
|
"use strict";
|
|
16929
|
-
|
|
16855
|
+
path8 = __toESM(require("path"), 1);
|
|
16930
16856
|
import_child_process3 = require("child_process");
|
|
16931
|
-
init_json();
|
|
16932
16857
|
init_core();
|
|
16933
16858
|
CODE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
16934
16859
|
".ts",
|
|
@@ -17005,7 +16930,7 @@ function getCurrentBranch(repoPath) {
|
|
|
17005
16930
|
function scanForRepos(scanPaths) {
|
|
17006
16931
|
const repos = {};
|
|
17007
16932
|
for (const scanPath of scanPaths) {
|
|
17008
|
-
if (!
|
|
16933
|
+
if (!fs8.existsSync(scanPath)) continue;
|
|
17009
16934
|
let gitDirs;
|
|
17010
16935
|
try {
|
|
17011
16936
|
const output = (0, import_child_process4.execFileSync)("find", [scanPath, "-maxdepth", "4", "-name", ".git", "-type", "d"], {
|
|
@@ -17019,7 +16944,7 @@ function scanForRepos(scanPaths) {
|
|
|
17019
16944
|
continue;
|
|
17020
16945
|
}
|
|
17021
16946
|
for (const gitDir of gitDirs) {
|
|
17022
|
-
const repoPath =
|
|
16947
|
+
const repoPath = path9.dirname(gitDir);
|
|
17023
16948
|
const remote = getGitHubRemote(repoPath);
|
|
17024
16949
|
if (!remote) continue;
|
|
17025
16950
|
const currentBranch = getCurrentBranch(repoPath);
|
|
@@ -17035,79 +16960,48 @@ function scanForRepos(scanPaths) {
|
|
|
17035
16960
|
async function runLocalRepos(options) {
|
|
17036
16961
|
const stateManager2 = getStateManager();
|
|
17037
16962
|
const state = stateManager2.getState();
|
|
17038
|
-
const scanPaths = options.paths?.map((p) =>
|
|
16963
|
+
const scanPaths = options.paths?.map((p) => path9.resolve(p)) ?? state.config.localRepoScanPaths ?? DEFAULT_SCAN_PATHS.filter((p) => fs8.existsSync(p));
|
|
17039
16964
|
if (!options.scan && state.localRepoCache) {
|
|
17040
16965
|
const cache = state.localRepoCache;
|
|
17041
|
-
|
|
16966
|
+
return {
|
|
17042
16967
|
repos: cache.repos,
|
|
17043
16968
|
scanPaths: cache.scanPaths,
|
|
17044
16969
|
cachedAt: cache.cachedAt,
|
|
17045
16970
|
fromCache: true
|
|
17046
16971
|
};
|
|
17047
|
-
if (options.json) {
|
|
17048
|
-
outputJson(result2);
|
|
17049
|
-
} else {
|
|
17050
|
-
console.log(`
|
|
17051
|
-
\u{1F4C1} Local Repos (cached ${cache.cachedAt})
|
|
17052
|
-
`);
|
|
17053
|
-
printRepos(cache.repos);
|
|
17054
|
-
}
|
|
17055
|
-
return;
|
|
17056
|
-
}
|
|
17057
|
-
if (!options.json) {
|
|
17058
|
-
console.log(`
|
|
17059
|
-
\u{1F50D} Scanning for local repos in ${scanPaths.length} directories...
|
|
17060
|
-
`);
|
|
17061
16972
|
}
|
|
17062
16973
|
const repos = scanForRepos(scanPaths);
|
|
17063
|
-
const repoCount = Object.keys(repos).length;
|
|
17064
16974
|
const cachedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17065
16975
|
try {
|
|
17066
16976
|
stateManager2.setLocalRepoCache({ repos, scanPaths, cachedAt });
|
|
17067
16977
|
stateManager2.save();
|
|
17068
16978
|
} catch (error) {
|
|
17069
16979
|
const msg = error instanceof Error ? error.message : String(error);
|
|
17070
|
-
|
|
16980
|
+
debug("local-repos", `Failed to cache scan results: ${msg}`);
|
|
17071
16981
|
}
|
|
17072
|
-
|
|
16982
|
+
return {
|
|
17073
16983
|
repos,
|
|
17074
16984
|
scanPaths,
|
|
17075
16985
|
cachedAt,
|
|
17076
16986
|
fromCache: false
|
|
17077
16987
|
};
|
|
17078
|
-
if (options.json) {
|
|
17079
|
-
outputJson(result);
|
|
17080
|
-
} else {
|
|
17081
|
-
console.log(`Found ${repoCount} repos:
|
|
17082
|
-
`);
|
|
17083
|
-
printRepos(repos);
|
|
17084
|
-
}
|
|
17085
|
-
}
|
|
17086
|
-
function printRepos(repos) {
|
|
17087
|
-
const entries = Object.entries(repos).sort(([a], [b]) => a.localeCompare(b));
|
|
17088
|
-
for (const [remote, info] of entries) {
|
|
17089
|
-
const branch = info.currentBranch ? ` (${info.currentBranch})` : "";
|
|
17090
|
-
console.log(` ${remote}${branch}`);
|
|
17091
|
-
console.log(` ${info.path}`);
|
|
17092
|
-
}
|
|
17093
16988
|
}
|
|
17094
|
-
var
|
|
16989
|
+
var fs8, path9, os2, import_child_process4, DEFAULT_SCAN_PATHS;
|
|
17095
16990
|
var init_local_repos = __esm({
|
|
17096
16991
|
"src/commands/local-repos.ts"() {
|
|
17097
16992
|
"use strict";
|
|
17098
|
-
|
|
17099
|
-
|
|
16993
|
+
fs8 = __toESM(require("fs"), 1);
|
|
16994
|
+
path9 = __toESM(require("path"), 1);
|
|
17100
16995
|
os2 = __toESM(require("os"), 1);
|
|
17101
16996
|
import_child_process4 = require("child_process");
|
|
17102
16997
|
init_core();
|
|
17103
|
-
init_json();
|
|
17104
16998
|
DEFAULT_SCAN_PATHS = [
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
16999
|
+
path9.join(os2.homedir(), "Documents", "oss"),
|
|
17000
|
+
path9.join(os2.homedir(), "dev"),
|
|
17001
|
+
path9.join(os2.homedir(), "projects"),
|
|
17002
|
+
path9.join(os2.homedir(), "src"),
|
|
17003
|
+
path9.join(os2.homedir(), "code"),
|
|
17004
|
+
path9.join(os2.homedir(), "repos")
|
|
17111
17005
|
];
|
|
17112
17006
|
}
|
|
17113
17007
|
});
|
|
@@ -17122,8 +17016,8 @@ __export(startup_exports, {
|
|
|
17122
17016
|
});
|
|
17123
17017
|
function getVersion() {
|
|
17124
17018
|
try {
|
|
17125
|
-
const pkgPath =
|
|
17126
|
-
return JSON.parse(
|
|
17019
|
+
const pkgPath = path10.join(path10.dirname(process.argv[1]), "..", "package.json");
|
|
17020
|
+
return JSON.parse(fs9.readFileSync(pkgPath, "utf-8")).version;
|
|
17127
17021
|
} catch (error) {
|
|
17128
17022
|
console.error("[STARTUP] Failed to detect CLI version:", error instanceof Error ? error.message : error);
|
|
17129
17023
|
return "0.0.0";
|
|
@@ -17155,11 +17049,11 @@ function detectIssueList() {
|
|
|
17155
17049
|
let issueListPath = "";
|
|
17156
17050
|
let source = "auto-detected";
|
|
17157
17051
|
const configPath = ".claude/oss-autopilot/config.md";
|
|
17158
|
-
if (
|
|
17052
|
+
if (fs9.existsSync(configPath)) {
|
|
17159
17053
|
try {
|
|
17160
|
-
const configContent =
|
|
17054
|
+
const configContent = fs9.readFileSync(configPath, "utf-8");
|
|
17161
17055
|
const configuredPath = parseIssueListPathFromConfig(configContent);
|
|
17162
|
-
if (configuredPath &&
|
|
17056
|
+
if (configuredPath && fs9.existsSync(configuredPath)) {
|
|
17163
17057
|
issueListPath = configuredPath;
|
|
17164
17058
|
source = "configured";
|
|
17165
17059
|
}
|
|
@@ -17170,7 +17064,7 @@ function detectIssueList() {
|
|
|
17170
17064
|
if (!issueListPath) {
|
|
17171
17065
|
const probes = ["open-source/potential-issue-list.md", "oss/issue-list.md", "issues.md"];
|
|
17172
17066
|
for (const probe of probes) {
|
|
17173
|
-
if (
|
|
17067
|
+
if (fs9.existsSync(probe)) {
|
|
17174
17068
|
issueListPath = probe;
|
|
17175
17069
|
source = "auto-detected";
|
|
17176
17070
|
break;
|
|
@@ -17179,7 +17073,7 @@ function detectIssueList() {
|
|
|
17179
17073
|
}
|
|
17180
17074
|
if (!issueListPath) return void 0;
|
|
17181
17075
|
try {
|
|
17182
|
-
const content =
|
|
17076
|
+
const content = fs9.readFileSync(issueListPath, "utf-8");
|
|
17183
17077
|
const { availableCount, completedCount } = countIssueListItems(content);
|
|
17184
17078
|
return { path: issueListPath, source, availableCount, completedCount };
|
|
17185
17079
|
} catch (error) {
|
|
@@ -17200,82 +17094,52 @@ function openInBrowser(filePath) {
|
|
|
17200
17094
|
}
|
|
17201
17095
|
});
|
|
17202
17096
|
}
|
|
17203
|
-
async function runStartup(
|
|
17097
|
+
async function runStartup() {
|
|
17204
17098
|
const version = getVersion();
|
|
17205
17099
|
const stateManager2 = getStateManager();
|
|
17206
17100
|
if (!stateManager2.isSetupComplete()) {
|
|
17207
|
-
|
|
17208
|
-
outputJson({ version, setupComplete: false });
|
|
17209
|
-
} else {
|
|
17210
|
-
console.log("Setup incomplete. Run /setup-oss first.");
|
|
17211
|
-
}
|
|
17212
|
-
return;
|
|
17101
|
+
return { version, setupComplete: false };
|
|
17213
17102
|
}
|
|
17214
17103
|
const token = getGitHubToken();
|
|
17215
17104
|
if (!token) {
|
|
17216
|
-
|
|
17217
|
-
|
|
17218
|
-
|
|
17219
|
-
|
|
17220
|
-
|
|
17221
|
-
});
|
|
17222
|
-
} else {
|
|
17223
|
-
console.error("Error: GitHub authentication required.");
|
|
17224
|
-
}
|
|
17225
|
-
return;
|
|
17105
|
+
return {
|
|
17106
|
+
version,
|
|
17107
|
+
setupComplete: true,
|
|
17108
|
+
authError: 'GitHub authentication required. Install GitHub CLI (https://cli.github.com/) and run "gh auth login", or set GITHUB_TOKEN.'
|
|
17109
|
+
};
|
|
17226
17110
|
}
|
|
17111
|
+
const daily = await executeDailyCheck(token);
|
|
17112
|
+
let dashboardPath;
|
|
17113
|
+
let dashboardOpened = false;
|
|
17227
17114
|
try {
|
|
17228
|
-
|
|
17229
|
-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
dashboardPath = writeDashboardFromState();
|
|
17233
|
-
if (daily.digest.summary.totalActivePRs > 0) {
|
|
17234
|
-
openInBrowser(dashboardPath);
|
|
17235
|
-
dashboardOpened = true;
|
|
17236
|
-
}
|
|
17237
|
-
} catch (error) {
|
|
17238
|
-
console.error("[STARTUP] Dashboard generation failed:", error instanceof Error ? error.message : error);
|
|
17239
|
-
}
|
|
17240
|
-
if (dashboardOpened) {
|
|
17241
|
-
daily.briefSummary += " | Dashboard opened in browser";
|
|
17242
|
-
}
|
|
17243
|
-
const issueList = detectIssueList();
|
|
17244
|
-
if (options.json) {
|
|
17245
|
-
outputJson({
|
|
17246
|
-
version,
|
|
17247
|
-
setupComplete: true,
|
|
17248
|
-
daily,
|
|
17249
|
-
dashboardPath,
|
|
17250
|
-
issueList
|
|
17251
|
-
});
|
|
17252
|
-
} else {
|
|
17253
|
-
console.log(`OSS Autopilot v${version}`);
|
|
17254
|
-
console.log(daily.briefSummary);
|
|
17255
|
-
if (dashboardPath) console.log(`Dashboard: ${dashboardPath}`);
|
|
17115
|
+
dashboardPath = writeDashboardFromState();
|
|
17116
|
+
if (daily.digest.summary.totalActivePRs > 0) {
|
|
17117
|
+
openInBrowser(dashboardPath);
|
|
17118
|
+
dashboardOpened = true;
|
|
17256
17119
|
}
|
|
17257
17120
|
} catch (error) {
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
console.error(`[FATAL] Daily check failed: ${msg}`);
|
|
17263
|
-
if (error instanceof Error && error.stack) {
|
|
17264
|
-
console.error(error.stack);
|
|
17265
|
-
}
|
|
17266
|
-
}
|
|
17267
|
-
process.exit(1);
|
|
17121
|
+
console.error("[STARTUP] Dashboard generation failed:", error instanceof Error ? error.message : error);
|
|
17122
|
+
}
|
|
17123
|
+
if (dashboardOpened) {
|
|
17124
|
+
daily.briefSummary += " | Dashboard opened in browser";
|
|
17268
17125
|
}
|
|
17126
|
+
const issueList = detectIssueList();
|
|
17127
|
+
return {
|
|
17128
|
+
version,
|
|
17129
|
+
setupComplete: true,
|
|
17130
|
+
daily,
|
|
17131
|
+
dashboardPath,
|
|
17132
|
+
issueList
|
|
17133
|
+
};
|
|
17269
17134
|
}
|
|
17270
|
-
var
|
|
17135
|
+
var fs9, path10, import_child_process5;
|
|
17271
17136
|
var init_startup = __esm({
|
|
17272
17137
|
"src/commands/startup.ts"() {
|
|
17273
17138
|
"use strict";
|
|
17274
|
-
|
|
17275
|
-
|
|
17139
|
+
fs9 = __toESM(require("fs"), 1);
|
|
17140
|
+
path10 = __toESM(require("path"), 1);
|
|
17276
17141
|
import_child_process5 = require("child_process");
|
|
17277
17142
|
init_core();
|
|
17278
|
-
init_json();
|
|
17279
17143
|
init_daily();
|
|
17280
17144
|
init_dashboard();
|
|
17281
17145
|
}
|
|
@@ -17290,44 +17154,28 @@ __export(shelve_exports, {
|
|
|
17290
17154
|
});
|
|
17291
17155
|
async function runShelve(options) {
|
|
17292
17156
|
validateUrl(options.prUrl);
|
|
17293
|
-
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR"
|
|
17157
|
+
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR");
|
|
17294
17158
|
const stateManager2 = getStateManager();
|
|
17295
17159
|
const added = stateManager2.shelvePR(options.prUrl);
|
|
17296
17160
|
if (added) {
|
|
17297
17161
|
stateManager2.save();
|
|
17298
17162
|
}
|
|
17299
|
-
|
|
17300
|
-
outputJson({ shelved: added, url: options.prUrl });
|
|
17301
|
-
} else if (added) {
|
|
17302
|
-
console.log(`Shelved: ${options.prUrl}`);
|
|
17303
|
-
console.log("This PR is now excluded from capacity and actionable issues.");
|
|
17304
|
-
console.log("It will auto-unshelve if a maintainer engages.");
|
|
17305
|
-
} else {
|
|
17306
|
-
console.log("PR is already shelved.");
|
|
17307
|
-
}
|
|
17163
|
+
return { shelved: added, url: options.prUrl };
|
|
17308
17164
|
}
|
|
17309
17165
|
async function runUnshelve(options) {
|
|
17310
17166
|
validateUrl(options.prUrl);
|
|
17311
|
-
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR"
|
|
17167
|
+
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR");
|
|
17312
17168
|
const stateManager2 = getStateManager();
|
|
17313
17169
|
const removed = stateManager2.unshelvePR(options.prUrl);
|
|
17314
17170
|
if (removed) {
|
|
17315
17171
|
stateManager2.save();
|
|
17316
17172
|
}
|
|
17317
|
-
|
|
17318
|
-
outputJson({ unshelved: removed, url: options.prUrl });
|
|
17319
|
-
} else if (removed) {
|
|
17320
|
-
console.log(`Unshelved: ${options.prUrl}`);
|
|
17321
|
-
console.log("This PR is now active again.");
|
|
17322
|
-
} else {
|
|
17323
|
-
console.log("PR was not shelved.");
|
|
17324
|
-
}
|
|
17173
|
+
return { unshelved: removed, url: options.prUrl };
|
|
17325
17174
|
}
|
|
17326
17175
|
var init_shelve = __esm({
|
|
17327
17176
|
"src/commands/shelve.ts"() {
|
|
17328
17177
|
"use strict";
|
|
17329
17178
|
init_core();
|
|
17330
|
-
init_json();
|
|
17331
17179
|
init_validation();
|
|
17332
17180
|
}
|
|
17333
17181
|
});
|
|
@@ -17341,44 +17189,28 @@ __export(dismiss_exports, {
|
|
|
17341
17189
|
});
|
|
17342
17190
|
async function runDismiss(options) {
|
|
17343
17191
|
validateUrl(options.issueUrl);
|
|
17344
|
-
validateGitHubUrl(options.issueUrl, ISSUE_URL_PATTERN, "issue"
|
|
17192
|
+
validateGitHubUrl(options.issueUrl, ISSUE_URL_PATTERN, "issue");
|
|
17345
17193
|
const stateManager2 = getStateManager();
|
|
17346
17194
|
const added = stateManager2.dismissIssue(options.issueUrl, (/* @__PURE__ */ new Date()).toISOString());
|
|
17347
17195
|
if (added) {
|
|
17348
17196
|
stateManager2.save();
|
|
17349
17197
|
}
|
|
17350
|
-
|
|
17351
|
-
outputJson({ dismissed: added, url: options.issueUrl });
|
|
17352
|
-
} else if (added) {
|
|
17353
|
-
console.log(`Dismissed: ${options.issueUrl}`);
|
|
17354
|
-
console.log("Issue reply notifications are now muted.");
|
|
17355
|
-
console.log("New responses after this point will resurface automatically.");
|
|
17356
|
-
} else {
|
|
17357
|
-
console.log("Issue is already dismissed.");
|
|
17358
|
-
}
|
|
17198
|
+
return { dismissed: added, url: options.issueUrl };
|
|
17359
17199
|
}
|
|
17360
17200
|
async function runUndismiss(options) {
|
|
17361
17201
|
validateUrl(options.issueUrl);
|
|
17362
|
-
validateGitHubUrl(options.issueUrl, ISSUE_URL_PATTERN, "issue"
|
|
17202
|
+
validateGitHubUrl(options.issueUrl, ISSUE_URL_PATTERN, "issue");
|
|
17363
17203
|
const stateManager2 = getStateManager();
|
|
17364
17204
|
const removed = stateManager2.undismissIssue(options.issueUrl);
|
|
17365
17205
|
if (removed) {
|
|
17366
17206
|
stateManager2.save();
|
|
17367
17207
|
}
|
|
17368
|
-
|
|
17369
|
-
outputJson({ undismissed: removed, url: options.issueUrl });
|
|
17370
|
-
} else if (removed) {
|
|
17371
|
-
console.log(`Undismissed: ${options.issueUrl}`);
|
|
17372
|
-
console.log("Issue reply notifications are active again.");
|
|
17373
|
-
} else {
|
|
17374
|
-
console.log("Issue was not dismissed.");
|
|
17375
|
-
}
|
|
17208
|
+
return { undismissed: removed, url: options.issueUrl };
|
|
17376
17209
|
}
|
|
17377
17210
|
var init_dismiss = __esm({
|
|
17378
17211
|
"src/commands/dismiss.ts"() {
|
|
17379
17212
|
"use strict";
|
|
17380
17213
|
init_core();
|
|
17381
|
-
init_json();
|
|
17382
17214
|
init_validation();
|
|
17383
17215
|
}
|
|
17384
17216
|
});
|
|
@@ -17391,77 +17223,41 @@ __export(snooze_exports, {
|
|
|
17391
17223
|
});
|
|
17392
17224
|
async function runSnooze(options) {
|
|
17393
17225
|
validateUrl(options.prUrl);
|
|
17394
|
-
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR"
|
|
17226
|
+
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR");
|
|
17395
17227
|
validateMessage(options.reason);
|
|
17396
17228
|
const days = options.days ?? DEFAULT_SNOOZE_DAYS;
|
|
17397
17229
|
if (!Number.isFinite(days) || days <= 0) {
|
|
17398
|
-
|
|
17399
|
-
outputJsonError("Snooze duration must be a positive number of days.");
|
|
17400
|
-
} else {
|
|
17401
|
-
console.error("Error: Snooze duration must be a positive number of days.");
|
|
17402
|
-
}
|
|
17403
|
-
process.exit(1);
|
|
17230
|
+
throw new Error("Snooze duration must be a positive number of days.");
|
|
17404
17231
|
}
|
|
17405
|
-
|
|
17406
|
-
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
stateManager2.save();
|
|
17410
|
-
}
|
|
17411
|
-
const snoozeInfo = stateManager2.getSnoozeInfo(options.prUrl);
|
|
17412
|
-
if (options.json) {
|
|
17413
|
-
outputJson({
|
|
17414
|
-
snoozed: added,
|
|
17415
|
-
url: options.prUrl,
|
|
17416
|
-
days,
|
|
17417
|
-
reason: options.reason,
|
|
17418
|
-
expiresAt: snoozeInfo?.expiresAt
|
|
17419
|
-
});
|
|
17420
|
-
} else if (added) {
|
|
17421
|
-
console.log(`Snoozed: ${options.prUrl}`);
|
|
17422
|
-
console.log(`Reason: ${options.reason}`);
|
|
17423
|
-
console.log(`Duration: ${days} day${days === 1 ? "" : "s"}`);
|
|
17424
|
-
console.log(`Expires: ${snoozeInfo?.expiresAt ? new Date(snoozeInfo.expiresAt).toLocaleString() : "unknown"}`);
|
|
17425
|
-
console.log("CI failure notifications are now muted for this PR.");
|
|
17426
|
-
} else {
|
|
17427
|
-
console.log("PR is already snoozed.");
|
|
17428
|
-
if (snoozeInfo) {
|
|
17429
|
-
console.log(`Expires: ${new Date(snoozeInfo.expiresAt).toLocaleString()}`);
|
|
17430
|
-
}
|
|
17431
|
-
}
|
|
17432
|
-
} catch (error) {
|
|
17433
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
17434
|
-
if (options.json) {
|
|
17435
|
-
outputJsonError(`Snooze failed: ${msg}`);
|
|
17436
|
-
} else {
|
|
17437
|
-
console.error(`Error: Snooze failed: ${msg}`);
|
|
17438
|
-
}
|
|
17439
|
-
process.exit(1);
|
|
17232
|
+
const stateManager2 = getStateManager();
|
|
17233
|
+
const added = stateManager2.snoozePR(options.prUrl, options.reason, days);
|
|
17234
|
+
if (added) {
|
|
17235
|
+
stateManager2.save();
|
|
17440
17236
|
}
|
|
17237
|
+
const snoozeInfo = stateManager2.getSnoozeInfo(options.prUrl);
|
|
17238
|
+
return {
|
|
17239
|
+
snoozed: added,
|
|
17240
|
+
url: options.prUrl,
|
|
17241
|
+
days,
|
|
17242
|
+
reason: options.reason,
|
|
17243
|
+
expiresAt: snoozeInfo?.expiresAt
|
|
17244
|
+
};
|
|
17441
17245
|
}
|
|
17442
17246
|
async function runUnsnooze(options) {
|
|
17443
17247
|
validateUrl(options.prUrl);
|
|
17444
|
-
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR"
|
|
17248
|
+
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, "PR");
|
|
17445
17249
|
const stateManager2 = getStateManager();
|
|
17446
17250
|
const removed = stateManager2.unsnoozePR(options.prUrl);
|
|
17447
17251
|
if (removed) {
|
|
17448
17252
|
stateManager2.save();
|
|
17449
17253
|
}
|
|
17450
|
-
|
|
17451
|
-
outputJson({ unsnoozed: removed, url: options.prUrl });
|
|
17452
|
-
} else if (removed) {
|
|
17453
|
-
console.log(`Unsnoozed: ${options.prUrl}`);
|
|
17454
|
-
console.log("CI failure notifications are active again for this PR.");
|
|
17455
|
-
} else {
|
|
17456
|
-
console.log("PR was not snoozed.");
|
|
17457
|
-
}
|
|
17254
|
+
return { unsnoozed: removed, url: options.prUrl };
|
|
17458
17255
|
}
|
|
17459
17256
|
var DEFAULT_SNOOZE_DAYS;
|
|
17460
17257
|
var init_snooze = __esm({
|
|
17461
17258
|
"src/commands/snooze.ts"() {
|
|
17462
17259
|
"use strict";
|
|
17463
17260
|
init_core();
|
|
17464
|
-
init_json();
|
|
17465
17261
|
init_validation();
|
|
17466
17262
|
DEFAULT_SNOOZE_DAYS = 7;
|
|
17467
17263
|
}
|
|
@@ -17486,12 +17282,30 @@ var {
|
|
|
17486
17282
|
|
|
17487
17283
|
// src/cli.ts
|
|
17488
17284
|
init_core();
|
|
17285
|
+
init_json();
|
|
17286
|
+
function printRepos(repos) {
|
|
17287
|
+
const entries = Object.entries(repos).sort(([a], [b]) => a.localeCompare(b));
|
|
17288
|
+
for (const [remote, info] of entries) {
|
|
17289
|
+
const branch = info.currentBranch ? ` (${info.currentBranch})` : "";
|
|
17290
|
+
console.log(` ${remote}${branch}`);
|
|
17291
|
+
console.log(` ${info.path}`);
|
|
17292
|
+
}
|
|
17293
|
+
}
|
|
17294
|
+
function handleCommandError(err, json) {
|
|
17295
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
17296
|
+
if (json) {
|
|
17297
|
+
outputJsonError(msg);
|
|
17298
|
+
} else {
|
|
17299
|
+
console.error(`Error: ${msg}`);
|
|
17300
|
+
}
|
|
17301
|
+
process.exit(1);
|
|
17302
|
+
}
|
|
17489
17303
|
var VERSION10 = (() => {
|
|
17490
17304
|
try {
|
|
17491
|
-
const
|
|
17492
|
-
const
|
|
17493
|
-
const pkgPath =
|
|
17494
|
-
return JSON.parse(
|
|
17305
|
+
const fs10 = require("fs");
|
|
17306
|
+
const path11 = require("path");
|
|
17307
|
+
const pkgPath = path11.join(path11.dirname(process.argv[1]), "..", "package.json");
|
|
17308
|
+
return JSON.parse(fs10.readFileSync(pkgPath, "utf-8")).version;
|
|
17495
17309
|
} catch (_err) {
|
|
17496
17310
|
return "0.0.0";
|
|
17497
17311
|
}
|
|
@@ -17506,6 +17320,7 @@ var LOCAL_ONLY_COMMANDS = [
|
|
|
17506
17320
|
"setup",
|
|
17507
17321
|
"checkSetup",
|
|
17508
17322
|
"dashboard",
|
|
17323
|
+
"serve",
|
|
17509
17324
|
"parse-issue-list",
|
|
17510
17325
|
"check-integration",
|
|
17511
17326
|
"local-repos",
|
|
@@ -17520,106 +17335,571 @@ var LOCAL_ONLY_COMMANDS = [
|
|
|
17520
17335
|
var program2 = new Command();
|
|
17521
17336
|
program2.name("oss-autopilot").description("AI-powered autopilot for managing open source contributions").version(VERSION10).option("--debug", "Enable debug logging");
|
|
17522
17337
|
program2.command("daily").description("Run daily check on all tracked PRs").option("--json", "Output as JSON").action(async (options) => {
|
|
17523
|
-
|
|
17524
|
-
|
|
17338
|
+
try {
|
|
17339
|
+
if (options.json) {
|
|
17340
|
+
const { runDaily: runDaily2 } = await Promise.resolve().then(() => (init_daily(), daily_exports));
|
|
17341
|
+
const data = await runDaily2();
|
|
17342
|
+
outputJson(data);
|
|
17343
|
+
} else {
|
|
17344
|
+
const { runDailyForDisplay: runDailyForDisplay2, printDigest: printDigest2 } = await Promise.resolve().then(() => (init_daily(), daily_exports));
|
|
17345
|
+
const result = await runDailyForDisplay2();
|
|
17346
|
+
printDigest2(result.digest, result.capacity, result.commentedIssues);
|
|
17347
|
+
}
|
|
17348
|
+
} catch (err) {
|
|
17349
|
+
handleCommandError(err, options.json);
|
|
17350
|
+
}
|
|
17525
17351
|
});
|
|
17526
17352
|
program2.command("status").description("Show current status and stats").option("--json", "Output as JSON").option("--offline", "Use cached data only (no GitHub API calls)").action(async (options) => {
|
|
17527
|
-
|
|
17528
|
-
|
|
17353
|
+
try {
|
|
17354
|
+
const { runStatus: runStatus2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
17355
|
+
const data = await runStatus2({ offline: options.offline });
|
|
17356
|
+
if (options.json) {
|
|
17357
|
+
outputJson(data);
|
|
17358
|
+
} else {
|
|
17359
|
+
console.log("\n\u{1F4CA} OSS Status\n");
|
|
17360
|
+
console.log(`Merged PRs: ${data.stats.mergedPRs}`);
|
|
17361
|
+
console.log(`Closed PRs: ${data.stats.closedPRs}`);
|
|
17362
|
+
console.log(`Merge Rate: ${data.stats.mergeRate}`);
|
|
17363
|
+
console.log(`Needs Response: ${data.stats.needsResponse}`);
|
|
17364
|
+
if (data.offline) {
|
|
17365
|
+
console.log(`
|
|
17366
|
+
Last Updated: ${data.lastUpdated || "Never"}`);
|
|
17367
|
+
console.log("(Offline mode: showing cached data)");
|
|
17368
|
+
} else {
|
|
17369
|
+
console.log(`
|
|
17370
|
+
Last Run: ${data.lastRunAt || "Never"}`);
|
|
17371
|
+
}
|
|
17372
|
+
console.log("\nRun with --json for structured output");
|
|
17373
|
+
}
|
|
17374
|
+
} catch (err) {
|
|
17375
|
+
handleCommandError(err, options.json);
|
|
17376
|
+
}
|
|
17529
17377
|
});
|
|
17530
17378
|
program2.command("search [count]").description("Search for new issues to work on").option("--json", "Output as JSON").action(async (count, options) => {
|
|
17531
|
-
|
|
17532
|
-
|
|
17379
|
+
try {
|
|
17380
|
+
const { runSearch: runSearch2 } = await Promise.resolve().then(() => (init_search(), search_exports));
|
|
17381
|
+
if (!options.json) {
|
|
17382
|
+
console.log(`
|
|
17383
|
+
Searching for issues (max ${parseInt(count) || 5})...
|
|
17384
|
+
`);
|
|
17385
|
+
}
|
|
17386
|
+
const data = await runSearch2({ maxResults: parseInt(count) || 5 });
|
|
17387
|
+
if (options.json) {
|
|
17388
|
+
outputJson(data);
|
|
17389
|
+
} else {
|
|
17390
|
+
if (data.candidates.length === 0) {
|
|
17391
|
+
if (data.rateLimitWarning) {
|
|
17392
|
+
console.warn(`
|
|
17393
|
+
${data.rateLimitWarning}
|
|
17394
|
+
`);
|
|
17395
|
+
} else {
|
|
17396
|
+
console.log("No matching issues found.");
|
|
17397
|
+
}
|
|
17398
|
+
return;
|
|
17399
|
+
}
|
|
17400
|
+
if (data.rateLimitWarning) {
|
|
17401
|
+
console.warn(`
|
|
17402
|
+
${data.rateLimitWarning}
|
|
17403
|
+
`);
|
|
17404
|
+
}
|
|
17405
|
+
console.log(`Found ${data.candidates.length} candidates:
|
|
17406
|
+
`);
|
|
17407
|
+
for (const candidate of data.candidates) {
|
|
17408
|
+
const { issue, recommendation, reasonsToApprove, reasonsToSkip, viabilityScore } = candidate;
|
|
17409
|
+
console.log(`[${recommendation.toUpperCase()}] ${issue.repo}#${issue.number}: ${issue.title}`);
|
|
17410
|
+
console.log(` URL: ${issue.url}`);
|
|
17411
|
+
console.log(` Viability: ${viabilityScore}/100`);
|
|
17412
|
+
if (reasonsToApprove.length > 0) console.log(` Approve: ${reasonsToApprove.join(", ")}`);
|
|
17413
|
+
if (reasonsToSkip.length > 0) console.log(` Skip: ${reasonsToSkip.join(", ")}`);
|
|
17414
|
+
console.log("---");
|
|
17415
|
+
}
|
|
17416
|
+
}
|
|
17417
|
+
} catch (err) {
|
|
17418
|
+
handleCommandError(err, options.json);
|
|
17419
|
+
}
|
|
17533
17420
|
});
|
|
17534
17421
|
program2.command("vet <issue-url>").description("Vet a specific issue before working on it").option("--json", "Output as JSON").action(async (issueUrl, options) => {
|
|
17535
|
-
|
|
17536
|
-
|
|
17422
|
+
try {
|
|
17423
|
+
const { runVet: runVet2 } = await Promise.resolve().then(() => (init_vet(), vet_exports));
|
|
17424
|
+
const data = await runVet2({ issueUrl });
|
|
17425
|
+
if (options.json) {
|
|
17426
|
+
outputJson(data);
|
|
17427
|
+
} else {
|
|
17428
|
+
const { issue, recommendation, reasonsToApprove, reasonsToSkip } = data;
|
|
17429
|
+
console.log(`
|
|
17430
|
+
Vetting issue: ${issueUrl}
|
|
17431
|
+
`);
|
|
17432
|
+
console.log(`[${recommendation.toUpperCase()}] ${issue.repo}#${issue.number}: ${issue.title}`);
|
|
17433
|
+
console.log(` URL: ${issue.url}`);
|
|
17434
|
+
if (reasonsToApprove.length > 0) console.log(` Approve: ${reasonsToApprove.join(", ")}`);
|
|
17435
|
+
if (reasonsToSkip.length > 0) console.log(` Skip: ${reasonsToSkip.join(", ")}`);
|
|
17436
|
+
}
|
|
17437
|
+
} catch (err) {
|
|
17438
|
+
handleCommandError(err, options.json);
|
|
17439
|
+
}
|
|
17537
17440
|
});
|
|
17538
17441
|
program2.command("track <pr-url>").description("Add a PR to track").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17539
|
-
|
|
17540
|
-
|
|
17442
|
+
try {
|
|
17443
|
+
const { runTrack: runTrack2 } = await Promise.resolve().then(() => (init_track(), track_exports));
|
|
17444
|
+
const data = await runTrack2({ prUrl });
|
|
17445
|
+
if (options.json) {
|
|
17446
|
+
outputJson(data);
|
|
17447
|
+
} else {
|
|
17448
|
+
console.log(`
|
|
17449
|
+
PR: ${data.pr.repo}#${data.pr.number} - ${data.pr.title}`);
|
|
17450
|
+
console.log("Note: In v2, PRs are tracked automatically via the daily run.");
|
|
17451
|
+
}
|
|
17452
|
+
} catch (err) {
|
|
17453
|
+
handleCommandError(err, options.json);
|
|
17454
|
+
}
|
|
17541
17455
|
});
|
|
17542
17456
|
program2.command("untrack <pr-url>").description("Stop tracking a PR").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17543
|
-
|
|
17544
|
-
|
|
17457
|
+
try {
|
|
17458
|
+
const { runUntrack: runUntrack2 } = await Promise.resolve().then(() => (init_track(), track_exports));
|
|
17459
|
+
const data = await runUntrack2({ prUrl });
|
|
17460
|
+
if (options.json) {
|
|
17461
|
+
outputJson(data);
|
|
17462
|
+
} else {
|
|
17463
|
+
console.log(
|
|
17464
|
+
"Note: In v2, PRs are fetched fresh on each daily run \u2014 there is no local tracking list to remove from."
|
|
17465
|
+
);
|
|
17466
|
+
console.log("Use `shelve` to temporarily hide a PR from the daily summary.");
|
|
17467
|
+
}
|
|
17468
|
+
} catch (err) {
|
|
17469
|
+
handleCommandError(err, options.json);
|
|
17470
|
+
}
|
|
17545
17471
|
});
|
|
17546
17472
|
program2.command("read [pr-url]").description("Mark PR comments as read").option("--all", "Mark all PRs as read").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17547
|
-
|
|
17548
|
-
|
|
17473
|
+
try {
|
|
17474
|
+
const { runRead: runRead2 } = await Promise.resolve().then(() => (init_read(), read_exports));
|
|
17475
|
+
const data = await runRead2({ prUrl, all: options.all });
|
|
17476
|
+
if (options.json) {
|
|
17477
|
+
outputJson(data);
|
|
17478
|
+
} else {
|
|
17479
|
+
console.log("Note: In v2, PR read state is not tracked locally. PRs are fetched fresh on each daily run.");
|
|
17480
|
+
}
|
|
17481
|
+
} catch (err) {
|
|
17482
|
+
handleCommandError(err, options.json);
|
|
17483
|
+
}
|
|
17549
17484
|
});
|
|
17550
17485
|
program2.command("comments <pr-url>").description("Show all comments on a PR").option("--bots", "Include bot comments").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17551
|
-
|
|
17552
|
-
|
|
17486
|
+
try {
|
|
17487
|
+
const { runComments: runComments2 } = await Promise.resolve().then(() => (init_comments(), comments_exports));
|
|
17488
|
+
const data = await runComments2({ prUrl, showBots: options.bots });
|
|
17489
|
+
if (options.json) {
|
|
17490
|
+
outputJson(data);
|
|
17491
|
+
} else {
|
|
17492
|
+
console.log(`
|
|
17493
|
+
Fetching comments for: ${prUrl}
|
|
17494
|
+
`);
|
|
17495
|
+
console.log(`## ${data.pr.title}
|
|
17496
|
+
`);
|
|
17497
|
+
console.log(`**Status:** ${data.pr.state} | **Mergeable:** ${data.pr.mergeable ?? "checking..."}`);
|
|
17498
|
+
console.log(`**Branch:** ${data.pr.head} -> ${data.pr.base}`);
|
|
17499
|
+
console.log(`**URL:** ${data.pr.url}
|
|
17500
|
+
`);
|
|
17501
|
+
const REVIEW_STATE_LABELS = {
|
|
17502
|
+
APPROVED: "[Approved]",
|
|
17503
|
+
CHANGES_REQUESTED: "[Changes]"
|
|
17504
|
+
};
|
|
17505
|
+
if (data.reviews.length > 0) {
|
|
17506
|
+
console.log("### Reviews (newest first)\n");
|
|
17507
|
+
for (const review of data.reviews) {
|
|
17508
|
+
const state = REVIEW_STATE_LABELS[review.state] ?? "[Comment]";
|
|
17509
|
+
const time = review.submittedAt ? formatRelativeTime(review.submittedAt) : "";
|
|
17510
|
+
console.log(`${state} **@${review.user}** (${review.state}) - ${time}`);
|
|
17511
|
+
if (review.body) {
|
|
17512
|
+
console.log(`> ${review.body.split("\n").join("\n> ")}
|
|
17513
|
+
`);
|
|
17514
|
+
}
|
|
17515
|
+
}
|
|
17516
|
+
}
|
|
17517
|
+
if (data.reviewComments.length > 0) {
|
|
17518
|
+
console.log("### Inline Comments (newest first)\n");
|
|
17519
|
+
for (const comment of data.reviewComments) {
|
|
17520
|
+
const time = formatRelativeTime(comment.createdAt);
|
|
17521
|
+
console.log(`**@${comment.user}** on \`${comment.path}\` - ${time}`);
|
|
17522
|
+
console.log(`> ${comment.body.split("\n").join("\n> ")}`);
|
|
17523
|
+
console.log("");
|
|
17524
|
+
}
|
|
17525
|
+
}
|
|
17526
|
+
if (data.issueComments.length > 0) {
|
|
17527
|
+
console.log("### Discussion (newest first)\n");
|
|
17528
|
+
for (const comment of data.issueComments) {
|
|
17529
|
+
const time = formatRelativeTime(comment.createdAt);
|
|
17530
|
+
console.log(`**@${comment.user}** - ${time}`);
|
|
17531
|
+
console.log(`> ${comment.body?.split("\n").join("\n> ")}
|
|
17532
|
+
`);
|
|
17533
|
+
}
|
|
17534
|
+
}
|
|
17535
|
+
if (data.reviewComments.length === 0 && data.issueComments.length === 0 && data.reviews.length === 0) {
|
|
17536
|
+
console.log("No comments from other users.\n");
|
|
17537
|
+
}
|
|
17538
|
+
console.log("---");
|
|
17539
|
+
console.log(
|
|
17540
|
+
`**Summary:** ${data.summary.reviewCount} reviews, ${data.summary.inlineCommentCount} inline comments, ${data.summary.discussionCommentCount} discussion comments`
|
|
17541
|
+
);
|
|
17542
|
+
}
|
|
17543
|
+
} catch (err) {
|
|
17544
|
+
handleCommandError(err, options.json);
|
|
17545
|
+
}
|
|
17553
17546
|
});
|
|
17554
17547
|
program2.command("post <url> [message...]").description("Post a comment to a PR or issue").option("--stdin", "Read message from stdin").option("--json", "Output as JSON").action(async (url, messageParts, options) => {
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
|
|
17548
|
+
try {
|
|
17549
|
+
let message;
|
|
17550
|
+
if (options.stdin) {
|
|
17551
|
+
const chunks = [];
|
|
17552
|
+
for await (const chunk of process.stdin) {
|
|
17553
|
+
chunks.push(chunk);
|
|
17554
|
+
}
|
|
17555
|
+
message = Buffer.concat(chunks).toString("utf-8").trim();
|
|
17556
|
+
} else {
|
|
17557
|
+
message = messageParts.join(" ");
|
|
17558
|
+
}
|
|
17559
|
+
const { runPost: runPost2 } = await Promise.resolve().then(() => (init_comments(), comments_exports));
|
|
17560
|
+
const data = await runPost2({ url, message });
|
|
17561
|
+
if (options.json) {
|
|
17562
|
+
outputJson(data);
|
|
17563
|
+
} else {
|
|
17564
|
+
console.log(`Comment posted: ${data.commentUrl}`);
|
|
17565
|
+
}
|
|
17566
|
+
} catch (err) {
|
|
17567
|
+
handleCommandError(err, options.json);
|
|
17568
|
+
}
|
|
17558
17569
|
});
|
|
17559
17570
|
program2.command("claim <issue-url> [message...]").description("Claim an issue by posting a comment").option("--json", "Output as JSON").action(async (issueUrl, messageParts, options) => {
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17571
|
+
try {
|
|
17572
|
+
const { runClaim: runClaim2 } = await Promise.resolve().then(() => (init_comments(), comments_exports));
|
|
17573
|
+
const message = messageParts.length > 0 ? messageParts.join(" ") : void 0;
|
|
17574
|
+
const data = await runClaim2({ issueUrl, message });
|
|
17575
|
+
if (options.json) {
|
|
17576
|
+
outputJson(data);
|
|
17577
|
+
} else {
|
|
17578
|
+
console.log(`Issue claimed: ${data.commentUrl}`);
|
|
17579
|
+
}
|
|
17580
|
+
} catch (err) {
|
|
17581
|
+
handleCommandError(err, options.json);
|
|
17582
|
+
}
|
|
17563
17583
|
});
|
|
17564
17584
|
program2.command("config [key] [value]").description("Show or update configuration").option("--json", "Output as JSON").action(async (key, value, options) => {
|
|
17565
|
-
|
|
17566
|
-
|
|
17585
|
+
try {
|
|
17586
|
+
const { runConfig: runConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
17587
|
+
const data = await runConfig2({ key, value });
|
|
17588
|
+
if (options.json) {
|
|
17589
|
+
outputJson(data);
|
|
17590
|
+
} else if ("config" in data) {
|
|
17591
|
+
console.log("\n\u2699\uFE0F Current Configuration:\n");
|
|
17592
|
+
console.log(JSON.stringify(data.config, null, 2));
|
|
17593
|
+
} else {
|
|
17594
|
+
console.log(`Set ${data.key} to: ${data.value}`);
|
|
17595
|
+
}
|
|
17596
|
+
} catch (err) {
|
|
17597
|
+
handleCommandError(err, options.json);
|
|
17598
|
+
}
|
|
17567
17599
|
});
|
|
17568
17600
|
program2.command("init <username>").description("Initialize with your GitHub username and import open PRs").option("--json", "Output as JSON").action(async (username, options) => {
|
|
17569
|
-
|
|
17570
|
-
|
|
17601
|
+
try {
|
|
17602
|
+
const { runInit: runInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
17603
|
+
const data = await runInit2({ username });
|
|
17604
|
+
if (options.json) {
|
|
17605
|
+
outputJson(data);
|
|
17606
|
+
} else {
|
|
17607
|
+
console.log(`
|
|
17608
|
+
Username set to @${data.username}.`);
|
|
17609
|
+
console.log("Run `oss-autopilot daily` to fetch your open PRs from GitHub.");
|
|
17610
|
+
}
|
|
17611
|
+
} catch (err) {
|
|
17612
|
+
handleCommandError(err, options.json);
|
|
17613
|
+
}
|
|
17571
17614
|
});
|
|
17572
17615
|
program2.command("setup").description("Interactive setup / configuration").option("--reset", "Re-run setup even if already complete").option("--set <settings...>", "Set specific values (key=value)").option("--json", "Output as JSON").action(async (options) => {
|
|
17573
|
-
|
|
17574
|
-
|
|
17616
|
+
try {
|
|
17617
|
+
const { runSetup: runSetup2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
17618
|
+
const data = await runSetup2({ reset: options.reset, set: options.set });
|
|
17619
|
+
if (options.json) {
|
|
17620
|
+
outputJson(data);
|
|
17621
|
+
} else if ("success" in data) {
|
|
17622
|
+
for (const [key, value] of Object.entries(data.settings)) {
|
|
17623
|
+
console.log(`\u2713 ${key}: ${value}`);
|
|
17624
|
+
}
|
|
17625
|
+
if (data.warnings) {
|
|
17626
|
+
for (const w of data.warnings) {
|
|
17627
|
+
console.warn(w);
|
|
17628
|
+
}
|
|
17629
|
+
}
|
|
17630
|
+
} else if ("setupComplete" in data && data.setupComplete) {
|
|
17631
|
+
console.log("\n\u2699\uFE0F OSS Autopilot Setup\n");
|
|
17632
|
+
console.log("\u2713 Setup already complete!\n");
|
|
17633
|
+
console.log("Current settings:");
|
|
17634
|
+
console.log(` GitHub username: ${data.config.githubUsername || "(not set)"}`);
|
|
17635
|
+
console.log(` Max active PRs: ${data.config.maxActivePRs}`);
|
|
17636
|
+
console.log(` Dormant threshold: ${data.config.dormantThresholdDays} days`);
|
|
17637
|
+
console.log(` Approaching dormant: ${data.config.approachingDormantDays} days`);
|
|
17638
|
+
console.log(` Languages: ${data.config.languages.join(", ")}`);
|
|
17639
|
+
console.log(` Labels: ${data.config.labels.join(", ")}`);
|
|
17640
|
+
console.log(`
|
|
17641
|
+
Run 'setup --reset' to reconfigure.`);
|
|
17642
|
+
} else if ("setupRequired" in data) {
|
|
17643
|
+
console.log("\n\u2699\uFE0F OSS Autopilot Setup\n");
|
|
17644
|
+
console.log("SETUP_REQUIRED");
|
|
17645
|
+
console.log("---");
|
|
17646
|
+
console.log("Please configure the following settings:\n");
|
|
17647
|
+
for (const prompt of data.prompts) {
|
|
17648
|
+
console.log(`SETTING: ${prompt.setting}`);
|
|
17649
|
+
console.log(`PROMPT: ${prompt.prompt}`);
|
|
17650
|
+
const currentVal = Array.isArray(prompt.current) ? prompt.current.join(", ") : prompt.current;
|
|
17651
|
+
console.log(`CURRENT: ${currentVal ?? "(not set)"}`);
|
|
17652
|
+
if (prompt.required) console.log("REQUIRED: true");
|
|
17653
|
+
if (prompt.default !== void 0) {
|
|
17654
|
+
const defaultVal = Array.isArray(prompt.default) ? prompt.default.join(", ") : prompt.default;
|
|
17655
|
+
console.log(`DEFAULT: ${defaultVal}`);
|
|
17656
|
+
}
|
|
17657
|
+
if (prompt.type) console.log(`TYPE: ${prompt.type}`);
|
|
17658
|
+
console.log("");
|
|
17659
|
+
}
|
|
17660
|
+
console.log("---");
|
|
17661
|
+
console.log("END_SETUP_PROMPTS");
|
|
17662
|
+
}
|
|
17663
|
+
} catch (err) {
|
|
17664
|
+
handleCommandError(err, options.json);
|
|
17665
|
+
}
|
|
17575
17666
|
});
|
|
17576
17667
|
program2.command("checkSetup").description("Check if setup is complete").option("--json", "Output as JSON").action(async (options) => {
|
|
17577
|
-
|
|
17578
|
-
|
|
17668
|
+
try {
|
|
17669
|
+
const { runCheckSetup: runCheckSetup2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
17670
|
+
const data = await runCheckSetup2();
|
|
17671
|
+
if (options.json) {
|
|
17672
|
+
outputJson(data);
|
|
17673
|
+
} else if (data.setupComplete) {
|
|
17674
|
+
console.log("SETUP_COMPLETE");
|
|
17675
|
+
console.log(`username=${data.username}`);
|
|
17676
|
+
} else {
|
|
17677
|
+
console.log("SETUP_INCOMPLETE");
|
|
17678
|
+
}
|
|
17679
|
+
} catch (err) {
|
|
17680
|
+
handleCommandError(err, options.json);
|
|
17681
|
+
}
|
|
17682
|
+
});
|
|
17683
|
+
var dashboardCmd = program2.command("dashboard").description("Dashboard commands");
|
|
17684
|
+
dashboardCmd.command("serve").description("Start interactive dashboard server").option("--port <port>", "Port to listen on", "3000").option("--no-open", "Do not open browser automatically").action(async (options) => {
|
|
17685
|
+
const port = parseInt(options.port, 10);
|
|
17686
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
17687
|
+
console.error(`Invalid port number: "${options.port}". Must be an integer between 1 and 65535.`);
|
|
17688
|
+
process.exit(1);
|
|
17689
|
+
}
|
|
17690
|
+
const { serveDashboard: serveDashboard2 } = await Promise.resolve().then(() => (init_dashboard(), dashboard_exports));
|
|
17691
|
+
await serveDashboard2({ port, open: options.open });
|
|
17579
17692
|
});
|
|
17580
|
-
|
|
17693
|
+
dashboardCmd.option("--open", "Open in browser").option("--json", "Output as JSON").option("--offline", "Use cached data only (no GitHub API calls)").action(async (options) => {
|
|
17581
17694
|
const { runDashboard: runDashboard2 } = await Promise.resolve().then(() => (init_dashboard(), dashboard_exports));
|
|
17582
17695
|
await runDashboard2({ open: options.open, json: options.json, offline: options.offline });
|
|
17583
17696
|
});
|
|
17584
17697
|
program2.command("parse-issue-list <path>").description("Parse a markdown issue list into structured JSON").option("--json", "Output as JSON").action(async (filePath, options) => {
|
|
17585
|
-
|
|
17586
|
-
|
|
17698
|
+
try {
|
|
17699
|
+
const { runParseList: runParseList2 } = await Promise.resolve().then(() => (init_parse_list(), parse_list_exports));
|
|
17700
|
+
const data = await runParseList2({ filePath });
|
|
17701
|
+
if (options.json) {
|
|
17702
|
+
outputJson(data);
|
|
17703
|
+
} else {
|
|
17704
|
+
const path11 = await import("path");
|
|
17705
|
+
const resolvedPath = path11.resolve(filePath);
|
|
17706
|
+
console.log(`
|
|
17707
|
+
\u{1F4CB} Issue List: ${resolvedPath}
|
|
17708
|
+
`);
|
|
17709
|
+
console.log(`Available: ${data.availableCount} | Completed: ${data.completedCount}
|
|
17710
|
+
`);
|
|
17711
|
+
if (data.available.length > 0) {
|
|
17712
|
+
console.log("--- Available ---");
|
|
17713
|
+
for (const item of data.available) {
|
|
17714
|
+
console.log(` [${item.tier}] ${item.repo}#${item.number}: ${item.title}`);
|
|
17715
|
+
}
|
|
17716
|
+
}
|
|
17717
|
+
if (data.completed.length > 0) {
|
|
17718
|
+
console.log("\n--- Completed ---");
|
|
17719
|
+
for (const item of data.completed) {
|
|
17720
|
+
console.log(` [${item.tier}] ${item.repo}#${item.number}: ${item.title}`);
|
|
17721
|
+
}
|
|
17722
|
+
}
|
|
17723
|
+
}
|
|
17724
|
+
} catch (err) {
|
|
17725
|
+
handleCommandError(err, options.json);
|
|
17726
|
+
}
|
|
17587
17727
|
});
|
|
17588
17728
|
program2.command("check-integration").description("Detect new files not referenced by the codebase").option("--base <branch>", "Base branch to compare against", "main").option("--json", "Output as JSON").action(async (options) => {
|
|
17589
|
-
|
|
17590
|
-
|
|
17729
|
+
try {
|
|
17730
|
+
const { runCheckIntegration: runCheckIntegration2 } = await Promise.resolve().then(() => (init_check_integration(), check_integration_exports));
|
|
17731
|
+
const data = await runCheckIntegration2({ base: options.base });
|
|
17732
|
+
if (options.json) {
|
|
17733
|
+
outputJson(data);
|
|
17734
|
+
} else if (data.newFiles.length === 0) {
|
|
17735
|
+
console.log("\nNo new code files to check.");
|
|
17736
|
+
} else {
|
|
17737
|
+
console.log(`
|
|
17738
|
+
\u{1F50D} Integration Check (base: ${options.base})
|
|
17739
|
+
`);
|
|
17740
|
+
console.log(`New files: ${data.newFiles.length} | Unreferenced: ${data.unreferencedCount}
|
|
17741
|
+
`);
|
|
17742
|
+
for (const file of data.newFiles) {
|
|
17743
|
+
const status = file.isIntegrated ? "\u2705" : "\u26A0\uFE0F";
|
|
17744
|
+
console.log(`${status} ${file.path}`);
|
|
17745
|
+
if (file.isIntegrated) {
|
|
17746
|
+
console.log(` Referenced by: ${file.referencedBy.join(", ")}`);
|
|
17747
|
+
} else {
|
|
17748
|
+
console.log(" Not referenced by any file");
|
|
17749
|
+
if (file.suggestedEntryPoints && file.suggestedEntryPoints.length > 0) {
|
|
17750
|
+
console.log(` Suggested entry points: ${file.suggestedEntryPoints.join(", ")}`);
|
|
17751
|
+
}
|
|
17752
|
+
}
|
|
17753
|
+
}
|
|
17754
|
+
}
|
|
17755
|
+
} catch (err) {
|
|
17756
|
+
handleCommandError(err, options.json);
|
|
17757
|
+
}
|
|
17591
17758
|
});
|
|
17592
17759
|
program2.command("local-repos").description("Scan filesystem for local git clones").option("--scan", "Force re-scan (ignores cache)").option("--paths <dirs...>", "Directories to scan").option("--json", "Output as JSON").action(async (options) => {
|
|
17593
|
-
|
|
17594
|
-
|
|
17760
|
+
try {
|
|
17761
|
+
const { runLocalRepos: runLocalRepos2 } = await Promise.resolve().then(() => (init_local_repos(), local_repos_exports));
|
|
17762
|
+
const data = await runLocalRepos2({ scan: options.scan, paths: options.paths });
|
|
17763
|
+
if (options.json) {
|
|
17764
|
+
outputJson(data);
|
|
17765
|
+
} else if (data.fromCache) {
|
|
17766
|
+
console.log(`
|
|
17767
|
+
\u{1F4C1} Local Repos (cached ${data.cachedAt})
|
|
17768
|
+
`);
|
|
17769
|
+
printRepos(data.repos);
|
|
17770
|
+
} else {
|
|
17771
|
+
console.log(`Found ${Object.keys(data.repos).length} repos:
|
|
17772
|
+
`);
|
|
17773
|
+
printRepos(data.repos);
|
|
17774
|
+
}
|
|
17775
|
+
} catch (err) {
|
|
17776
|
+
handleCommandError(err, options.json);
|
|
17777
|
+
}
|
|
17595
17778
|
});
|
|
17596
17779
|
program2.command("startup").description("Run all pre-flight checks and daily fetch in one call").option("--json", "Output as JSON").action(async (options) => {
|
|
17597
|
-
|
|
17598
|
-
|
|
17780
|
+
try {
|
|
17781
|
+
const { runStartup: runStartup2 } = await Promise.resolve().then(() => (init_startup(), startup_exports));
|
|
17782
|
+
const data = await runStartup2();
|
|
17783
|
+
if (options.json) {
|
|
17784
|
+
outputJson(data);
|
|
17785
|
+
} else {
|
|
17786
|
+
if (!data.setupComplete) {
|
|
17787
|
+
console.log("Setup incomplete. Run /setup-oss first.");
|
|
17788
|
+
} else if (data.authError) {
|
|
17789
|
+
console.error(`Error: ${data.authError}`);
|
|
17790
|
+
} else {
|
|
17791
|
+
console.log(`OSS Autopilot v${data.version}`);
|
|
17792
|
+
console.log(data.daily?.briefSummary ?? "");
|
|
17793
|
+
if (data.dashboardPath) console.log(`Dashboard: ${data.dashboardPath}`);
|
|
17794
|
+
}
|
|
17795
|
+
}
|
|
17796
|
+
} catch (err) {
|
|
17797
|
+
handleCommandError(err, options.json);
|
|
17798
|
+
}
|
|
17599
17799
|
});
|
|
17600
17800
|
program2.command("shelve <pr-url>").description("Shelve a PR (exclude from capacity and actionable issues)").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17601
|
-
|
|
17602
|
-
|
|
17801
|
+
try {
|
|
17802
|
+
const { runShelve: runShelve2 } = await Promise.resolve().then(() => (init_shelve(), shelve_exports));
|
|
17803
|
+
const data = await runShelve2({ prUrl });
|
|
17804
|
+
if (options.json) {
|
|
17805
|
+
outputJson(data);
|
|
17806
|
+
} else if (data.shelved) {
|
|
17807
|
+
console.log(`Shelved: ${prUrl}`);
|
|
17808
|
+
console.log("This PR is now excluded from capacity and actionable issues.");
|
|
17809
|
+
console.log("It will auto-unshelve if a maintainer engages.");
|
|
17810
|
+
} else {
|
|
17811
|
+
console.log("PR is already shelved.");
|
|
17812
|
+
}
|
|
17813
|
+
} catch (err) {
|
|
17814
|
+
handleCommandError(err, options.json);
|
|
17815
|
+
}
|
|
17603
17816
|
});
|
|
17604
17817
|
program2.command("unshelve <pr-url>").description("Unshelve a PR (include in capacity and actionable issues again)").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17605
|
-
|
|
17606
|
-
|
|
17818
|
+
try {
|
|
17819
|
+
const { runUnshelve: runUnshelve2 } = await Promise.resolve().then(() => (init_shelve(), shelve_exports));
|
|
17820
|
+
const data = await runUnshelve2({ prUrl });
|
|
17821
|
+
if (options.json) {
|
|
17822
|
+
outputJson(data);
|
|
17823
|
+
} else if (data.unshelved) {
|
|
17824
|
+
console.log(`Unshelved: ${prUrl}`);
|
|
17825
|
+
console.log("This PR is now active again.");
|
|
17826
|
+
} else {
|
|
17827
|
+
console.log("PR was not shelved.");
|
|
17828
|
+
}
|
|
17829
|
+
} catch (err) {
|
|
17830
|
+
handleCommandError(err, options.json);
|
|
17831
|
+
}
|
|
17607
17832
|
});
|
|
17608
17833
|
program2.command("dismiss <issue-url>").description("Dismiss issue reply notifications (resurfaces on new activity)").option("--json", "Output as JSON").action(async (issueUrl, options) => {
|
|
17609
|
-
|
|
17610
|
-
|
|
17834
|
+
try {
|
|
17835
|
+
const { runDismiss: runDismiss2 } = await Promise.resolve().then(() => (init_dismiss(), dismiss_exports));
|
|
17836
|
+
const data = await runDismiss2({ issueUrl });
|
|
17837
|
+
if (options.json) {
|
|
17838
|
+
outputJson(data);
|
|
17839
|
+
} else if (data.dismissed) {
|
|
17840
|
+
console.log(`Dismissed: ${issueUrl}`);
|
|
17841
|
+
console.log("Issue reply notifications are now muted.");
|
|
17842
|
+
console.log("New responses after this point will resurface automatically.");
|
|
17843
|
+
} else {
|
|
17844
|
+
console.log("Issue is already dismissed.");
|
|
17845
|
+
}
|
|
17846
|
+
} catch (err) {
|
|
17847
|
+
handleCommandError(err, options.json);
|
|
17848
|
+
}
|
|
17611
17849
|
});
|
|
17612
17850
|
program2.command("undismiss <issue-url>").description("Undismiss an issue (re-enable reply notifications)").option("--json", "Output as JSON").action(async (issueUrl, options) => {
|
|
17613
|
-
|
|
17614
|
-
|
|
17851
|
+
try {
|
|
17852
|
+
const { runUndismiss: runUndismiss2 } = await Promise.resolve().then(() => (init_dismiss(), dismiss_exports));
|
|
17853
|
+
const data = await runUndismiss2({ issueUrl });
|
|
17854
|
+
if (options.json) {
|
|
17855
|
+
outputJson(data);
|
|
17856
|
+
} else if (data.undismissed) {
|
|
17857
|
+
console.log(`Undismissed: ${issueUrl}`);
|
|
17858
|
+
console.log("Issue reply notifications are active again.");
|
|
17859
|
+
} else {
|
|
17860
|
+
console.log("Issue was not dismissed.");
|
|
17861
|
+
}
|
|
17862
|
+
} catch (err) {
|
|
17863
|
+
handleCommandError(err, options.json);
|
|
17864
|
+
}
|
|
17615
17865
|
});
|
|
17616
17866
|
program2.command("snooze <pr-url>").description("Snooze CI failure notifications for a PR").requiredOption("--reason <reason>", 'Reason for snoozing (e.g., "upstream infrastructure issue")').option("--days <days>", "Number of days to snooze (default: 7)", "7").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17617
|
-
|
|
17618
|
-
|
|
17867
|
+
try {
|
|
17868
|
+
const { runSnooze: runSnooze2 } = await Promise.resolve().then(() => (init_snooze(), snooze_exports));
|
|
17869
|
+
const data = await runSnooze2({ prUrl, reason: options.reason, days: parseInt(options.days, 10) });
|
|
17870
|
+
if (options.json) {
|
|
17871
|
+
outputJson(data);
|
|
17872
|
+
} else if (data.snoozed) {
|
|
17873
|
+
console.log(`Snoozed: ${prUrl}`);
|
|
17874
|
+
console.log(`Reason: ${data.reason}`);
|
|
17875
|
+
console.log(`Duration: ${data.days} day${data.days === 1 ? "" : "s"}`);
|
|
17876
|
+
console.log(`Expires: ${data.expiresAt ? new Date(data.expiresAt).toLocaleString() : "unknown"}`);
|
|
17877
|
+
console.log("CI failure notifications are now muted for this PR.");
|
|
17878
|
+
} else {
|
|
17879
|
+
console.log("PR is already snoozed.");
|
|
17880
|
+
if (data.expiresAt) {
|
|
17881
|
+
console.log(`Expires: ${new Date(data.expiresAt).toLocaleString()}`);
|
|
17882
|
+
}
|
|
17883
|
+
}
|
|
17884
|
+
} catch (err) {
|
|
17885
|
+
handleCommandError(err, options.json);
|
|
17886
|
+
}
|
|
17619
17887
|
});
|
|
17620
17888
|
program2.command("unsnooze <pr-url>").description("Unsnooze a PR (re-enable CI failure notifications)").option("--json", "Output as JSON").action(async (prUrl, options) => {
|
|
17621
|
-
|
|
17622
|
-
|
|
17889
|
+
try {
|
|
17890
|
+
const { runUnsnooze: runUnsnooze2 } = await Promise.resolve().then(() => (init_snooze(), snooze_exports));
|
|
17891
|
+
const data = await runUnsnooze2({ prUrl });
|
|
17892
|
+
if (options.json) {
|
|
17893
|
+
outputJson(data);
|
|
17894
|
+
} else if (data.unsnoozed) {
|
|
17895
|
+
console.log(`Unsnoozed: ${prUrl}`);
|
|
17896
|
+
console.log("CI failure notifications are active again for this PR.");
|
|
17897
|
+
} else {
|
|
17898
|
+
console.log("PR was not snoozed.");
|
|
17899
|
+
}
|
|
17900
|
+
} catch (err) {
|
|
17901
|
+
handleCommandError(err, options.json);
|
|
17902
|
+
}
|
|
17623
17903
|
});
|
|
17624
17904
|
program2.hook("preAction", async (thisCommand, actionCommand) => {
|
|
17625
17905
|
const globalOpts = thisCommand.opts();
|