@oss-autopilot/core 0.41.0 → 0.42.1
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 +1552 -1318
- package/dist/cli.js +593 -69
- package/dist/commands/check-integration.d.ts +3 -3
- package/dist/commands/check-integration.js +10 -43
- package/dist/commands/comments.d.ts +6 -9
- package/dist/commands/comments.js +102 -252
- 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 +33 -45
- package/dist/commands/dashboard-data.js +7 -6
- package/dist/commands/dashboard-server.d.ts +14 -0
- package/dist/commands/dashboard-server.js +362 -0
- package/dist/commands/dashboard.d.ts +5 -0
- package/dist/commands/dashboard.js +51 -1
- 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 +6 -33
- package/dist/commands/parse-list.d.ts +3 -4
- package/dist/commands/parse-list.js +8 -39
- 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 +44 -82
- 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 +7 -15
- package/dist/commands/vet.d.ts +3 -3
- package/dist/commands/vet.js +16 -26
- package/dist/core/errors.d.ts +9 -0
- package/dist/core/errors.js +17 -0
- package/dist/core/github-stats.d.ts +14 -21
- package/dist/core/github-stats.js +84 -138
- package/dist/core/http-cache.d.ts +6 -0
- package/dist/core/http-cache.js +16 -4
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +2 -1
- package/dist/core/issue-conversation.js +4 -4
- package/dist/core/issue-discovery.js +14 -14
- package/dist/core/issue-vetting.js +17 -17
- package/dist/core/pr-monitor.d.ts +6 -20
- package/dist/core/pr-monitor.js +11 -52
- package/dist/core/state.js +4 -5
- package/dist/core/utils.d.ts +11 -0
- package/dist/core/utils.js +21 -0
- package/dist/formatters/json.d.ts +58 -0
- package/package.json +5 -1
package/dist/core/pr-monitor.js
CHANGED
|
@@ -15,7 +15,7 @@ import { getOctokit } from './github.js';
|
|
|
15
15
|
import { getStateManager } from './state.js';
|
|
16
16
|
import { daysBetween, parseGitHubUrl, extractOwnerRepo } from './utils.js';
|
|
17
17
|
import { runWorkerPool } from './concurrency.js';
|
|
18
|
-
import { ConfigurationError, ValidationError } from './errors.js';
|
|
18
|
+
import { ConfigurationError, ValidationError, errorMessage, getHttpStatusCode } from './errors.js';
|
|
19
19
|
import { paginateAll } from './pagination.js';
|
|
20
20
|
import { debug, warn, timed } from './logger.js';
|
|
21
21
|
import { getHttpCache, cachedRequest } from './http-cache.js';
|
|
@@ -114,9 +114,9 @@ export class PRMonitor {
|
|
|
114
114
|
prs.push(pr);
|
|
115
115
|
}
|
|
116
116
|
catch (error) {
|
|
117
|
-
const
|
|
118
|
-
warn('pr-monitor', `Error fetching ${item.html_url}: ${
|
|
119
|
-
failures.push({ prUrl: item.html_url, error:
|
|
117
|
+
const errMsg = errorMessage(error);
|
|
118
|
+
warn('pr-monitor', `Error fetching ${item.html_url}: ${errMsg}`);
|
|
119
|
+
failures.push({ prUrl: item.html_url, error: errMsg });
|
|
120
120
|
}
|
|
121
121
|
}, MAX_CONCURRENT_REQUESTS);
|
|
122
122
|
});
|
|
@@ -162,14 +162,14 @@ export class PRMonitor {
|
|
|
162
162
|
paginateAll((page) => this.octokit.issues.listComments({ owner, repo, issue_number: number, per_page: 100, page })),
|
|
163
163
|
this.octokit.pulls.listReviews({ owner, repo, pull_number: number }),
|
|
164
164
|
paginateAll((page) => this.octokit.pulls.listReviewComments({ owner, repo, pull_number: number, per_page: 100, page })).catch((err) => {
|
|
165
|
-
const status = err
|
|
165
|
+
const status = getHttpStatusCode(err);
|
|
166
166
|
// Rate limit errors must propagate — silently swallowing them hides
|
|
167
167
|
// a systemic problem and produces misleading results (#229).
|
|
168
168
|
if (status === 429) {
|
|
169
169
|
throw err;
|
|
170
170
|
}
|
|
171
171
|
if (status === 403) {
|
|
172
|
-
const msg = (err
|
|
172
|
+
const msg = errorMessage(err).toLowerCase();
|
|
173
173
|
if (msg.includes('rate limit') || msg.includes('abuse detection')) {
|
|
174
174
|
throw err;
|
|
175
175
|
}
|
|
@@ -349,7 +349,7 @@ export class PRMonitor {
|
|
|
349
349
|
this.octokit.repos.getCombinedStatusForRef({ owner, repo, ref: sha }),
|
|
350
350
|
// 404 is expected for repos without check runs configured; log other errors for debugging
|
|
351
351
|
this.octokit.checks.listForRef({ owner, repo, ref: sha }).catch((err) => {
|
|
352
|
-
const status = err
|
|
352
|
+
const status = getHttpStatusCode(err);
|
|
353
353
|
if (status === 404) {
|
|
354
354
|
debug('pr-monitor', `Check runs 404 for ${owner}/${repo}@${sha.slice(0, 7)} (no checks configured)`);
|
|
355
355
|
}
|
|
@@ -378,8 +378,8 @@ export class PRMonitor {
|
|
|
378
378
|
return mergeStatuses(checkRunAnalysis, combinedAnalysis, checkRuns.length);
|
|
379
379
|
}
|
|
380
380
|
catch (error) {
|
|
381
|
-
const statusCode = error
|
|
382
|
-
const
|
|
381
|
+
const statusCode = getHttpStatusCode(error);
|
|
382
|
+
const errMsg = errorMessage(error);
|
|
383
383
|
if (statusCode === 401) {
|
|
384
384
|
warn('pr-monitor', `CI check failed for ${owner}/${repo}: Invalid token`);
|
|
385
385
|
}
|
|
@@ -392,7 +392,7 @@ export class PRMonitor {
|
|
|
392
392
|
return { status: 'unknown', failingCheckNames: [], failingCheckConclusions: new Map() };
|
|
393
393
|
}
|
|
394
394
|
else {
|
|
395
|
-
warn('pr-monitor', `Failed to check CI for ${owner}/${repo}@${sha.slice(0, 7)}: ${
|
|
395
|
+
warn('pr-monitor', `Failed to check CI for ${owner}/${repo}@${sha.slice(0, 7)}: ${errMsg}`);
|
|
396
396
|
}
|
|
397
397
|
return { status: 'unknown', failingCheckNames: [], failingCheckConclusions: new Map() };
|
|
398
398
|
}
|
|
@@ -451,7 +451,7 @@ export class PRMonitor {
|
|
|
451
451
|
}
|
|
452
452
|
else {
|
|
453
453
|
chunkFailures++;
|
|
454
|
-
warn(MODULE, `Failed to fetch stars for ${chunk[j]}: ${result.reason
|
|
454
|
+
warn(MODULE, `Failed to fetch stars for ${chunk[j]}: ${errorMessage(result.reason)}`);
|
|
455
455
|
}
|
|
456
456
|
}
|
|
457
457
|
// If entire chunk failed, likely a systemic issue (rate limit, auth, outage) — abort remaining
|
|
@@ -466,47 +466,6 @@ export class PRMonitor {
|
|
|
466
466
|
debug(MODULE, `Fetched star counts for ${results.size}/${repos.length} repos`);
|
|
467
467
|
return results;
|
|
468
468
|
}
|
|
469
|
-
/**
|
|
470
|
-
* Shared helper: search for recent PRs and filter out own repos, excluded repos/orgs.
|
|
471
|
-
* Returns parsed search results that pass all filters.
|
|
472
|
-
*/
|
|
473
|
-
async fetchRecentPRs(query, label, days, mapItem) {
|
|
474
|
-
const config = this.stateManager.getState().config;
|
|
475
|
-
if (!config.githubUsername) {
|
|
476
|
-
warn(MODULE, `Skipping recently ${label} PRs fetch: no githubUsername configured. Run /setup-oss to configure.`);
|
|
477
|
-
return [];
|
|
478
|
-
}
|
|
479
|
-
const sinceDate = new Date();
|
|
480
|
-
sinceDate.setDate(sinceDate.getDate() - days);
|
|
481
|
-
const since = sinceDate.toISOString().split('T')[0]; // YYYY-MM-DD
|
|
482
|
-
debug(MODULE, `Fetching recently ${label} PRs for @${config.githubUsername} (since ${since})...`);
|
|
483
|
-
const { data } = await this.octokit.search.issuesAndPullRequests({
|
|
484
|
-
q: query.replace('{username}', config.githubUsername).replace('{since}', since),
|
|
485
|
-
sort: 'updated',
|
|
486
|
-
order: 'desc',
|
|
487
|
-
per_page: 100,
|
|
488
|
-
});
|
|
489
|
-
const results = [];
|
|
490
|
-
for (const item of data.items) {
|
|
491
|
-
const parsed = parseGitHubUrl(item.html_url);
|
|
492
|
-
if (!parsed) {
|
|
493
|
-
warn(MODULE, `Could not parse GitHub URL from API response: ${item.html_url}`);
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
const repo = `${parsed.owner}/${parsed.repo}`;
|
|
497
|
-
// Skip own repos
|
|
498
|
-
if (parsed.owner.toLowerCase() === config.githubUsername.toLowerCase())
|
|
499
|
-
continue;
|
|
500
|
-
// Skip excluded repos and orgs
|
|
501
|
-
if (config.excludeRepos.includes(repo))
|
|
502
|
-
continue;
|
|
503
|
-
if (config.excludeOrgs?.some((org) => parsed.owner.toLowerCase() === org.toLowerCase()))
|
|
504
|
-
continue;
|
|
505
|
-
results.push(mapItem(item, { owner: parsed.owner, repo, number: parsed.number }));
|
|
506
|
-
}
|
|
507
|
-
debug(MODULE, `Found ${results.length} recently ${label} PRs`);
|
|
508
|
-
return results;
|
|
509
|
-
}
|
|
510
469
|
/**
|
|
511
470
|
* Fetch PRs closed without merge in the last N days.
|
|
512
471
|
* Delegates to github-stats module.
|
package/dist/core/state.js
CHANGED
|
@@ -6,7 +6,7 @@ import * as fs from 'fs';
|
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { INITIAL_STATE, } from './types.js';
|
|
8
8
|
import { getStatePath, getBackupDir, getDataDir } from './utils.js';
|
|
9
|
-
import { ValidationError } from './errors.js';
|
|
9
|
+
import { ValidationError, errorMessage } from './errors.js';
|
|
10
10
|
import { debug, warn } from './logger.js';
|
|
11
11
|
const MODULE = 'state';
|
|
12
12
|
// Current state version
|
|
@@ -272,8 +272,7 @@ export class StateManager {
|
|
|
272
272
|
return true;
|
|
273
273
|
}
|
|
274
274
|
catch (error) {
|
|
275
|
-
|
|
276
|
-
warn(MODULE, `Failed to migrate state: ${errorMessage}`);
|
|
275
|
+
warn(MODULE, `Failed to migrate state: ${errorMessage(error)}`);
|
|
277
276
|
// Clean up partial migration to avoid inconsistent state
|
|
278
277
|
const newStatePath = getStatePath();
|
|
279
278
|
if (fs.existsSync(newStatePath) && fs.existsSync(LEGACY_STATE_FILE)) {
|
|
@@ -471,12 +470,12 @@ export class StateManager {
|
|
|
471
470
|
fs.unlinkSync(path.join(backupDir, file));
|
|
472
471
|
}
|
|
473
472
|
catch (error) {
|
|
474
|
-
warn(MODULE, `Could not delete old backup ${file}:`, error
|
|
473
|
+
warn(MODULE, `Could not delete old backup ${file}:`, errorMessage(error));
|
|
475
474
|
}
|
|
476
475
|
}
|
|
477
476
|
}
|
|
478
477
|
catch (error) {
|
|
479
|
-
warn(MODULE, 'Could not clean up backups:', error
|
|
478
|
+
warn(MODULE, 'Could not clean up backups:', errorMessage(error));
|
|
480
479
|
}
|
|
481
480
|
}
|
|
482
481
|
/**
|
package/dist/core/utils.d.ts
CHANGED
|
@@ -157,6 +157,17 @@ export declare function splitRepo(repoFullName: string): {
|
|
|
157
157
|
owner: string;
|
|
158
158
|
repo: string;
|
|
159
159
|
};
|
|
160
|
+
/**
|
|
161
|
+
* Case-insensitive check whether a repo owner matches the given GitHub username.
|
|
162
|
+
* Used to skip a user's own repos (PRs to your own repos aren't OSS contributions).
|
|
163
|
+
*/
|
|
164
|
+
export declare function isOwnRepo(owner: string, username: string): boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Read the CLI package version from package.json relative to the running CLI bundle.
|
|
167
|
+
* Resolves `../package.json` from `process.argv[1]` (the bundle entry point).
|
|
168
|
+
* Falls back to '0.0.0' if the file is unreadable.
|
|
169
|
+
*/
|
|
170
|
+
export declare function getCLIVersion(): string;
|
|
160
171
|
/**
|
|
161
172
|
* Formats a timestamp as a human-readable relative time string.
|
|
162
173
|
*
|
package/dist/core/utils.js
CHANGED
|
@@ -228,6 +228,27 @@ export function splitRepo(repoFullName) {
|
|
|
228
228
|
const [owner, repo] = repoFullName.split('/');
|
|
229
229
|
return { owner, repo };
|
|
230
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Case-insensitive check whether a repo owner matches the given GitHub username.
|
|
233
|
+
* Used to skip a user's own repos (PRs to your own repos aren't OSS contributions).
|
|
234
|
+
*/
|
|
235
|
+
export function isOwnRepo(owner, username) {
|
|
236
|
+
return owner.toLowerCase() === username.toLowerCase();
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Read the CLI package version from package.json relative to the running CLI bundle.
|
|
240
|
+
* Resolves `../package.json` from `process.argv[1]` (the bundle entry point).
|
|
241
|
+
* Falls back to '0.0.0' if the file is unreadable.
|
|
242
|
+
*/
|
|
243
|
+
export function getCLIVersion() {
|
|
244
|
+
try {
|
|
245
|
+
const pkgPath = path.join(path.dirname(process.argv[1]), '..', 'package.json');
|
|
246
|
+
return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version;
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return '0.0.0';
|
|
250
|
+
}
|
|
251
|
+
}
|
|
231
252
|
/**
|
|
232
253
|
* Formats a timestamp as a human-readable relative time string.
|
|
233
254
|
*
|
|
@@ -238,6 +238,64 @@ export interface CheckIntegrationOutput {
|
|
|
238
238
|
newFiles: NewFileInfo[];
|
|
239
239
|
unreferencedCount: number;
|
|
240
240
|
}
|
|
241
|
+
/** Output of the vet command */
|
|
242
|
+
export interface VetOutput {
|
|
243
|
+
issue: {
|
|
244
|
+
repo: string;
|
|
245
|
+
number: number;
|
|
246
|
+
title: string;
|
|
247
|
+
url: string;
|
|
248
|
+
labels: string[];
|
|
249
|
+
};
|
|
250
|
+
recommendation: 'approve' | 'skip' | 'needs_review';
|
|
251
|
+
reasonsToApprove: string[];
|
|
252
|
+
reasonsToSkip: string[];
|
|
253
|
+
projectHealth: unknown;
|
|
254
|
+
vettingResult: unknown;
|
|
255
|
+
}
|
|
256
|
+
/** Output of the comments command */
|
|
257
|
+
export interface CommentsOutput {
|
|
258
|
+
pr: {
|
|
259
|
+
title: string;
|
|
260
|
+
state: string;
|
|
261
|
+
mergeable: boolean | null;
|
|
262
|
+
head: string;
|
|
263
|
+
base: string;
|
|
264
|
+
url: string;
|
|
265
|
+
};
|
|
266
|
+
reviews: Array<{
|
|
267
|
+
user: string | undefined;
|
|
268
|
+
state: string;
|
|
269
|
+
body: string | null;
|
|
270
|
+
submittedAt: string | null;
|
|
271
|
+
}>;
|
|
272
|
+
reviewComments: Array<{
|
|
273
|
+
user: string | undefined;
|
|
274
|
+
body: string;
|
|
275
|
+
path: string;
|
|
276
|
+
createdAt: string;
|
|
277
|
+
}>;
|
|
278
|
+
issueComments: Array<{
|
|
279
|
+
user: string | undefined;
|
|
280
|
+
body: string | undefined;
|
|
281
|
+
createdAt: string;
|
|
282
|
+
}>;
|
|
283
|
+
summary: {
|
|
284
|
+
reviewCount: number;
|
|
285
|
+
inlineCommentCount: number;
|
|
286
|
+
discussionCommentCount: number;
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
/** Output of the post command */
|
|
290
|
+
export interface PostOutput {
|
|
291
|
+
commentUrl: string;
|
|
292
|
+
url: string;
|
|
293
|
+
}
|
|
294
|
+
/** Output of the claim command */
|
|
295
|
+
export interface ClaimOutput {
|
|
296
|
+
commentUrl: string;
|
|
297
|
+
issueUrl: string;
|
|
298
|
+
}
|
|
241
299
|
/** Info about a local git clone (#84) */
|
|
242
300
|
export interface LocalRepoInfo {
|
|
243
301
|
path: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oss-autopilot/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.1",
|
|
4
4
|
"description": "CLI and core library for managing open source contributions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./types": {
|
|
15
15
|
"import": "./dist/core/types.js",
|
|
16
16
|
"types": "./dist/core/types.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./commands": {
|
|
19
|
+
"import": "./dist/commands/index.js",
|
|
20
|
+
"types": "./dist/commands/index.d.ts"
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"files": [
|