terminalhire 0.20.0 → 0.21.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/bin/claim-push-bg.js +16 -7
- package/dist/bin/jpi-bounties.js +122 -13
- package/dist/bin/jpi-chat-read.js +17 -0
- package/dist/bin/jpi-chat.js +17 -0
- package/dist/bin/jpi-claim.js +159 -98
- package/dist/bin/jpi-contribute.js +17 -0
- package/dist/bin/jpi-devs.js +123 -14
- package/dist/bin/jpi-dispatch.js +329 -130
- package/dist/bin/jpi-inbox.js +17 -0
- package/dist/bin/jpi-init.js +6921 -28
- package/dist/bin/jpi-intro.js +17 -0
- package/dist/bin/jpi-jobs.js +122 -13
- package/dist/bin/jpi-learn.js +17 -0
- package/dist/bin/jpi-login.js +122 -13
- package/dist/bin/jpi-profile.js +17 -0
- package/dist/bin/jpi-project.js +166 -30
- package/dist/bin/jpi-refresh.js +199 -68
- package/dist/bin/jpi-save.js +17 -0
- package/dist/bin/jpi-spinner.js +18 -0
- package/dist/bin/jpi-sync.js +17 -0
- package/dist/bin/jpi-trajectory.js +17 -0
- package/dist/bin/spinner.js +20 -22
- package/dist/src/chat-client.js +18 -0
- package/dist/src/chat-keystore.js +18 -0
- package/dist/src/claims.js +11 -1
- package/dist/src/intro.js +17 -0
- package/dist/src/profile.js +18 -0
- package/dist/src/signal.js +18 -0
- package/dist/src/trajectory.js +17 -0
- package/package.json +1 -1
|
@@ -99,6 +99,7 @@ var require_keytar2 = __commonJS({
|
|
|
99
99
|
// src/claims.ts
|
|
100
100
|
var claims_exports = {};
|
|
101
101
|
__export(claims_exports, {
|
|
102
|
+
PUSHED_CLAIM_FIELDS: () => PUSHED_CLAIM_FIELDS,
|
|
102
103
|
acceptedPRRate: () => acceptedPRRate,
|
|
103
104
|
findClaim: () => findClaim,
|
|
104
105
|
listClaims: () => listClaims,
|
|
@@ -199,12 +200,21 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
199
200
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
200
201
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
201
202
|
}
|
|
202
|
-
var TERMINALHIRE_DIR2, CLAIMS_FILE, TERMINAL_STATES;
|
|
203
|
+
var TERMINALHIRE_DIR2, CLAIMS_FILE, PUSHED_CLAIM_FIELDS, TERMINAL_STATES;
|
|
203
204
|
var init_claims = __esm({
|
|
204
205
|
"src/claims.ts"() {
|
|
205
206
|
"use strict";
|
|
206
|
-
TERMINALHIRE_DIR2 = join2(homedir2(), ".terminalhire");
|
|
207
|
+
TERMINALHIRE_DIR2 = process.env.TERMINALHIRE_DIR || join2(homedir2(), ".terminalhire");
|
|
207
208
|
CLAIMS_FILE = join2(TERMINALHIRE_DIR2, "claims.json");
|
|
209
|
+
PUSHED_CLAIM_FIELDS = [
|
|
210
|
+
"kind",
|
|
211
|
+
"repoFullName",
|
|
212
|
+
"state",
|
|
213
|
+
"prUrl",
|
|
214
|
+
"merged",
|
|
215
|
+
"claimedAt",
|
|
216
|
+
"updatedAt"
|
|
217
|
+
];
|
|
208
218
|
TERMINAL_STATES = /* @__PURE__ */ new Set(["merged", "abandoned"]);
|
|
209
219
|
}
|
|
210
220
|
});
|
|
@@ -278,7 +288,6 @@ var CLAIM_PUSH_TOKEN_FILE = join3(TERMINALHIRE_DIR3, "claim-push-token.enc");
|
|
|
278
288
|
var CLAIM_SYNC_BASE = "https://terminalhire.com";
|
|
279
289
|
var AUTO_CONSENT_VERSION = 2;
|
|
280
290
|
var AUTO_PUSH_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
281
|
-
var CLAIM_PUSH_FIELDS = ["kind", "repoFullName", "state", "prUrl", "merged", "claimedAt", "updatedAt"];
|
|
282
291
|
async function writePushTokenEnc(rawToken) {
|
|
283
292
|
mkdirSync3(TERMINALHIRE_DIR3, { recursive: true });
|
|
284
293
|
const key = await loadKey();
|
|
@@ -348,7 +357,7 @@ async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
|
348
357
|
if (!existsSync3(CLAIM_PUSH_AUTO_MARKER) || !existsSync3(CLAIM_PUSH_TOKEN_FILE)) return;
|
|
349
358
|
const marker = readAutoMarker();
|
|
350
359
|
if (!marker || !marker.autoConsentedAt) return;
|
|
351
|
-
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
360
|
+
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2, PUSHED_CLAIM_FIELDS: PUSHED_CLAIM_FIELDS2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
352
361
|
const pushed = listClaims2().map((c) => toPushedClaim2(c));
|
|
353
362
|
const currentHash = computeSnapshotHash(pushed);
|
|
354
363
|
const gate = backgroundPushGate({
|
|
@@ -363,15 +372,15 @@ async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
|
363
372
|
if (!gate.push) return;
|
|
364
373
|
const token = await readPushTokenEnc();
|
|
365
374
|
if (!token) return;
|
|
366
|
-
const
|
|
375
|
+
const consentReceipt = {
|
|
367
376
|
consentedAt: marker.autoConsentedAt,
|
|
368
377
|
version: AUTO_CONSENT_VERSION,
|
|
369
|
-
fields:
|
|
378
|
+
fields: PUSHED_CLAIM_FIELDS2
|
|
370
379
|
};
|
|
371
380
|
const res = await fetch(`${CLAIM_SYNC_BASE}/api/claim-sync`, {
|
|
372
381
|
method: "POST",
|
|
373
382
|
headers: { "Content-Type": "application/json" },
|
|
374
|
-
body: JSON.stringify({ consentToken, claims: pushed, pushToken: token }),
|
|
383
|
+
body: JSON.stringify({ consentToken: consentReceipt, claims: pushed, pushToken: token }),
|
|
375
384
|
signal: AbortSignal.timeout(1e4)
|
|
376
385
|
});
|
|
377
386
|
if (!res.ok) return;
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -924,7 +924,7 @@ async function repoContributorCount(owner, name, token) {
|
|
|
924
924
|
return void 0;
|
|
925
925
|
}
|
|
926
926
|
}
|
|
927
|
-
async function fetchRepoMeta(owner, name, token, cache) {
|
|
927
|
+
async function fetchRepoMeta(owner, name, token, cache, stats) {
|
|
928
928
|
const key = `${owner}/${name}`.toLowerCase();
|
|
929
929
|
const cached = cache.get(key);
|
|
930
930
|
if (cached !== void 0) return cached;
|
|
@@ -941,8 +941,10 @@ async function fetchRepoMeta(owner, name, token, cache) {
|
|
|
941
941
|
topics: r.topics ?? [],
|
|
942
942
|
contributors
|
|
943
943
|
};
|
|
944
|
-
} catch {
|
|
944
|
+
} catch (err) {
|
|
945
945
|
meta = null;
|
|
946
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
947
|
+
if (stats && TRANSIENT_META_ERROR.test(msg)) stats.transient += 1;
|
|
946
948
|
}
|
|
947
949
|
cache.set(key, meta);
|
|
948
950
|
return meta;
|
|
@@ -981,8 +983,10 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
981
983
|
return emptyCredential(/HTTP 403|HTTP 429|rate limit/i.test(msg) ? "rate-limited" : "failed");
|
|
982
984
|
}
|
|
983
985
|
const byDomain = {};
|
|
986
|
+
const distinctOrgSet = /* @__PURE__ */ new Set();
|
|
984
987
|
let qualifyingTotal = 0;
|
|
985
988
|
const qualifyingPRs = [];
|
|
989
|
+
const metaStats = { transient: 0 };
|
|
986
990
|
for (const item of items) {
|
|
987
991
|
const repo = parseRepoUrl(item.repository_url);
|
|
988
992
|
if (!repo) continue;
|
|
@@ -990,13 +994,20 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
990
994
|
if (ownerLc === loginLc) continue;
|
|
991
995
|
if (ownedOrgs.has(ownerLc)) continue;
|
|
992
996
|
if (isTrivialPRTitle(item.title)) continue;
|
|
993
|
-
const meta = await fetchRepoMeta(repo.owner, repo.name, token, cache);
|
|
997
|
+
const meta = await fetchRepoMeta(repo.owner, repo.name, token, cache, metaStats);
|
|
998
|
+
if (metaStats.transient > 0) {
|
|
999
|
+
console.warn(
|
|
1000
|
+
`[acceptance] ${login}: per-repo metadata transient failure (${metaStats.transient}) \u2014 degrading to 'rate-limited' rather than a fabricated count`
|
|
1001
|
+
);
|
|
1002
|
+
return emptyCredential("rate-limited");
|
|
1003
|
+
}
|
|
994
1004
|
if (!meta) continue;
|
|
995
1005
|
if (meta.private) continue;
|
|
996
1006
|
if (meta.archived || meta.fork) continue;
|
|
997
1007
|
if (meta.stars < gates.minStars) continue;
|
|
998
1008
|
if (meta.contributors !== void 0 && meta.contributors < gates.minContributors) continue;
|
|
999
1009
|
qualifyingTotal += 1;
|
|
1010
|
+
distinctOrgSet.add(ownerLc);
|
|
1000
1011
|
const mergedAt = item.pull_request?.merged_at ?? item.closed_at ?? item.created_at;
|
|
1001
1012
|
const rawDomains = [meta.language ?? "", ...meta.topics].filter(Boolean);
|
|
1002
1013
|
const domainTags = [...new Set(normalize(rawDomains))];
|
|
@@ -1022,7 +1033,14 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
1022
1033
|
lastMergedAt: b.lastMergedAt
|
|
1023
1034
|
};
|
|
1024
1035
|
}
|
|
1025
|
-
return {
|
|
1036
|
+
return {
|
|
1037
|
+
status: "ok",
|
|
1038
|
+
byDomain: finalDomains,
|
|
1039
|
+
qualifyingTotal,
|
|
1040
|
+
qualifyingPRs,
|
|
1041
|
+
distinctOrgs: distinctOrgSet.size,
|
|
1042
|
+
computedAt
|
|
1043
|
+
};
|
|
1026
1044
|
}
|
|
1027
1045
|
async function computeAcceptanceCredential(login, token, cache = /* @__PURE__ */ new Map()) {
|
|
1028
1046
|
if (!token) return emptyCredential("no-token");
|
|
@@ -1036,6 +1054,61 @@ async function computeAcceptanceCredentialPublic(login, token, cache = /* @__PUR
|
|
|
1036
1054
|
const gates = opts?.relaxGates ? { minStars: 0, minContributors: 0 } : void 0;
|
|
1037
1055
|
return computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates);
|
|
1038
1056
|
}
|
|
1057
|
+
async function fetchOpenExternalPRs(login, token, cache = /* @__PURE__ */ new Map(), gates = {
|
|
1058
|
+
minStars: MIN_STARS,
|
|
1059
|
+
minContributors: MIN_CONTRIBUTORS
|
|
1060
|
+
}) {
|
|
1061
|
+
if (!token) return [];
|
|
1062
|
+
const loginLc = login.toLowerCase();
|
|
1063
|
+
let ownedOrgs;
|
|
1064
|
+
try {
|
|
1065
|
+
ownedOrgs = await fetchPublicOrgs(login, token);
|
|
1066
|
+
} catch {
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1069
|
+
let items;
|
|
1070
|
+
try {
|
|
1071
|
+
const q = encodeURIComponent(`type:pr is:open is:public author:${login} -user:${login} sort:updated`);
|
|
1072
|
+
const res = await ghFetch(
|
|
1073
|
+
`/search/issues?q=${q}&per_page=${OPEN_PR_PAGE}`,
|
|
1074
|
+
token
|
|
1075
|
+
);
|
|
1076
|
+
items = res.items ?? [];
|
|
1077
|
+
} catch (err) {
|
|
1078
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1079
|
+
console.warn("[open-prs] search failed:", msg);
|
|
1080
|
+
return null;
|
|
1081
|
+
}
|
|
1082
|
+
const metaStats = { transient: 0 };
|
|
1083
|
+
const out = [];
|
|
1084
|
+
for (const item of items) {
|
|
1085
|
+
const repo = parseRepoUrl(item.repository_url);
|
|
1086
|
+
if (!repo) continue;
|
|
1087
|
+
const ownerLc = repo.owner.toLowerCase();
|
|
1088
|
+
if (ownerLc === loginLc) continue;
|
|
1089
|
+
if (ownedOrgs.has(ownerLc)) continue;
|
|
1090
|
+
if (isTrivialPRTitle(item.title)) continue;
|
|
1091
|
+
const meta = await fetchRepoMeta(repo.owner, repo.name, token, cache, metaStats);
|
|
1092
|
+
if (metaStats.transient > 0) {
|
|
1093
|
+
console.warn(
|
|
1094
|
+
`[open-prs] ${login}: per-repo metadata transient failure (${metaStats.transient}) \u2014 returning null (keep prior strip)`
|
|
1095
|
+
);
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
if (!meta) continue;
|
|
1099
|
+
if (meta.private) continue;
|
|
1100
|
+
if (meta.archived || meta.fork) continue;
|
|
1101
|
+
if (meta.stars < gates.minStars) continue;
|
|
1102
|
+
if (meta.contributors !== void 0 && meta.contributors < gates.minContributors) continue;
|
|
1103
|
+
out.push({
|
|
1104
|
+
title: item.title,
|
|
1105
|
+
url: item.html_url,
|
|
1106
|
+
repoFullName: `${repo.owner}/${repo.name}`,
|
|
1107
|
+
openedAt: item.created_at
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
return out;
|
|
1111
|
+
}
|
|
1039
1112
|
function acceptanceCountForDomains(cred, domains) {
|
|
1040
1113
|
if (cred.status !== "ok") return 0;
|
|
1041
1114
|
let max = 0;
|
|
@@ -1107,7 +1180,7 @@ function deriveResumeTrend(cred, repoRecency, now = Date.now()) {
|
|
|
1107
1180
|
}
|
|
1108
1181
|
return scored.sort((a, b) => b.weight - a.weight).slice(0, 12).map((s) => s.t);
|
|
1109
1182
|
}
|
|
1110
|
-
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1183
|
+
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1111
1184
|
var init_github = __esm({
|
|
1112
1185
|
"../../packages/core/src/github.ts"() {
|
|
1113
1186
|
"use strict";
|
|
@@ -1115,6 +1188,8 @@ var init_github = __esm({
|
|
|
1115
1188
|
init_contribution_gate();
|
|
1116
1189
|
TRACTION_TOP_N = 6;
|
|
1117
1190
|
CANDIDATE_PR_PAGE = 50;
|
|
1191
|
+
OPEN_PR_PAGE = 20;
|
|
1192
|
+
TRANSIENT_META_ERROR = /HTTP 403|HTTP 429|rate limit|HTTP 5\d\d|timeout|network|fetch failed/i;
|
|
1118
1193
|
RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
1119
1194
|
RESUME_MIN_SCORE = 0.05;
|
|
1120
1195
|
}
|
|
@@ -2860,6 +2935,10 @@ ${pr.body ?? ""}`.matchAll(/#(\d+)\b/g)) {
|
|
|
2860
2935
|
}
|
|
2861
2936
|
return refs;
|
|
2862
2937
|
}
|
|
2938
|
+
async function fetchRateLimit(client) {
|
|
2939
|
+
const r = await client.json("/rate_limit");
|
|
2940
|
+
return r?.resources ?? null;
|
|
2941
|
+
}
|
|
2863
2942
|
async function searchContribIssues(client, queries) {
|
|
2864
2943
|
const byUrl = /* @__PURE__ */ new Map();
|
|
2865
2944
|
for (const q of queries) {
|
|
@@ -2904,6 +2983,9 @@ async function aggregateContributions(opts = {}) {
|
|
|
2904
2983
|
const jobs = [];
|
|
2905
2984
|
const seen = /* @__PURE__ */ new Set();
|
|
2906
2985
|
const perRepo = /* @__PURE__ */ new Map();
|
|
2986
|
+
let metaNull = 0;
|
|
2987
|
+
let contribUndefined = 0;
|
|
2988
|
+
let prRefsNull = 0;
|
|
2907
2989
|
for (const issue of issues) {
|
|
2908
2990
|
if (jobs.length >= MAX_CONTRIB_ITEMS) break;
|
|
2909
2991
|
const fullName = repoFullNameFromApiUrl2(issue.repository_url);
|
|
@@ -2914,9 +2996,13 @@ async function aggregateContributions(opts = {}) {
|
|
|
2914
2996
|
if (isAssigned(issue)) continue;
|
|
2915
2997
|
if ((perRepo.get(fullName) ?? 0) >= MAX_BOUNTIES_PER_DISCOVERED_REPO) continue;
|
|
2916
2998
|
const repo = await repoMeta(fullName);
|
|
2917
|
-
if (!repo)
|
|
2999
|
+
if (!repo) {
|
|
3000
|
+
metaNull++;
|
|
3001
|
+
continue;
|
|
3002
|
+
}
|
|
2918
3003
|
const title = decodeEntities(issue.title).trim();
|
|
2919
3004
|
const contributors = await repoContribCount(fullName);
|
|
3005
|
+
if (contributors === void 0) contribUndefined++;
|
|
2920
3006
|
if (!passesContributionGate({
|
|
2921
3007
|
fullName,
|
|
2922
3008
|
stars: repo.stargazers_count,
|
|
@@ -2932,6 +3018,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
2932
3018
|
const labels = labelNames2(issue.labels);
|
|
2933
3019
|
if (looksLikeContentTask({ title, body, labels })) continue;
|
|
2934
3020
|
const prRefs = await repoPRRefs(fullName);
|
|
3021
|
+
if (prRefs === null) prRefsNull++;
|
|
2935
3022
|
if (prRefs && prRefs.has(issue.number)) continue;
|
|
2936
3023
|
const openPRsAtDiscovery = prRefs ? 0 : void 0;
|
|
2937
3024
|
const tags = normalize(
|
|
@@ -2971,9 +3058,18 @@ async function aggregateContributions(opts = {}) {
|
|
|
2971
3058
|
raw: issue
|
|
2972
3059
|
});
|
|
2973
3060
|
}
|
|
3061
|
+
if (!opts.fetchImpl) {
|
|
3062
|
+
const rl = await fetchRateLimit(client);
|
|
3063
|
+
const core = rl?.core ? `${rl.core.remaining}/${rl.core.limit}` : "n/a";
|
|
3064
|
+
const search = rl?.search ? `${rl.search.remaining}/${rl.search.limit}` : "n/a";
|
|
3065
|
+
const noToken = !(process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"]);
|
|
3066
|
+
console.info(
|
|
3067
|
+
`[contribute] build metrics \u2014 scanned=${issues.length} reposDistinct=${repoCache.size} emitted=${jobs.length} metaNull=${metaNull} contribUndefined=${contribUndefined} prRefsNull=${prRefsNull} core=${core} search=${search}` + (noToken ? " (NO TOKEN \u2192 60/hr)" : "")
|
|
3068
|
+
);
|
|
3069
|
+
}
|
|
2974
3070
|
return jobs;
|
|
2975
3071
|
}
|
|
2976
|
-
var GITHUB_API2, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2, MAX_CONTRIB_ITEMS, MAX_CONTRIB_ISSUES_SCANNED;
|
|
3072
|
+
var GITHUB_API2, CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2, MAX_CONTRIB_ITEMS, MAX_CONTRIB_ISSUES_SCANNED;
|
|
2977
3073
|
var init_contributions = __esm({
|
|
2978
3074
|
"../../packages/core/src/feeds/contributions.ts"() {
|
|
2979
3075
|
"use strict";
|
|
@@ -2985,15 +3081,25 @@ var init_contributions = __esm({
|
|
|
2985
3081
|
init_github_bounties();
|
|
2986
3082
|
init_http();
|
|
2987
3083
|
GITHUB_API2 = "https://api.github.com";
|
|
2988
|
-
|
|
3084
|
+
CONTRIB_LABEL_QUERIES = [
|
|
2989
3085
|
'label:"good first issue" type:issue state:open',
|
|
2990
|
-
'label:"help wanted" type:issue state:open',
|
|
2991
3086
|
'label:"good-first-issue" type:issue state:open',
|
|
2992
|
-
'label:"help
|
|
3087
|
+
'label:"help wanted" type:issue state:open',
|
|
3088
|
+
'label:"help-wanted" type:issue state:open',
|
|
3089
|
+
'label:"up-for-grabs" type:issue state:open'
|
|
3090
|
+
];
|
|
3091
|
+
CONTRIB_LANGUAGE_QUERIES = [
|
|
3092
|
+
...["rust", "go", "python", "c++", "ruby"].map(
|
|
3093
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
3094
|
+
),
|
|
3095
|
+
...["rust", "go"].map(
|
|
3096
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
3097
|
+
)
|
|
2993
3098
|
];
|
|
3099
|
+
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
2994
3100
|
SEARCH_PER_PAGE2 = 100;
|
|
2995
3101
|
MAX_CONTRIB_ITEMS = 150;
|
|
2996
|
-
MAX_CONTRIB_ISSUES_SCANNED =
|
|
3102
|
+
MAX_CONTRIB_ISSUES_SCANNED = 600;
|
|
2997
3103
|
}
|
|
2998
3104
|
});
|
|
2999
3105
|
|
|
@@ -6436,13 +6542,15 @@ function deriveLegibleProfile(credential, recency, traction, seniorityBand) {
|
|
|
6436
6542
|
daysAgo = Math.max(0, Math.round(ageDays2));
|
|
6437
6543
|
recencyBadge = { lastMergedAt: mostRecent, state: ageDays2 <= thresholdDays ? "live" : "dormant" };
|
|
6438
6544
|
}
|
|
6439
|
-
const
|
|
6545
|
+
const exactOrgCount = typeof credential.distinctOrgs === "number" && credential.distinctOrgs > 0;
|
|
6546
|
+
const orgCount = exactOrgCount ? credential.distinctOrgs : Object.values(domains).reduce((m, d) => Math.max(m, d.distinctOrgs), 0);
|
|
6440
6547
|
let proofSentence;
|
|
6441
6548
|
if (!ok) {
|
|
6442
6549
|
proofSentence = "Contribution credential unavailable \u2014 could not verify.";
|
|
6443
6550
|
} else {
|
|
6444
6551
|
const prs = credential.qualifyingTotal;
|
|
6445
|
-
|
|
6552
|
+
const orgPhrase = exactOrgCount ? `${orgCount}` : `at least ${orgCount}`;
|
|
6553
|
+
let s = `${prs} substantive PR${prs === 1 ? "" : "s"} merged into ${orgPhrase} external org${orgCount === 1 ? "" : "s"} (\u2265${MIN_STARS}\u2605, \u2265${MIN_CONTRIBUTORS} contributors)`;
|
|
6446
6554
|
if (daysAgo !== void 0) s += ` \u2014 most recent ${daysAgo}d ago`;
|
|
6447
6555
|
proofSentence = `${s}.`;
|
|
6448
6556
|
}
|
|
@@ -6680,6 +6788,7 @@ __export(src_exports, {
|
|
|
6680
6788
|
expandWeighted: () => expandWeighted,
|
|
6681
6789
|
extractSkillTags: () => extractSkillTags,
|
|
6682
6790
|
fetchGitHubProfile: () => fetchGitHubProfile,
|
|
6791
|
+
fetchOpenExternalPRs: () => fetchOpenExternalPRs,
|
|
6683
6792
|
fetchOwnedRepoTraction: () => fetchOwnedRepoTraction,
|
|
6684
6793
|
fetchRepoRecency: () => fetchRepoRecency,
|
|
6685
6794
|
flattenTiers: () => flattenTiers,
|
|
@@ -751,6 +751,7 @@ var init_contribution_classify = __esm({
|
|
|
751
751
|
});
|
|
752
752
|
|
|
753
753
|
// ../../packages/core/src/feeds/contributions.ts
|
|
754
|
+
var CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES;
|
|
754
755
|
var init_contributions = __esm({
|
|
755
756
|
"../../packages/core/src/feeds/contributions.ts"() {
|
|
756
757
|
"use strict";
|
|
@@ -761,6 +762,22 @@ var init_contributions = __esm({
|
|
|
761
762
|
init_contribution_classify();
|
|
762
763
|
init_github_bounties();
|
|
763
764
|
init_http();
|
|
765
|
+
CONTRIB_LABEL_QUERIES = [
|
|
766
|
+
'label:"good first issue" type:issue state:open',
|
|
767
|
+
'label:"good-first-issue" type:issue state:open',
|
|
768
|
+
'label:"help wanted" type:issue state:open',
|
|
769
|
+
'label:"help-wanted" type:issue state:open',
|
|
770
|
+
'label:"up-for-grabs" type:issue state:open'
|
|
771
|
+
];
|
|
772
|
+
CONTRIB_LANGUAGE_QUERIES = [
|
|
773
|
+
...["rust", "go", "python", "c++", "ruby"].map(
|
|
774
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
775
|
+
),
|
|
776
|
+
...["rust", "go"].map(
|
|
777
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
778
|
+
)
|
|
779
|
+
];
|
|
780
|
+
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
764
781
|
}
|
|
765
782
|
});
|
|
766
783
|
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -768,6 +768,7 @@ var init_contribution_classify = __esm({
|
|
|
768
768
|
});
|
|
769
769
|
|
|
770
770
|
// ../../packages/core/src/feeds/contributions.ts
|
|
771
|
+
var CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES;
|
|
771
772
|
var init_contributions = __esm({
|
|
772
773
|
"../../packages/core/src/feeds/contributions.ts"() {
|
|
773
774
|
"use strict";
|
|
@@ -778,6 +779,22 @@ var init_contributions = __esm({
|
|
|
778
779
|
init_contribution_classify();
|
|
779
780
|
init_github_bounties();
|
|
780
781
|
init_http();
|
|
782
|
+
CONTRIB_LABEL_QUERIES = [
|
|
783
|
+
'label:"good first issue" type:issue state:open',
|
|
784
|
+
'label:"good-first-issue" type:issue state:open',
|
|
785
|
+
'label:"help wanted" type:issue state:open',
|
|
786
|
+
'label:"help-wanted" type:issue state:open',
|
|
787
|
+
'label:"up-for-grabs" type:issue state:open'
|
|
788
|
+
];
|
|
789
|
+
CONTRIB_LANGUAGE_QUERIES = [
|
|
790
|
+
...["rust", "go", "python", "c++", "ruby"].map(
|
|
791
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
792
|
+
),
|
|
793
|
+
...["rust", "go"].map(
|
|
794
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
795
|
+
)
|
|
796
|
+
];
|
|
797
|
+
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
781
798
|
}
|
|
782
799
|
});
|
|
783
800
|
|