@oss-scout/core 0.2.0 → 0.2.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 +42 -42
- package/dist/cli.js +110 -86
- package/dist/commands/config.d.ts +1 -1
- package/dist/commands/config.js +76 -72
- package/dist/commands/results.d.ts +1 -1
- package/dist/commands/results.js +1 -1
- package/dist/commands/search.d.ts +2 -2
- package/dist/commands/search.js +16 -6
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +27 -21
- package/dist/commands/validation.d.ts +1 -1
- package/dist/commands/validation.js +1 -1
- package/dist/commands/vet-list.d.ts +2 -2
- package/dist/commands/vet-list.js +12 -5
- package/dist/commands/vet.d.ts +3 -3
- package/dist/commands/vet.js +9 -5
- package/dist/core/bootstrap.d.ts +1 -1
- package/dist/core/bootstrap.js +20 -16
- package/dist/core/category-mapping.d.ts +1 -1
- package/dist/core/category-mapping.js +104 -13
- package/dist/core/errors.d.ts +8 -1
- package/dist/core/errors.js +31 -19
- package/dist/core/gist-state-store.d.ts +1 -1
- package/dist/core/gist-state-store.js +36 -27
- package/dist/core/github.d.ts +1 -1
- package/dist/core/github.js +5 -5
- package/dist/core/http-cache.js +26 -22
- package/dist/core/issue-discovery.d.ts +3 -3
- package/dist/core/issue-discovery.js +325 -277
- package/dist/core/issue-eligibility.d.ts +2 -2
- package/dist/core/issue-eligibility.js +26 -21
- package/dist/core/issue-filtering.js +23 -15
- package/dist/core/issue-scoring.js +1 -1
- package/dist/core/issue-vetting.d.ts +2 -2
- package/dist/core/issue-vetting.js +66 -53
- package/dist/core/local-state.d.ts +1 -1
- package/dist/core/local-state.js +16 -14
- package/dist/core/repo-health.d.ts +2 -2
- package/dist/core/repo-health.js +46 -35
- package/dist/core/schemas.d.ts +1 -1
- package/dist/core/schemas.js +40 -18
- package/dist/core/search-budget.js +3 -3
- package/dist/core/search-phases.d.ts +6 -6
- package/dist/core/search-phases.js +23 -19
- package/dist/core/types.d.ts +9 -9
- package/dist/core/types.js +15 -3
- package/dist/core/utils.d.ts +10 -1
- package/dist/core/utils.js +44 -25
- package/dist/formatters/json.d.ts +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +5 -5
- package/dist/scout.d.ts +4 -5
- package/dist/scout.js +72 -31
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JSON output formatter for oss-scout CLI.
|
|
3
3
|
*/
|
|
4
|
-
import type { ErrorCode } from
|
|
4
|
+
import type { ErrorCode } from "../core/errors.js";
|
|
5
5
|
export declare function formatJsonSuccess<T>(data: T): string;
|
|
6
6
|
export declare function formatJsonError(error: string, errorCode?: ErrorCode): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @packageDocumentation
|
|
16
16
|
*/
|
|
17
|
-
export { createScout, OssScout } from
|
|
18
|
-
export type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectHealth, SearchPriority, CheckResult, VetListOptions, VetListResult, VetListEntry, VetListSummary, } from
|
|
19
|
-
export type { ScoutState, ScoutPreferences, RepoScore, RepoSignals, IssueVettingResult, ContributionGuidelines, TrackedIssue, IssueScope, ProjectCategory, StoredMergedPR, StoredClosedPR, SearchStrategy, } from
|
|
20
|
-
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from
|
|
21
|
-
export { requireGitHubToken, getGitHubToken } from
|
|
22
|
-
export { IssueDiscovery } from
|
|
23
|
-
export { IssueVetter, type ScoutStateReader } from
|
|
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
CHANGED
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
* @packageDocumentation
|
|
16
16
|
*/
|
|
17
17
|
// Main API
|
|
18
|
-
export { createScout, OssScout } from
|
|
18
|
+
export { createScout, OssScout } from "./scout.js";
|
|
19
19
|
// Schemas (for consumers who need runtime validation)
|
|
20
|
-
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from
|
|
20
|
+
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from "./core/schemas.js";
|
|
21
21
|
// Utilities
|
|
22
|
-
export { requireGitHubToken, getGitHubToken } from
|
|
22
|
+
export { requireGitHubToken, getGitHubToken } from "./core/utils.js";
|
|
23
23
|
// Internal classes (for advanced use)
|
|
24
|
-
export { IssueDiscovery } from
|
|
25
|
-
export { IssueVetter } from
|
|
24
|
+
export { IssueDiscovery } from "./core/issue-discovery.js";
|
|
25
|
+
export { IssueVetter } from "./core/issue-vetting.js";
|
package/dist/scout.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Provides personalized issue discovery, vetting, and scoring.
|
|
5
5
|
* Implements ScoutStateReader to bridge state with the search engine.
|
|
6
6
|
*/
|
|
7
|
-
import type { ScoutStateReader } from
|
|
8
|
-
import type { ScoutState, ScoutPreferences, RepoScore, SavedCandidate } from
|
|
9
|
-
import type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectCategory, VetListOptions, VetListResult } from
|
|
10
|
-
import { GistStateStore } from
|
|
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
11
|
/**
|
|
12
12
|
* Create an OssScout instance.
|
|
13
13
|
*
|
|
@@ -114,7 +114,6 @@ export declare class OssScout implements ScoutStateReader {
|
|
|
114
114
|
* Get the full state snapshot for serialization or external consumption.
|
|
115
115
|
*/
|
|
116
116
|
getState(): Readonly<ScoutState>;
|
|
117
|
-
private extractRepoFromUrl;
|
|
118
117
|
private updateRepoScoreFromPRs;
|
|
119
118
|
/**
|
|
120
119
|
* Calculate repo score (1-10) from observed data.
|
package/dist/scout.js
CHANGED
|
@@ -4,12 +4,55 @@
|
|
|
4
4
|
* Provides personalized issue discovery, vetting, and scoring.
|
|
5
5
|
* Implements ScoutStateReader to bridge state with the search engine.
|
|
6
6
|
*/
|
|
7
|
-
import { IssueDiscovery } from
|
|
8
|
-
import { ScoutStateSchema } from
|
|
9
|
-
import { GistStateStore, mergeStates } from
|
|
10
|
-
import { getOctokit } from
|
|
11
|
-
import { loadLocalState } from
|
|
12
|
-
import { warn } from
|
|
7
|
+
import { IssueDiscovery } from "./core/issue-discovery.js";
|
|
8
|
+
import { ScoutStateSchema } from "./core/schemas.js";
|
|
9
|
+
import { GistStateStore, mergeStates } from "./core/gist-state-store.js";
|
|
10
|
+
import { getOctokit } from "./core/github.js";
|
|
11
|
+
import { loadLocalState } from "./core/local-state.js";
|
|
12
|
+
import { warn } from "./core/logger.js";
|
|
13
|
+
import { extractRepoFromUrl } from "./core/utils.js";
|
|
14
|
+
/** Wrap a real Octokit instance as GistOctokitLike without unsafe double casts. */
|
|
15
|
+
function toGistOctokit(octokit) {
|
|
16
|
+
return {
|
|
17
|
+
gists: {
|
|
18
|
+
async get(params) {
|
|
19
|
+
const { data } = await octokit.gists.get(params);
|
|
20
|
+
if (!data.id)
|
|
21
|
+
throw new Error("Gist get returned no id");
|
|
22
|
+
const files = data.files
|
|
23
|
+
? Object.fromEntries(Object.entries(data.files).map(([k, v]) => [
|
|
24
|
+
k,
|
|
25
|
+
v ? { content: v.content } : undefined,
|
|
26
|
+
]))
|
|
27
|
+
: null;
|
|
28
|
+
return { data: { id: data.id, files } };
|
|
29
|
+
},
|
|
30
|
+
async create(params) {
|
|
31
|
+
const { data } = await octokit.gists.create(params);
|
|
32
|
+
if (!data.id)
|
|
33
|
+
throw new Error("Gist create returned no id");
|
|
34
|
+
return { data: { id: data.id } };
|
|
35
|
+
},
|
|
36
|
+
async update(params) {
|
|
37
|
+
const { data } = await octokit.gists.update(params);
|
|
38
|
+
if (!data.id)
|
|
39
|
+
throw new Error("Gist update returned no id");
|
|
40
|
+
return { data: { id: data.id } };
|
|
41
|
+
},
|
|
42
|
+
async list(params) {
|
|
43
|
+
const { data } = await octokit.gists.list(params);
|
|
44
|
+
return {
|
|
45
|
+
data: data
|
|
46
|
+
.filter((g) => g.id)
|
|
47
|
+
.map((g) => ({
|
|
48
|
+
id: g.id,
|
|
49
|
+
description: g.description ?? null,
|
|
50
|
+
})),
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
13
56
|
/**
|
|
14
57
|
* Create an OssScout instance.
|
|
15
58
|
*
|
|
@@ -34,14 +77,14 @@ import { warn } from './core/logger.js';
|
|
|
34
77
|
export async function createScout(config) {
|
|
35
78
|
let state;
|
|
36
79
|
let gistStore = null;
|
|
37
|
-
if (config.persistence ===
|
|
80
|
+
if (config.persistence === "provided") {
|
|
38
81
|
state = config.initialState;
|
|
39
82
|
}
|
|
40
|
-
else if (config.persistence ===
|
|
41
|
-
gistStore = new GistStateStore(getOctokit(config.githubToken));
|
|
83
|
+
else if (config.persistence === "gist") {
|
|
84
|
+
gistStore = new GistStateStore(toGistOctokit(getOctokit(config.githubToken)));
|
|
42
85
|
const result = await gistStore.bootstrap();
|
|
43
86
|
if (result.degraded) {
|
|
44
|
-
warn(
|
|
87
|
+
warn("scout", "Gist sync unavailable — running in offline mode. Changes will only be saved locally.");
|
|
45
88
|
}
|
|
46
89
|
const localState = loadLocalState();
|
|
47
90
|
state = mergeStates(localState, result.state);
|
|
@@ -126,13 +169,13 @@ export class OssScout {
|
|
|
126
169
|
})
|
|
127
170
|
.catch((error) => {
|
|
128
171
|
const msg = error instanceof Error ? error.message : String(error);
|
|
129
|
-
const isGone = msg.includes(
|
|
172
|
+
const isGone = msg.includes("Not Found") || msg.includes("410");
|
|
130
173
|
results.push({
|
|
131
174
|
issueUrl: item.issueUrl,
|
|
132
175
|
repo: item.repo,
|
|
133
176
|
number: item.number,
|
|
134
177
|
title: item.title,
|
|
135
|
-
status: isGone ?
|
|
178
|
+
status: isGone ? "closed" : "error",
|
|
136
179
|
errorMessage: msg,
|
|
137
180
|
});
|
|
138
181
|
})
|
|
@@ -147,15 +190,18 @@ export class OssScout {
|
|
|
147
190
|
await Promise.allSettled(pending.values());
|
|
148
191
|
const summary = {
|
|
149
192
|
total: results.length,
|
|
150
|
-
stillAvailable: results.filter((r) => r.status ===
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
193
|
+
stillAvailable: results.filter((r) => r.status === "still_available")
|
|
194
|
+
.length,
|
|
195
|
+
claimed: results.filter((r) => r.status === "claimed").length,
|
|
196
|
+
closed: results.filter((r) => r.status === "closed").length,
|
|
197
|
+
hasPR: results.filter((r) => r.status === "has_pr").length,
|
|
198
|
+
errors: results.filter((r) => r.status === "error").length,
|
|
155
199
|
};
|
|
156
200
|
let prunedCount;
|
|
157
201
|
if (options?.prune) {
|
|
158
|
-
const unavailableUrls = new Set(results
|
|
202
|
+
const unavailableUrls = new Set(results
|
|
203
|
+
.filter((r) => r.status !== "still_available")
|
|
204
|
+
.map((r) => r.issueUrl));
|
|
159
205
|
const before = (this.state.savedResults ?? []).length;
|
|
160
206
|
this.state.savedResults = (this.state.savedResults ?? []).filter((r) => !unavailableUrls.has(r.issueUrl));
|
|
161
207
|
prunedCount = before - (this.state.savedResults?.length ?? 0);
|
|
@@ -166,16 +212,16 @@ export class OssScout {
|
|
|
166
212
|
classifyVetResult(candidate) {
|
|
167
213
|
const checks = candidate.vettingResult.checks;
|
|
168
214
|
if (!checks.noExistingPR)
|
|
169
|
-
return
|
|
215
|
+
return "has_pr";
|
|
170
216
|
if (!checks.notClaimed)
|
|
171
|
-
return
|
|
172
|
-
return
|
|
217
|
+
return "claimed";
|
|
218
|
+
return "still_available";
|
|
173
219
|
}
|
|
174
220
|
// ── State Reads (ScoutStateReader implementation) ───────────────────
|
|
175
221
|
getReposWithMergedPRs() {
|
|
176
222
|
const repoCounts = new Map();
|
|
177
223
|
for (const pr of this.state.mergedPRs ?? []) {
|
|
178
|
-
const repo =
|
|
224
|
+
const repo = extractRepoFromUrl(pr.url);
|
|
179
225
|
if (repo) {
|
|
180
226
|
repoCounts.set(repo, (repoCounts.get(repo) ?? 0) + 1);
|
|
181
227
|
}
|
|
@@ -353,21 +399,16 @@ export class OssScout {
|
|
|
353
399
|
return this.state;
|
|
354
400
|
}
|
|
355
401
|
// ── Private helpers ─────────────────────────────────────────────────
|
|
356
|
-
extractRepoFromUrl(url) {
|
|
357
|
-
const match = url.match(/github\.com\/([^/]+\/[^/]+)\//);
|
|
358
|
-
return match ? match[1] : null;
|
|
359
|
-
}
|
|
360
402
|
updateRepoScoreFromPRs(repo) {
|
|
361
|
-
const mergedCount = (this.state.mergedPRs ?? []).filter((p) =>
|
|
362
|
-
const closedCount = (this.state.closedPRs ?? []).filter((p) =>
|
|
403
|
+
const mergedCount = (this.state.mergedPRs ?? []).filter((p) => extractRepoFromUrl(p.url) === repo).length;
|
|
404
|
+
const closedCount = (this.state.closedPRs ?? []).filter((p) => extractRepoFromUrl(p.url) === repo).length;
|
|
363
405
|
this.updateRepoScore(repo, {
|
|
364
406
|
mergedPRCount: mergedCount,
|
|
365
407
|
closedWithoutMergeCount: closedCount,
|
|
366
408
|
lastMergedAt: mergedCount > 0
|
|
367
409
|
? (this.state.mergedPRs ?? [])
|
|
368
|
-
.filter((p) =>
|
|
369
|
-
.sort((a, b) => b.mergedAt.localeCompare(a.mergedAt))[0]
|
|
370
|
-
?.mergedAt
|
|
410
|
+
.filter((p) => extractRepoFromUrl(p.url) === repo)
|
|
411
|
+
.sort((a, b) => b.mergedAt.localeCompare(a.mergedAt))[0]?.mergedAt
|
|
371
412
|
: undefined,
|
|
372
413
|
});
|
|
373
414
|
}
|