@oss-autopilot/core 1.11.0 → 1.12.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/README.md +8 -5
- package/dist/cli.bundle.cjs +67 -108
- package/dist/commands/daily.js +17 -0
- package/dist/commands/index.d.ts +3 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/scout-bridge.d.ts +15 -0
- package/dist/commands/scout-bridge.js +63 -0
- package/dist/commands/search.d.ts +1 -1
- package/dist/commands/search.js +10 -13
- package/dist/commands/vet-list.d.ts +1 -1
- package/dist/commands/vet-list.js +4 -5
- package/dist/commands/vet.d.ts +1 -1
- package/dist/commands/vet.js +4 -5
- package/dist/core/index.d.ts +0 -2
- package/dist/core/index.js +1 -2
- package/package.json +2 -1
- package/dist/core/category-mapping.d.ts +0 -19
- package/dist/core/category-mapping.js +0 -58
- package/dist/core/issue-discovery.d.ts +0 -94
- package/dist/core/issue-discovery.js +0 -591
- package/dist/core/issue-eligibility.d.ts +0 -38
- package/dist/core/issue-eligibility.js +0 -151
- package/dist/core/issue-filtering.d.ts +0 -51
- package/dist/core/issue-filtering.js +0 -103
- package/dist/core/issue-scoring.d.ts +0 -43
- package/dist/core/issue-scoring.js +0 -97
- package/dist/core/issue-vetting.d.ts +0 -33
- package/dist/core/issue-vetting.js +0 -306
- package/dist/core/repo-health.d.ts +0 -24
- package/dist/core/repo-health.js +0 -194
- package/dist/core/search-budget.d.ts +0 -62
- package/dist/core/search-budget.js +0 -129
- package/dist/core/search-phases.d.ts +0 -83
- package/dist/core/search-phases.js +0 -238
package/dist/commands/daily.js
CHANGED
|
@@ -10,6 +10,7 @@ import { getStateManager, PRMonitor, IssueConversationMonitor, requireGitHubToke
|
|
|
10
10
|
import { errorMessage, isRateLimitOrAuthError } from '../core/errors.js';
|
|
11
11
|
import { warn } from '../core/logger.js';
|
|
12
12
|
import { emptyPRCountsResult } from '../core/github-stats.js';
|
|
13
|
+
import { createAutopilotScout } from './scout-bridge.js';
|
|
13
14
|
import { updateMonthlyAnalytics } from './dashboard-data.js';
|
|
14
15
|
import { deduplicateDigest, compactActionableIssues, compactRepoGroups, } from '../formatters/json.js';
|
|
15
16
|
const MODULE = 'daily';
|
|
@@ -444,6 +445,22 @@ async function executeDailyCheckInternal(token) {
|
|
|
444
445
|
catch (error) {
|
|
445
446
|
warn(MODULE, `Failed to persist monthly analytics: ${errorMessage(error)}`);
|
|
446
447
|
}
|
|
448
|
+
// Phase 3.5: Feed merged/closed PRs to oss-scout for cross-tool state sync.
|
|
449
|
+
if (recentlyMergedPRs.length > 0 || recentlyClosedPRs.length > 0) {
|
|
450
|
+
try {
|
|
451
|
+
const scout = await createAutopilotScout();
|
|
452
|
+
for (const pr of recentlyMergedPRs) {
|
|
453
|
+
scout.recordMergedPR({ url: pr.url, title: pr.title, mergedAt: pr.mergedAt, repo: pr.repo });
|
|
454
|
+
}
|
|
455
|
+
for (const pr of recentlyClosedPRs) {
|
|
456
|
+
scout.recordClosedPR({ url: pr.url, title: pr.title, closedAt: pr.closedAt, repo: pr.repo });
|
|
457
|
+
}
|
|
458
|
+
await scout.checkpoint();
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
warn(MODULE, `Failed to sync PR data to oss-scout: ${errorMessage(error)}`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
447
464
|
// Capture lastDigestAt BEFORE Phase 4 overwrites it with the current run's timestamp.
|
|
448
465
|
// Used by collectActionableIssues to determine which PRs are "new" (created since last digest).
|
|
449
466
|
const previousLastDigestAt = getStateManager().getState().lastDigestAt;
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export { runStatus } from './status.js';
|
|
|
25
25
|
export { runSearch } from './search.js';
|
|
26
26
|
/** Vet a single GitHub issue for claimability (open, unassigned, no linked PRs, repo health). */
|
|
27
27
|
export { runVet } from './vet.js';
|
|
28
|
+
/** Re-vet all available issues in a curated issue list for freshness. */
|
|
29
|
+
export { runVetList } from './vet-list.js';
|
|
28
30
|
/** Add a PR to tracking state. */
|
|
29
31
|
export { runTrack } from './track.js';
|
|
30
32
|
/** Remove a PR from tracking state. */
|
|
@@ -71,7 +73,7 @@ export { runDetectFormatters } from './detect-formatters.js';
|
|
|
71
73
|
export { runLocalRepos } from './local-repos.js';
|
|
72
74
|
export type { ErrorCode } from '../formatters/json.js';
|
|
73
75
|
export type { DailyOutput, SearchOutput, StartupOutput, StatusOutput, TrackOutput } from '../formatters/json.js';
|
|
74
|
-
export type { VetOutput, CommentsOutput, PostOutput, ClaimOutput } from '../formatters/json.js';
|
|
76
|
+
export type { VetOutput, CommentsOutput, PostOutput, ClaimOutput, VetListOutput, VetListItemStatus, } from '../formatters/json.js';
|
|
75
77
|
export type { ConfigOutput, DetectFormattersOutput, ParseIssueListOutput, ParsedIssueItem, CheckIntegrationOutput, LocalReposOutput, } from '../formatters/json.js';
|
|
76
78
|
export type { ReadOutput } from './read.js';
|
|
77
79
|
export type { ShelveOutput, UnshelveOutput } from './shelve.js';
|
package/dist/commands/index.js
CHANGED
|
@@ -26,6 +26,8 @@ export { runStatus } from './status.js';
|
|
|
26
26
|
export { runSearch } from './search.js';
|
|
27
27
|
/** Vet a single GitHub issue for claimability (open, unassigned, no linked PRs, repo health). */
|
|
28
28
|
export { runVet } from './vet.js';
|
|
29
|
+
/** Re-vet all available issues in a curated issue list for freshness. */
|
|
30
|
+
export { runVetList } from './vet-list.js';
|
|
29
31
|
// ── PR Management ───────────────────────────────────────────────────────────
|
|
30
32
|
/** Add a PR to tracking state. */
|
|
31
33
|
export { runTrack } from './track.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge between oss-autopilot's AgentState and oss-scout's OssScout API.
|
|
3
|
+
* Maps state fields and creates scout instances for search/vet commands.
|
|
4
|
+
*/
|
|
5
|
+
import { type OssScout, type ScoutState } from '@oss-scout/core';
|
|
6
|
+
/**
|
|
7
|
+
* Build a ScoutState from the current AgentState.
|
|
8
|
+
* Maps oss-autopilot's config and state fields to oss-scout's state format.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildScoutState(): ScoutState;
|
|
11
|
+
/**
|
|
12
|
+
* Create an OssScout instance backed by the current AgentState.
|
|
13
|
+
* Uses 'provided' persistence so scout reads from oss-autopilot's state.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createAutopilotScout(): Promise<OssScout>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge between oss-autopilot's AgentState and oss-scout's OssScout API.
|
|
3
|
+
* Maps state fields and creates scout instances for search/vet commands.
|
|
4
|
+
*/
|
|
5
|
+
import { createScout } from '@oss-scout/core';
|
|
6
|
+
import { getStateManager, requireGitHubToken } from '../core/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Build a ScoutState from the current AgentState.
|
|
9
|
+
* Maps oss-autopilot's config and state fields to oss-scout's state format.
|
|
10
|
+
*/
|
|
11
|
+
export function buildScoutState() {
|
|
12
|
+
const state = getStateManager().getState();
|
|
13
|
+
const { config } = state;
|
|
14
|
+
return {
|
|
15
|
+
version: 1,
|
|
16
|
+
preferences: {
|
|
17
|
+
githubUsername: config.githubUsername,
|
|
18
|
+
languages: config.languages,
|
|
19
|
+
labels: config.labels,
|
|
20
|
+
scope: config.scope,
|
|
21
|
+
excludeRepos: config.excludeRepos,
|
|
22
|
+
excludeOrgs: config.excludeOrgs ?? [],
|
|
23
|
+
aiPolicyBlocklist: config.aiPolicyBlocklist,
|
|
24
|
+
projectCategories: config.projectCategories ?? [],
|
|
25
|
+
minStars: config.minStars,
|
|
26
|
+
maxIssueAgeDays: config.maxIssueAgeDays,
|
|
27
|
+
includeDocIssues: config.includeDocIssues,
|
|
28
|
+
minRepoScoreThreshold: config.minRepoScoreThreshold,
|
|
29
|
+
interPhaseDelayMs: 30000,
|
|
30
|
+
broadPhaseDelayMs: 90000,
|
|
31
|
+
skipBroadWhenSufficientResults: 15,
|
|
32
|
+
persistence: config.persistence,
|
|
33
|
+
},
|
|
34
|
+
repoScores: state.repoScores,
|
|
35
|
+
starredRepos: config.starredRepos,
|
|
36
|
+
starredReposLastFetched: config.starredReposLastFetched,
|
|
37
|
+
mergedPRs: (state.mergedPRs ?? []).map((pr) => ({
|
|
38
|
+
url: pr.url,
|
|
39
|
+
title: pr.title,
|
|
40
|
+
mergedAt: pr.mergedAt,
|
|
41
|
+
})),
|
|
42
|
+
closedPRs: (state.closedPRs ?? []).map((pr) => ({
|
|
43
|
+
url: pr.url,
|
|
44
|
+
title: pr.title,
|
|
45
|
+
closedAt: pr.closedAt,
|
|
46
|
+
})),
|
|
47
|
+
savedResults: [],
|
|
48
|
+
skippedIssues: [],
|
|
49
|
+
lastRunAt: state.lastRunAt,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create an OssScout instance backed by the current AgentState.
|
|
54
|
+
* Uses 'provided' persistence so scout reads from oss-autopilot's state.
|
|
55
|
+
*/
|
|
56
|
+
export async function createAutopilotScout() {
|
|
57
|
+
const token = requireGitHubToken();
|
|
58
|
+
return createScout({
|
|
59
|
+
githubToken: token,
|
|
60
|
+
persistence: 'provided',
|
|
61
|
+
initialState: buildScoutState(),
|
|
62
|
+
});
|
|
63
|
+
}
|
package/dist/commands/search.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Search command
|
|
3
|
-
* Searches for new issues to work on
|
|
3
|
+
* Searches for new issues to work on via @oss-scout/core
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { createAutopilotScout } from './scout-bridge.js';
|
|
6
|
+
import { getStateManager } from '../core/index.js';
|
|
6
7
|
/**
|
|
7
8
|
* Search GitHub for contributable issues using multi-phase discovery.
|
|
8
9
|
*
|
|
@@ -22,15 +23,11 @@ import { IssueDiscovery, requireGitHubToken, getStateManager, DEFAULT_CONFIG } f
|
|
|
22
23
|
* ```
|
|
23
24
|
*/
|
|
24
25
|
export async function runSearch(options) {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const candidates = await discovery.searchIssues({ maxResults: options.maxResults });
|
|
26
|
+
const scout = await createAutopilotScout();
|
|
27
|
+
const result = await scout.search({ maxResults: options.maxResults });
|
|
28
28
|
const stateManager = getStateManager();
|
|
29
|
-
const { config } = stateManager.getState();
|
|
30
|
-
const excludedRepos = config.excludeRepos || [];
|
|
31
|
-
const aiPolicyBlocklist = config.aiPolicyBlocklist ?? DEFAULT_CONFIG.aiPolicyBlocklist ?? [];
|
|
32
29
|
const searchOutput = {
|
|
33
|
-
candidates: candidates.map((c) => {
|
|
30
|
+
candidates: result.candidates.map((c) => {
|
|
34
31
|
const repoScoreRecord = stateManager.getRepoScore(c.issue.repo);
|
|
35
32
|
return {
|
|
36
33
|
issue: {
|
|
@@ -57,11 +54,11 @@ export async function runSearch(options) {
|
|
|
57
54
|
: undefined,
|
|
58
55
|
};
|
|
59
56
|
}),
|
|
60
|
-
excludedRepos,
|
|
61
|
-
aiPolicyBlocklist,
|
|
57
|
+
excludedRepos: result.excludedRepos,
|
|
58
|
+
aiPolicyBlocklist: result.aiPolicyBlocklist,
|
|
62
59
|
};
|
|
63
|
-
if (
|
|
64
|
-
searchOutput.rateLimitWarning =
|
|
60
|
+
if (result.rateLimitWarning) {
|
|
61
|
+
searchOutput.rateLimitWarning = result.rateLimitWarning;
|
|
65
62
|
}
|
|
66
63
|
return searchOutput;
|
|
67
64
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vet-list command (#764)
|
|
3
|
-
* Re-vets all available issues in a curated issue list file.
|
|
3
|
+
* Re-vets all available issues in a curated issue list file via @oss-scout/core.
|
|
4
4
|
*/
|
|
5
5
|
import { type VetListOutput, type VetOutput, type VetListItemStatus } from '../formatters/json.js';
|
|
6
6
|
interface VetListOptions {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vet-list command (#764)
|
|
3
|
-
* Re-vets all available issues in a curated issue list file.
|
|
3
|
+
* Re-vets all available issues in a curated issue list file via @oss-scout/core.
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from 'fs';
|
|
6
|
-
import {
|
|
6
|
+
import { createAutopilotScout } from './scout-bridge.js';
|
|
7
7
|
import { runParseList, pruneIssueList } from './parse-list.js';
|
|
8
8
|
import { detectIssueList } from './startup.js';
|
|
9
9
|
/**
|
|
@@ -34,7 +34,6 @@ export function classifyListStatus(vetResult) {
|
|
|
34
34
|
* @returns Consolidated vetting results with list status for each issue
|
|
35
35
|
*/
|
|
36
36
|
export async function runVetList(options = {}) {
|
|
37
|
-
const token = requireGitHubToken();
|
|
38
37
|
const concurrency = options.concurrency ?? 5;
|
|
39
38
|
// 1. Find and parse the issue list
|
|
40
39
|
let issueListPath = options.issueListPath;
|
|
@@ -53,7 +52,7 @@ export async function runVetList(options = {}) {
|
|
|
53
52
|
};
|
|
54
53
|
}
|
|
55
54
|
// 2. Vet each available issue in parallel with concurrency limit
|
|
56
|
-
const
|
|
55
|
+
const scout = await createAutopilotScout();
|
|
57
56
|
const results = [];
|
|
58
57
|
// Simple concurrency limiter
|
|
59
58
|
const items = parsed.available;
|
|
@@ -62,7 +61,7 @@ export async function runVetList(options = {}) {
|
|
|
62
61
|
while (index < items.length) {
|
|
63
62
|
const item = items[index++];
|
|
64
63
|
try {
|
|
65
|
-
const candidate = await
|
|
64
|
+
const candidate = await scout.vetIssue(item.url);
|
|
66
65
|
const vetResult = {
|
|
67
66
|
issue: {
|
|
68
67
|
repo: candidate.issue.repo,
|
package/dist/commands/vet.d.ts
CHANGED
package/dist/commands/vet.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vet command
|
|
3
|
-
* Vets a specific issue before working on it
|
|
3
|
+
* Vets a specific issue before working on it via @oss-scout/core
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { createAutopilotScout } from './scout-bridge.js';
|
|
6
6
|
import { ISSUE_URL_PATTERN, validateGitHubUrl, validateUrl } from './validation.js';
|
|
7
7
|
/**
|
|
8
8
|
* Vet a specific GitHub issue for claimability and project health.
|
|
@@ -15,9 +15,8 @@ import { ISSUE_URL_PATTERN, validateGitHubUrl, validateUrl } from './validation.
|
|
|
15
15
|
export async function runVet(options) {
|
|
16
16
|
validateUrl(options.issueUrl);
|
|
17
17
|
validateGitHubUrl(options.issueUrl, ISSUE_URL_PATTERN, 'issue');
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const candidate = await discovery.vetIssue(options.issueUrl);
|
|
18
|
+
const scout = await createAutopilotScout();
|
|
19
|
+
const candidate = await scout.vetIssue(options.issueUrl);
|
|
21
20
|
return {
|
|
22
21
|
issue: {
|
|
23
22
|
repo: candidate.issue.repo,
|
package/dist/core/index.d.ts
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
export { StateManager, getStateManager, getStateManagerAsync, resetStateManager, type Stats } from './state.js';
|
|
6
6
|
export { GistStateStore } from './gist-state-store.js';
|
|
7
7
|
export { PRMonitor, type PRCheckFailure, type FetchPRsResult, computeDisplayLabel, classifyCICheck, classifyFailingChecks, } from './pr-monitor.js';
|
|
8
|
-
export { IssueDiscovery } from './issue-discovery.js';
|
|
9
|
-
export { isDocOnlyIssue, applyPerRepoCap, DOC_ONLY_LABELS } from './issue-filtering.js';
|
|
10
8
|
export { IssueConversationMonitor } from './issue-conversation.js';
|
|
11
9
|
export { isBotAuthor, isAcknowledgmentComment } from './comment-utils.js';
|
|
12
10
|
export { getOctokit, checkRateLimit, type RateLimitInfo } from './github.js';
|
package/dist/core/index.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
export { StateManager, getStateManager, getStateManagerAsync, resetStateManager } from './state.js';
|
|
6
6
|
export { GistStateStore } from './gist-state-store.js';
|
|
7
7
|
export { PRMonitor, computeDisplayLabel, classifyCICheck, classifyFailingChecks, } from './pr-monitor.js';
|
|
8
|
-
|
|
9
|
-
export { isDocOnlyIssue, applyPerRepoCap, DOC_ONLY_LABELS } from './issue-filtering.js';
|
|
8
|
+
// Search/vetting now delegated to @oss-scout/core via commands/scout-bridge.ts
|
|
10
9
|
export { IssueConversationMonitor } from './issue-conversation.js';
|
|
11
10
|
export { isBotAuthor, isAcknowledgmentComment } from './comment-utils.js';
|
|
12
11
|
export { getOctokit, checkRateLimit } from './github.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oss-autopilot/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.1",
|
|
4
4
|
"description": "CLI and core library for managing open source contributions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@octokit/plugin-throttling": "^11.0.3",
|
|
52
52
|
"@octokit/rest": "^22.0.1",
|
|
53
|
+
"@oss-scout/core": "^0.4.0",
|
|
53
54
|
"commander": "^14.0.3",
|
|
54
55
|
"zod": "^4.3.6"
|
|
55
56
|
},
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Category Mapping — static mappings from project categories to GitHub topics and organizations.
|
|
3
|
-
*
|
|
4
|
-
* Used by issue discovery to prioritize repos matching user's category preferences.
|
|
5
|
-
*/
|
|
6
|
-
import type { ProjectCategory } from './types.js';
|
|
7
|
-
/** GitHub topics associated with each project category, used for `topic:` search queries. */
|
|
8
|
-
export declare const CATEGORY_TOPICS: Record<ProjectCategory, string[]>;
|
|
9
|
-
/** Well-known GitHub organizations associated with each project category. */
|
|
10
|
-
export declare const CATEGORY_ORGS: Record<ProjectCategory, string[]>;
|
|
11
|
-
/**
|
|
12
|
-
* Check if a repo belongs to any of the given categories based on its owner matching a category org.
|
|
13
|
-
* Comparison is case-insensitive.
|
|
14
|
-
*/
|
|
15
|
-
export declare function repoBelongsToCategory(repoFullName: string, categories: ProjectCategory[]): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Get deduplicated GitHub topics for the given categories, for use in `topic:` search queries.
|
|
18
|
-
*/
|
|
19
|
-
export declare function getTopicsForCategories(categories: ProjectCategory[]): string[];
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Category Mapping — static mappings from project categories to GitHub topics and organizations.
|
|
3
|
-
*
|
|
4
|
-
* Used by issue discovery to prioritize repos matching user's category preferences.
|
|
5
|
-
*/
|
|
6
|
-
/** GitHub topics associated with each project category, used for `topic:` search queries. */
|
|
7
|
-
export const CATEGORY_TOPICS = {
|
|
8
|
-
nonprofit: ['nonprofit', 'social-good', 'humanitarian', 'charity', 'social-impact', 'civic-tech'],
|
|
9
|
-
devtools: ['developer-tools', 'devtools', 'cli', 'sdk', 'linter', 'formatter', 'build-tool'],
|
|
10
|
-
infrastructure: ['infrastructure', 'cloud', 'kubernetes', 'docker', 'devops', 'monitoring', 'observability'],
|
|
11
|
-
'web-frameworks': ['web-framework', 'frontend', 'backend', 'fullstack', 'nextjs', 'react', 'vue'],
|
|
12
|
-
'data-ml': ['machine-learning', 'data-science', 'deep-learning', 'nlp', 'data-pipeline', 'analytics'],
|
|
13
|
-
education: ['education', 'learning', 'tutorial', 'courseware', 'edtech', 'teaching'],
|
|
14
|
-
};
|
|
15
|
-
/** Well-known GitHub organizations associated with each project category. */
|
|
16
|
-
export const CATEGORY_ORGS = {
|
|
17
|
-
nonprofit: ['code-for-america', 'opengovfoundation', 'ushahidi', 'hotosm', 'openfn', 'democracyearth'],
|
|
18
|
-
devtools: ['eslint', 'prettier', 'vitejs', 'biomejs', 'oxc-project', 'ast-grep', 'turbot'],
|
|
19
|
-
infrastructure: ['kubernetes', 'hashicorp', 'grafana', 'prometheus', 'open-telemetry', 'envoyproxy', 'cncf'],
|
|
20
|
-
'web-frameworks': ['vercel', 'remix-run', 'sveltejs', 'nuxt', 'astro', 'redwoodjs', 'blitz-js'],
|
|
21
|
-
'data-ml': ['huggingface', 'mlflow', 'apache', 'dbt-labs', 'dagster-io', 'prefecthq', 'langchain-ai'],
|
|
22
|
-
education: ['freeCodeCamp', 'TheOdinProject', 'exercism', 'codecademy', 'oppia', 'Khan'],
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* Check if a repo belongs to any of the given categories based on its owner matching a category org.
|
|
26
|
-
* Comparison is case-insensitive.
|
|
27
|
-
*/
|
|
28
|
-
export function repoBelongsToCategory(repoFullName, categories) {
|
|
29
|
-
if (categories.length === 0)
|
|
30
|
-
return false;
|
|
31
|
-
const owner = repoFullName.split('/')[0]?.toLowerCase();
|
|
32
|
-
if (!owner)
|
|
33
|
-
return false;
|
|
34
|
-
for (const category of categories) {
|
|
35
|
-
const orgs = CATEGORY_ORGS[category];
|
|
36
|
-
if (!orgs)
|
|
37
|
-
continue; // Guard against invalid categories from hand-edited state.json
|
|
38
|
-
if (orgs.some((org) => org.toLowerCase() === owner)) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Get deduplicated GitHub topics for the given categories, for use in `topic:` search queries.
|
|
46
|
-
*/
|
|
47
|
-
export function getTopicsForCategories(categories) {
|
|
48
|
-
const topics = new Set();
|
|
49
|
-
for (const category of categories) {
|
|
50
|
-
const categoryTopics = CATEGORY_TOPICS[category];
|
|
51
|
-
if (!categoryTopics)
|
|
52
|
-
continue; // Guard against invalid categories from hand-edited state.json
|
|
53
|
-
for (const topic of categoryTopics) {
|
|
54
|
-
topics.add(topic);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return [...topics];
|
|
58
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Issue Discovery — orchestrates multi-phase issue search across GitHub.
|
|
3
|
-
*
|
|
4
|
-
* Delegates filtering, scoring, vetting, and search infrastructure to focused modules (#356, #621):
|
|
5
|
-
* - issue-filtering.ts — spam detection, doc-only filtering, per-repo caps
|
|
6
|
-
* - issue-scoring.ts — viability scores, repo quality bonuses
|
|
7
|
-
* - issue-vetting.ts — vetting orchestration, recommendation + viability scoring
|
|
8
|
-
* - issue-eligibility.ts — PR existence, claim detection, requirements analysis
|
|
9
|
-
* - repo-health.ts — project health checks, contribution guidelines
|
|
10
|
-
* - search-phases.ts — search helpers, caching, batched repo search
|
|
11
|
-
*/
|
|
12
|
-
import { type IssueCandidate } from './types.js';
|
|
13
|
-
/**
|
|
14
|
-
* Multi-phase issue discovery engine that searches GitHub for contributable issues.
|
|
15
|
-
*
|
|
16
|
-
* Search phases (in priority order):
|
|
17
|
-
* 0. Repos where user has merged PRs (highest merge probability)
|
|
18
|
-
* 0.5. Preferred organizations
|
|
19
|
-
* 1. Starred repos
|
|
20
|
-
* 2. General label-filtered search
|
|
21
|
-
* 3. Actively maintained repos
|
|
22
|
-
*
|
|
23
|
-
* Each candidate is vetted for claimability and scored 0-100 for viability.
|
|
24
|
-
*/
|
|
25
|
-
export declare class IssueDiscovery {
|
|
26
|
-
private octokit;
|
|
27
|
-
private stateManager;
|
|
28
|
-
private githubToken;
|
|
29
|
-
private vetter;
|
|
30
|
-
/** Set after searchIssues() runs if rate limits affected the search (low pre-flight quota or mid-search rate limit hits). */
|
|
31
|
-
rateLimitWarning: string | null;
|
|
32
|
-
/** @param githubToken - GitHub personal access token or token from `gh auth token` */
|
|
33
|
-
constructor(githubToken: string);
|
|
34
|
-
/**
|
|
35
|
-
* Fetch the authenticated user's starred repositories from GitHub.
|
|
36
|
-
* Updates the state manager with the list and timestamp.
|
|
37
|
-
* @returns Array of starred repo names in "owner/repo" format
|
|
38
|
-
*/
|
|
39
|
-
fetchStarredRepos(): Promise<string[]>;
|
|
40
|
-
/**
|
|
41
|
-
* Get starred repos, fetching from GitHub if cache is stale.
|
|
42
|
-
* @returns Array of starred repo names in "owner/repo" format
|
|
43
|
-
*/
|
|
44
|
-
getStarredReposWithRefresh(): Promise<string[]>;
|
|
45
|
-
/**
|
|
46
|
-
* Search for issues matching our criteria.
|
|
47
|
-
* Searches in priority order: merged-PR repos first (no label filter), then preferred
|
|
48
|
-
* organizations, then starred repos, then general search, then actively maintained repos.
|
|
49
|
-
* Filters out issues from low-scoring and excluded repos.
|
|
50
|
-
*
|
|
51
|
-
* @param options - Search configuration
|
|
52
|
-
* @param options.languages - Programming languages to filter by
|
|
53
|
-
* @param options.labels - Issue labels to search for
|
|
54
|
-
* @param options.maxResults - Maximum candidates to return (default: 10)
|
|
55
|
-
* @returns Scored and sorted issue candidates
|
|
56
|
-
* @throws {ValidationError} If no candidates found and no rate limits prevented the search
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* import { IssueDiscovery, requireGitHubToken } from '@oss-autopilot/core';
|
|
61
|
-
*
|
|
62
|
-
* const discovery = new IssueDiscovery(requireGitHubToken());
|
|
63
|
-
* const candidates = await discovery.searchIssues({ maxResults: 5 });
|
|
64
|
-
* for (const c of candidates) {
|
|
65
|
-
* console.log(`${c.issue.repo}#${c.issue.number}: ${c.viabilityScore}/100`);
|
|
66
|
-
* }
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
searchIssues(options?: {
|
|
70
|
-
languages?: string[];
|
|
71
|
-
labels?: string[];
|
|
72
|
-
maxResults?: number;
|
|
73
|
-
}): Promise<IssueCandidate[]>;
|
|
74
|
-
/**
|
|
75
|
-
* Vet a specific issue for claimability and project health.
|
|
76
|
-
* @param issueUrl - Full GitHub issue URL
|
|
77
|
-
* @returns The vetted issue candidate with recommendation and scores
|
|
78
|
-
* @throws {ValidationError} If the URL is invalid or the issue cannot be fetched
|
|
79
|
-
*/
|
|
80
|
-
vetIssue(issueUrl: string): Promise<IssueCandidate>;
|
|
81
|
-
/**
|
|
82
|
-
* Save search results to ~/.oss-autopilot/found-issues.md.
|
|
83
|
-
* Results are sorted by viability score (highest first).
|
|
84
|
-
* @param candidates - Issue candidates to save
|
|
85
|
-
* @returns Absolute path to the written file
|
|
86
|
-
*/
|
|
87
|
-
saveSearchResults(candidates: IssueCandidate[]): string;
|
|
88
|
-
/**
|
|
89
|
-
* Format issue candidate as a markdown display string.
|
|
90
|
-
* @param candidate - The issue candidate to format
|
|
91
|
-
* @returns Multi-line markdown string with vetting details
|
|
92
|
-
*/
|
|
93
|
-
formatCandidate(candidate: IssueCandidate): string;
|
|
94
|
-
}
|