@oss-scout/core 0.1.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 +114 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +341 -0
- package/dist/commands/config.d.ts +22 -0
- package/dist/commands/config.js +169 -0
- package/dist/commands/results.d.ts +8 -0
- package/dist/commands/results.js +13 -0
- package/dist/commands/search.d.ts +39 -0
- package/dist/commands/search.js +50 -0
- package/dist/commands/setup.d.ts +17 -0
- package/dist/commands/setup.js +104 -0
- package/dist/commands/validation.d.ts +6 -0
- package/dist/commands/validation.js +17 -0
- package/dist/commands/vet-list.d.ts +9 -0
- package/dist/commands/vet-list.js +16 -0
- package/dist/commands/vet.d.ts +25 -0
- package/dist/commands/vet.js +29 -0
- package/dist/core/bootstrap.d.ts +14 -0
- package/dist/core/bootstrap.js +122 -0
- package/dist/core/category-mapping.d.ts +19 -0
- package/dist/core/category-mapping.js +58 -0
- package/dist/core/concurrency.d.ts +6 -0
- package/dist/core/concurrency.js +25 -0
- package/dist/core/errors.d.ts +22 -0
- package/dist/core/errors.js +69 -0
- package/dist/core/gist-state-store.d.ts +96 -0
- package/dist/core/gist-state-store.js +302 -0
- package/dist/core/github.d.ts +16 -0
- package/dist/core/github.js +58 -0
- package/dist/core/http-cache.d.ts +108 -0
- package/dist/core/http-cache.js +314 -0
- package/dist/core/issue-discovery.d.ts +93 -0
- package/dist/core/issue-discovery.js +475 -0
- package/dist/core/issue-eligibility.d.ts +33 -0
- package/dist/core/issue-eligibility.js +151 -0
- package/dist/core/issue-filtering.d.ts +51 -0
- package/dist/core/issue-filtering.js +103 -0
- package/dist/core/issue-scoring.d.ts +43 -0
- package/dist/core/issue-scoring.js +97 -0
- package/dist/core/issue-vetting.d.ts +44 -0
- package/dist/core/issue-vetting.js +270 -0
- package/dist/core/local-state.d.ts +16 -0
- package/dist/core/local-state.js +56 -0
- package/dist/core/logger.d.ts +11 -0
- package/dist/core/logger.js +25 -0
- package/dist/core/pagination.d.ts +7 -0
- package/dist/core/pagination.js +16 -0
- package/dist/core/repo-health.d.ts +19 -0
- package/dist/core/repo-health.js +179 -0
- package/dist/core/schemas.d.ts +315 -0
- package/dist/core/schemas.js +137 -0
- package/dist/core/search-budget.d.ts +62 -0
- package/dist/core/search-budget.js +129 -0
- package/dist/core/search-phases.d.ts +69 -0
- package/dist/core/search-phases.js +238 -0
- package/dist/core/types.d.ts +124 -0
- package/dist/core/types.js +9 -0
- package/dist/core/utils.d.ts +18 -0
- package/dist/core/utils.js +106 -0
- package/dist/formatters/json.d.ts +6 -0
- package/dist/formatters/json.js +20 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +25 -0
- package/dist/scout.d.ts +125 -0
- package/dist/scout.js +391 -0
- package/package.json +70 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for oss-scout — ephemeral types that are never persisted.
|
|
3
|
+
*/
|
|
4
|
+
import type { RepoSignals, TrackedIssue, IssueVettingResult, IssueScope, ScoutState, SearchStrategy } from './schemas.js';
|
|
5
|
+
export type { ProjectCategory, IssueScope, RepoSignals, RepoScore, StoredMergedPR, StoredClosedPR, ContributionGuidelines, IssueVettingResult, TrackedIssue, ScoutPreferences, SavedCandidate, ScoutState, SearchStrategy, } from './schemas.js';
|
|
6
|
+
/** Health snapshot of a GitHub repository. */
|
|
7
|
+
export interface ProjectHealth {
|
|
8
|
+
repo: string;
|
|
9
|
+
lastCommitAt: string;
|
|
10
|
+
daysSinceLastCommit: number;
|
|
11
|
+
openIssuesCount: number;
|
|
12
|
+
avgIssueResponseDays: number;
|
|
13
|
+
ciStatus: 'passing' | 'failing' | 'unknown';
|
|
14
|
+
isActive: boolean;
|
|
15
|
+
stargazersCount?: number;
|
|
16
|
+
forksCount?: number;
|
|
17
|
+
language?: string | null;
|
|
18
|
+
checkFailed?: boolean;
|
|
19
|
+
failureReason?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Priority tier for issue search results. */
|
|
22
|
+
export type SearchPriority = 'merged_pr' | 'preferred_org' | 'starred' | 'normal';
|
|
23
|
+
/** A fully vetted issue candidate with scoring. */
|
|
24
|
+
export interface IssueCandidate {
|
|
25
|
+
issue: TrackedIssue;
|
|
26
|
+
vettingResult: IssueVettingResult;
|
|
27
|
+
projectHealth: ProjectHealth;
|
|
28
|
+
recommendation: 'approve' | 'skip' | 'needs_review';
|
|
29
|
+
reasonsToSkip: string[];
|
|
30
|
+
reasonsToApprove: string[];
|
|
31
|
+
viabilityScore: number;
|
|
32
|
+
searchPriority: SearchPriority;
|
|
33
|
+
}
|
|
34
|
+
/** Subset of RepoScore fields that callers may update. */
|
|
35
|
+
export interface RepoScoreUpdate {
|
|
36
|
+
mergedPRCount?: number;
|
|
37
|
+
closedWithoutMergeCount?: number;
|
|
38
|
+
avgResponseDays?: number | null;
|
|
39
|
+
lastMergedAt?: string;
|
|
40
|
+
signals?: Partial<RepoSignals>;
|
|
41
|
+
stargazersCount?: number;
|
|
42
|
+
language?: string | null;
|
|
43
|
+
}
|
|
44
|
+
/** Result of a check (e.g., no existing PR, not claimed). */
|
|
45
|
+
export interface CheckResult {
|
|
46
|
+
passed: boolean;
|
|
47
|
+
inconclusive?: boolean;
|
|
48
|
+
reason?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare const SCOPE_LABELS: Record<IssueScope, string[]>;
|
|
51
|
+
/** Options for batch vetting saved results. */
|
|
52
|
+
export interface VetListOptions {
|
|
53
|
+
concurrency?: number;
|
|
54
|
+
prune?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** A single entry in the vet-list result. */
|
|
57
|
+
export interface VetListEntry {
|
|
58
|
+
issueUrl: string;
|
|
59
|
+
repo: string;
|
|
60
|
+
number: number;
|
|
61
|
+
title: string;
|
|
62
|
+
status: 'still_available' | 'claimed' | 'closed' | 'has_pr' | 'error';
|
|
63
|
+
recommendation?: 'approve' | 'skip' | 'needs_review';
|
|
64
|
+
viabilityScore?: number;
|
|
65
|
+
errorMessage?: string;
|
|
66
|
+
}
|
|
67
|
+
/** Summary counts for a vet-list run. */
|
|
68
|
+
export interface VetListSummary {
|
|
69
|
+
total: number;
|
|
70
|
+
stillAvailable: number;
|
|
71
|
+
claimed: number;
|
|
72
|
+
closed: number;
|
|
73
|
+
hasPR: number;
|
|
74
|
+
errors: number;
|
|
75
|
+
}
|
|
76
|
+
/** Result of a batch vet-list operation. */
|
|
77
|
+
export interface VetListResult {
|
|
78
|
+
results: VetListEntry[];
|
|
79
|
+
summary: VetListSummary;
|
|
80
|
+
prunedCount?: number;
|
|
81
|
+
}
|
|
82
|
+
/** Configuration for creating an OssScout instance. */
|
|
83
|
+
export type ScoutConfig = {
|
|
84
|
+
/** GitHub token with `repo` read scope. Add `gist` scope for persistence. */
|
|
85
|
+
githubToken: string;
|
|
86
|
+
/** Use gist-backed persistence (default for standalone CLI). */
|
|
87
|
+
persistence?: 'gist';
|
|
88
|
+
/** Gist ID override. Skips gist discovery/creation if provided. */
|
|
89
|
+
gistId?: string;
|
|
90
|
+
} | {
|
|
91
|
+
/** GitHub token with `repo` read scope. */
|
|
92
|
+
githubToken: string;
|
|
93
|
+
/** Caller provides state directly. */
|
|
94
|
+
persistence: 'provided';
|
|
95
|
+
/** Pre-loaded state. Required when persistence is 'provided'. */
|
|
96
|
+
initialState: ScoutState;
|
|
97
|
+
};
|
|
98
|
+
/** Options for the search method. */
|
|
99
|
+
export interface SearchOptions {
|
|
100
|
+
maxResults?: number;
|
|
101
|
+
strategies?: SearchStrategy[];
|
|
102
|
+
}
|
|
103
|
+
/** Result of a search operation. */
|
|
104
|
+
export interface SearchResult {
|
|
105
|
+
candidates: IssueCandidate[];
|
|
106
|
+
excludedRepos: string[];
|
|
107
|
+
aiPolicyBlocklist: string[];
|
|
108
|
+
rateLimitWarning?: string;
|
|
109
|
+
strategiesUsed: SearchStrategy[];
|
|
110
|
+
}
|
|
111
|
+
/** Record of a merged PR for state contribution. */
|
|
112
|
+
export interface MergedPRRecord {
|
|
113
|
+
url: string;
|
|
114
|
+
title: string;
|
|
115
|
+
mergedAt: string;
|
|
116
|
+
repo: string;
|
|
117
|
+
}
|
|
118
|
+
/** Record of a closed PR for state contribution. */
|
|
119
|
+
export interface ClosedPRRecord {
|
|
120
|
+
url: string;
|
|
121
|
+
title: string;
|
|
122
|
+
closedAt: string;
|
|
123
|
+
repo: string;
|
|
124
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for oss-scout — ephemeral types that are never persisted.
|
|
3
|
+
*/
|
|
4
|
+
// ── Const arrays and mappings ───────────────────────────────────────
|
|
5
|
+
export const SCOPE_LABELS = {
|
|
6
|
+
beginner: ['good first issue', 'help wanted', 'easy', 'up-for-grabs', 'first-timers-only', 'beginner'],
|
|
7
|
+
intermediate: ['enhancement', 'feature', 'feature-request', 'contributions welcome'],
|
|
8
|
+
advanced: ['proposal', 'RFC', 'accepted', 'design'],
|
|
9
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility functions for oss-scout.
|
|
3
|
+
*/
|
|
4
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
5
|
+
export declare function getDataDir(): string;
|
|
6
|
+
export declare function getCacheDir(): string;
|
|
7
|
+
interface ParsedGitHubUrl {
|
|
8
|
+
owner: string;
|
|
9
|
+
repo: string;
|
|
10
|
+
number: number;
|
|
11
|
+
type: 'pull' | 'issues';
|
|
12
|
+
}
|
|
13
|
+
export declare function parseGitHubUrl(url: string): ParsedGitHubUrl | null;
|
|
14
|
+
export declare function daysBetween(from: Date, to?: Date): number;
|
|
15
|
+
export declare function getCLIVersion(): string;
|
|
16
|
+
export declare function getGitHubToken(): string | null;
|
|
17
|
+
export declare function requireGitHubToken(): string;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility functions for oss-scout.
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as os from 'os';
|
|
7
|
+
import { execFileSync } from 'child_process';
|
|
8
|
+
import { ConfigurationError, errorMessage } from './errors.js';
|
|
9
|
+
import { debug } from './logger.js';
|
|
10
|
+
export function sleep(ms) {
|
|
11
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
+
}
|
|
13
|
+
const MODULE = 'utils';
|
|
14
|
+
let cachedGitHubToken = null;
|
|
15
|
+
let tokenFetchAttempted = false;
|
|
16
|
+
export function getDataDir() {
|
|
17
|
+
const dir = path.join(os.homedir(), '.oss-scout');
|
|
18
|
+
if (!fs.existsSync(dir)) {
|
|
19
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
20
|
+
}
|
|
21
|
+
return dir;
|
|
22
|
+
}
|
|
23
|
+
export function getCacheDir() {
|
|
24
|
+
const dir = path.join(getDataDir(), 'cache');
|
|
25
|
+
if (!fs.existsSync(dir)) {
|
|
26
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
27
|
+
}
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
30
|
+
const OWNER_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
31
|
+
const REPO_PATTERN = /^[a-zA-Z0-9_.-]+$/;
|
|
32
|
+
function isValidOwnerRepo(owner, repo) {
|
|
33
|
+
return OWNER_PATTERN.test(owner) && REPO_PATTERN.test(repo);
|
|
34
|
+
}
|
|
35
|
+
export function parseGitHubUrl(url) {
|
|
36
|
+
if (!url.startsWith('https://github.com/'))
|
|
37
|
+
return null;
|
|
38
|
+
const prMatch = url.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
|
|
39
|
+
if (prMatch) {
|
|
40
|
+
const owner = prMatch[1];
|
|
41
|
+
const repo = prMatch[2];
|
|
42
|
+
if (!isValidOwnerRepo(owner, repo))
|
|
43
|
+
return null;
|
|
44
|
+
return { owner, repo, number: parseInt(prMatch[3], 10), type: 'pull' };
|
|
45
|
+
}
|
|
46
|
+
const issueMatch = url.match(/github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/);
|
|
47
|
+
if (issueMatch) {
|
|
48
|
+
const owner = issueMatch[1];
|
|
49
|
+
const repo = issueMatch[2];
|
|
50
|
+
if (!isValidOwnerRepo(owner, repo))
|
|
51
|
+
return null;
|
|
52
|
+
return { owner, repo, number: parseInt(issueMatch[3], 10), type: 'issues' };
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
export function daysBetween(from, to = new Date()) {
|
|
57
|
+
return Math.max(0, Math.floor((to.getTime() - from.getTime()) / (1000 * 60 * 60 * 24)));
|
|
58
|
+
}
|
|
59
|
+
export function getCLIVersion() {
|
|
60
|
+
try {
|
|
61
|
+
const pkgPath = path.join(path.dirname(process.argv[1]), '..', 'package.json');
|
|
62
|
+
return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
debug(MODULE, `Could not read CLI version: ${errorMessage(err)}`);
|
|
66
|
+
return 'unknown';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export function getGitHubToken() {
|
|
70
|
+
if (cachedGitHubToken)
|
|
71
|
+
return cachedGitHubToken;
|
|
72
|
+
if (tokenFetchAttempted)
|
|
73
|
+
return null;
|
|
74
|
+
tokenFetchAttempted = true;
|
|
75
|
+
if (process.env.GITHUB_TOKEN) {
|
|
76
|
+
cachedGitHubToken = process.env.GITHUB_TOKEN;
|
|
77
|
+
return cachedGitHubToken;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const token = execFileSync('gh', ['auth', 'token'], {
|
|
81
|
+
encoding: 'utf-8',
|
|
82
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
83
|
+
timeout: 2000,
|
|
84
|
+
}).trim();
|
|
85
|
+
if (token && token.length > 0) {
|
|
86
|
+
cachedGitHubToken = token;
|
|
87
|
+
debug(MODULE, 'Using GitHub token from gh CLI');
|
|
88
|
+
return cachedGitHubToken;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
debug(MODULE, 'gh auth token failed', err);
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
export function requireGitHubToken() {
|
|
97
|
+
const token = getGitHubToken();
|
|
98
|
+
if (!token) {
|
|
99
|
+
throw new ConfigurationError('GitHub authentication required.\n\n' +
|
|
100
|
+
'Options:\n' +
|
|
101
|
+
' 1. Use gh CLI: gh auth login\n' +
|
|
102
|
+
' 2. Set GITHUB_TOKEN environment variable\n\n' +
|
|
103
|
+
'The gh CLI is recommended - install from https://cli.github.com');
|
|
104
|
+
}
|
|
105
|
+
return token;
|
|
106
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON output formatter for oss-scout CLI.
|
|
3
|
+
*/
|
|
4
|
+
export function formatJsonSuccess(data) {
|
|
5
|
+
const output = {
|
|
6
|
+
success: true,
|
|
7
|
+
data,
|
|
8
|
+
timestamp: new Date().toISOString(),
|
|
9
|
+
};
|
|
10
|
+
return JSON.stringify(output, null, 2);
|
|
11
|
+
}
|
|
12
|
+
export function formatJsonError(error, errorCode) {
|
|
13
|
+
const output = {
|
|
14
|
+
success: false,
|
|
15
|
+
error,
|
|
16
|
+
errorCode,
|
|
17
|
+
timestamp: new Date().toISOString(),
|
|
18
|
+
};
|
|
19
|
+
return JSON.stringify(output, null, 2);
|
|
20
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @oss-scout/core — Find open source issues personalized to your contribution history.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { createScout } from '@oss-scout/core';
|
|
7
|
+
*
|
|
8
|
+
* const scout = await createScout({ githubToken: 'ghp_...' });
|
|
9
|
+
* const results = await scout.search({ maxResults: 10 });
|
|
10
|
+
* for (const c of results.candidates) {
|
|
11
|
+
* console.log(`${c.issue.repo}#${c.issue.number}: ${c.viabilityScore}/100`);
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
export { createScout, OssScout } from './scout.js';
|
|
18
|
+
export type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectHealth, SearchPriority, CheckResult, VetListOptions, VetListResult, VetListEntry, VetListSummary, } from './core/types.js';
|
|
19
|
+
export type { ScoutState, ScoutPreferences, RepoScore, RepoSignals, IssueVettingResult, ContributionGuidelines, TrackedIssue, IssueScope, ProjectCategory, StoredMergedPR, StoredClosedPR, SearchStrategy, } from './core/schemas.js';
|
|
20
|
+
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from './core/schemas.js';
|
|
21
|
+
export { requireGitHubToken, getGitHubToken } from './core/utils.js';
|
|
22
|
+
export { IssueDiscovery } from './core/issue-discovery.js';
|
|
23
|
+
export { IssueVetter, type ScoutStateReader } from './core/issue-vetting.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @oss-scout/core — Find open source issues personalized to your contribution history.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { createScout } from '@oss-scout/core';
|
|
7
|
+
*
|
|
8
|
+
* const scout = await createScout({ githubToken: 'ghp_...' });
|
|
9
|
+
* const results = await scout.search({ maxResults: 10 });
|
|
10
|
+
* for (const c of results.candidates) {
|
|
11
|
+
* console.log(`${c.issue.repo}#${c.issue.number}: ${c.viabilityScore}/100`);
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
// Main API
|
|
18
|
+
export { createScout, OssScout } from './scout.js';
|
|
19
|
+
// Schemas (for consumers who need runtime validation)
|
|
20
|
+
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from './core/schemas.js';
|
|
21
|
+
// Utilities
|
|
22
|
+
export { requireGitHubToken, getGitHubToken } from './core/utils.js';
|
|
23
|
+
// Internal classes (for advanced use)
|
|
24
|
+
export { IssueDiscovery } from './core/issue-discovery.js';
|
|
25
|
+
export { IssueVetter } from './core/issue-vetting.js';
|
package/dist/scout.d.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OssScout — the public API for oss-scout.
|
|
3
|
+
*
|
|
4
|
+
* Provides personalized issue discovery, vetting, and scoring.
|
|
5
|
+
* Implements ScoutStateReader to bridge state with the search engine.
|
|
6
|
+
*/
|
|
7
|
+
import type { ScoutStateReader } from './core/issue-vetting.js';
|
|
8
|
+
import type { ScoutState, ScoutPreferences, RepoScore, SavedCandidate } from './core/schemas.js';
|
|
9
|
+
import type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectCategory, VetListOptions, VetListResult } from './core/types.js';
|
|
10
|
+
import { GistStateStore } from './core/gist-state-store.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create an OssScout instance.
|
|
13
|
+
*
|
|
14
|
+
* @param config - Configuration including GitHub token and persistence mode
|
|
15
|
+
* @returns A ready-to-use OssScout instance
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { createScout } from '@oss-scout/core';
|
|
20
|
+
*
|
|
21
|
+
* // Standalone with gist persistence
|
|
22
|
+
* const scout = await createScout({ githubToken: 'ghp_...', persistence: 'gist' });
|
|
23
|
+
*
|
|
24
|
+
* // As a library (host application provides state)
|
|
25
|
+
* const scout = await createScout({
|
|
26
|
+
* githubToken: 'ghp_...',
|
|
27
|
+
* persistence: 'provided',
|
|
28
|
+
* initialState: myState,
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function createScout(config: ScoutConfig): Promise<OssScout>;
|
|
33
|
+
/**
|
|
34
|
+
* Main oss-scout class. Provides search, vetting, and state management.
|
|
35
|
+
*
|
|
36
|
+
* Implements ScoutStateReader so the search engine can read state
|
|
37
|
+
* without knowing about the persistence layer.
|
|
38
|
+
*/
|
|
39
|
+
export declare class OssScout implements ScoutStateReader {
|
|
40
|
+
private githubToken;
|
|
41
|
+
private gistStore;
|
|
42
|
+
private state;
|
|
43
|
+
private dirty;
|
|
44
|
+
constructor(githubToken: string, initialState: ScoutState, gistStore?: GistStateStore | null);
|
|
45
|
+
/**
|
|
46
|
+
* Multi-strategy issue search. Returns scored, sorted candidates.
|
|
47
|
+
*/
|
|
48
|
+
search(options?: SearchOptions): Promise<SearchResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Vet a single issue URL for claimability.
|
|
51
|
+
*/
|
|
52
|
+
vetIssue(issueUrl: string): Promise<IssueCandidate>;
|
|
53
|
+
/**
|
|
54
|
+
* Re-vet all saved results with bounded concurrency.
|
|
55
|
+
* Classifies each as still_available, claimed, has_pr, closed, or error.
|
|
56
|
+
* Optionally prunes unavailable issues from saved results.
|
|
57
|
+
*/
|
|
58
|
+
vetList(options?: VetListOptions): Promise<VetListResult>;
|
|
59
|
+
private classifyVetResult;
|
|
60
|
+
getReposWithMergedPRs(): string[];
|
|
61
|
+
getStarredRepos(): string[];
|
|
62
|
+
getPreferredOrgs(): string[];
|
|
63
|
+
getProjectCategories(): ProjectCategory[];
|
|
64
|
+
getRepoScore(repo: string): number | null;
|
|
65
|
+
/** Get current preferences (read-only). */
|
|
66
|
+
getPreferences(): Readonly<ScoutPreferences>;
|
|
67
|
+
/** Get repo score record for a specific repository. */
|
|
68
|
+
getRepoScoreRecord(repo: string): Readonly<RepoScore> | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Record that a PR was merged in this repo.
|
|
71
|
+
* Updates the merged PRs list and recalculates the repo score.
|
|
72
|
+
*/
|
|
73
|
+
recordMergedPR(pr: MergedPRRecord): void;
|
|
74
|
+
/**
|
|
75
|
+
* Record that a PR was closed without merge.
|
|
76
|
+
*/
|
|
77
|
+
recordClosedPR(pr: ClosedPRRecord): void;
|
|
78
|
+
/**
|
|
79
|
+
* Update repo score with observed signals.
|
|
80
|
+
*/
|
|
81
|
+
updateRepoScore(repo: string, update: Partial<RepoScoreUpdate>): void;
|
|
82
|
+
/**
|
|
83
|
+
* Update user preferences.
|
|
84
|
+
*/
|
|
85
|
+
updatePreferences(updates: Partial<ScoutPreferences>): void;
|
|
86
|
+
/**
|
|
87
|
+
* Update starred repos cache.
|
|
88
|
+
*/
|
|
89
|
+
setStarredRepos(repos: string[]): void;
|
|
90
|
+
/**
|
|
91
|
+
* Save search candidates to state, deduplicating by URL.
|
|
92
|
+
* If a candidate already exists, updates score/recommendation/lastSeenAt
|
|
93
|
+
* but preserves firstSeenAt.
|
|
94
|
+
*/
|
|
95
|
+
saveResults(candidates: IssueCandidate[]): void;
|
|
96
|
+
/**
|
|
97
|
+
* Get all saved results.
|
|
98
|
+
*/
|
|
99
|
+
getSavedResults(): SavedCandidate[];
|
|
100
|
+
/**
|
|
101
|
+
* Clear all saved results.
|
|
102
|
+
*/
|
|
103
|
+
clearResults(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Check if state has uncommitted changes.
|
|
106
|
+
*/
|
|
107
|
+
isDirty(): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Push pending changes to the persistence layer.
|
|
110
|
+
* Pushes to gist if gist persistence is configured.
|
|
111
|
+
*/
|
|
112
|
+
checkpoint(): Promise<boolean>;
|
|
113
|
+
/**
|
|
114
|
+
* Get the full state snapshot for serialization or external consumption.
|
|
115
|
+
*/
|
|
116
|
+
getState(): Readonly<ScoutState>;
|
|
117
|
+
private extractRepoFromUrl;
|
|
118
|
+
private updateRepoScoreFromPRs;
|
|
119
|
+
/**
|
|
120
|
+
* Calculate repo score (1-10) from observed data.
|
|
121
|
+
* base 5, +1 per merged PR (max +3), -1 per closed-without-merge (max -3),
|
|
122
|
+
* +1 responsive, +1 active maintainers, -2 hostile comments, clamped 1-10
|
|
123
|
+
*/
|
|
124
|
+
private calculateScore;
|
|
125
|
+
}
|