terminalhire 0.20.0 → 0.22.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 +18 -9
- package/dist/bin/jpi-bounties.js +356 -25
- package/dist/bin/jpi-chat-read.js +27 -2
- package/dist/bin/jpi-chat.js +27 -2
- package/dist/bin/jpi-claim.js +6715 -233
- package/dist/bin/jpi-contribute.js +27 -2
- package/dist/bin/jpi-devs.js +357 -26
- package/dist/bin/jpi-dispatch.js +915 -204
- package/dist/bin/jpi-inbox.js +27 -2
- package/dist/bin/jpi-init.js +7143 -28
- package/dist/bin/jpi-intro.js +27 -2
- package/dist/bin/jpi-jobs.js +356 -25
- package/dist/bin/jpi-learn.js +27 -2
- package/dist/bin/jpi-login.js +356 -25
- package/dist/bin/jpi-profile.js +27 -2
- package/dist/bin/jpi-project.js +398 -40
- package/dist/bin/jpi-refresh.js +433 -80
- package/dist/bin/jpi-save.js +27 -2
- package/dist/bin/jpi-spinner.js +18 -0
- package/dist/bin/jpi-sync.js +27 -2
- package/dist/bin/jpi-trajectory.js +27 -2
- package/dist/bin/spinner.js +20 -22
- package/dist/src/chat-client.js +20 -2
- package/dist/src/chat-keystore.js +20 -2
- package/dist/src/claims.js +11 -1
- package/dist/src/github-auth.js +2 -2
- package/dist/src/intro.js +27 -2
- package/dist/src/profile.js +20 -2
- package/dist/src/signal.js +18 -0
- package/dist/src/trajectory.js +27 -2
- package/package.json +1 -1
|
@@ -45,9 +45,9 @@ var init_keytar = __esm({
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
48
|
+
// node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/claim-frictionless/node_modules/keytar/build/Release/keytar.node
|
|
49
49
|
var require_keytar = __commonJS({
|
|
50
|
-
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
50
|
+
"node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/claim-frictionless/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
51
51
|
"use strict";
|
|
52
52
|
init_keytar();
|
|
53
53
|
try {
|
|
@@ -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
|
@@ -761,9 +761,9 @@ function ghHeaders(token) {
|
|
|
761
761
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
762
762
|
return headers;
|
|
763
763
|
}
|
|
764
|
-
async function ghFetch(path, token) {
|
|
764
|
+
async function ghFetch(path, token, signal) {
|
|
765
765
|
const url = `https://api.github.com${path}`;
|
|
766
|
-
const res = await fetch(url, { headers: ghHeaders(token) });
|
|
766
|
+
const res = await fetch(url, { headers: ghHeaders(token), signal });
|
|
767
767
|
if (!res.ok) {
|
|
768
768
|
throw new Error(`GitHub API ${path}: HTTP ${res.status} ${res.statusText}`);
|
|
769
769
|
}
|
|
@@ -812,6 +812,7 @@ async function fetchGitHubProfile(login, token) {
|
|
|
812
812
|
} catch {
|
|
813
813
|
}
|
|
814
814
|
return {
|
|
815
|
+
id: user.id,
|
|
815
816
|
login: user.login,
|
|
816
817
|
name: user.name ?? void 0,
|
|
817
818
|
publicEmail: user.email ?? void 0,
|
|
@@ -888,8 +889,8 @@ async function fetchOwnedRepoTraction(login, token) {
|
|
|
888
889
|
computedAt
|
|
889
890
|
};
|
|
890
891
|
}
|
|
891
|
-
async function ghFetchRaw(path, token) {
|
|
892
|
-
return fetch(`https://api.github.com${path}`, { headers: ghHeaders(token) });
|
|
892
|
+
async function ghFetchRaw(path, token, signal) {
|
|
893
|
+
return fetch(`https://api.github.com${path}`, { headers: ghHeaders(token), signal });
|
|
893
894
|
}
|
|
894
895
|
function parseRepoUrl(repoUrl) {
|
|
895
896
|
const m = repoUrl.match(/\/repos\/([^/]+)\/([^/]+)\/?$/);
|
|
@@ -908,11 +909,12 @@ async function fetchOwnedOrgs(token) {
|
|
|
908
909
|
return /* @__PURE__ */ new Set();
|
|
909
910
|
}
|
|
910
911
|
}
|
|
911
|
-
async function repoContributorCount(owner, name, token) {
|
|
912
|
+
async function repoContributorCount(owner, name, token, signal) {
|
|
912
913
|
try {
|
|
913
914
|
const res = await ghFetchRaw(
|
|
914
915
|
`/repos/${owner}/${name}/contributors?per_page=1&anon=false`,
|
|
915
|
-
token
|
|
916
|
+
token,
|
|
917
|
+
signal
|
|
916
918
|
);
|
|
917
919
|
if (!res.ok) return void 0;
|
|
918
920
|
const link = res.headers.get("link");
|
|
@@ -924,7 +926,7 @@ async function repoContributorCount(owner, name, token) {
|
|
|
924
926
|
return void 0;
|
|
925
927
|
}
|
|
926
928
|
}
|
|
927
|
-
async function fetchRepoMeta(owner, name, token, cache) {
|
|
929
|
+
async function fetchRepoMeta(owner, name, token, cache, stats) {
|
|
928
930
|
const key = `${owner}/${name}`.toLowerCase();
|
|
929
931
|
const cached = cache.get(key);
|
|
930
932
|
if (cached !== void 0) return cached;
|
|
@@ -941,8 +943,10 @@ async function fetchRepoMeta(owner, name, token, cache) {
|
|
|
941
943
|
topics: r.topics ?? [],
|
|
942
944
|
contributors
|
|
943
945
|
};
|
|
944
|
-
} catch {
|
|
946
|
+
} catch (err) {
|
|
945
947
|
meta = null;
|
|
948
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
949
|
+
if (stats && TRANSIENT_META_ERROR.test(msg)) stats.transient += 1;
|
|
946
950
|
}
|
|
947
951
|
cache.set(key, meta);
|
|
948
952
|
return meta;
|
|
@@ -981,8 +985,10 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
981
985
|
return emptyCredential(/HTTP 403|HTTP 429|rate limit/i.test(msg) ? "rate-limited" : "failed");
|
|
982
986
|
}
|
|
983
987
|
const byDomain = {};
|
|
988
|
+
const distinctOrgSet = /* @__PURE__ */ new Set();
|
|
984
989
|
let qualifyingTotal = 0;
|
|
985
990
|
const qualifyingPRs = [];
|
|
991
|
+
const metaStats = { transient: 0 };
|
|
986
992
|
for (const item of items) {
|
|
987
993
|
const repo = parseRepoUrl(item.repository_url);
|
|
988
994
|
if (!repo) continue;
|
|
@@ -990,13 +996,20 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
990
996
|
if (ownerLc === loginLc) continue;
|
|
991
997
|
if (ownedOrgs.has(ownerLc)) continue;
|
|
992
998
|
if (isTrivialPRTitle(item.title)) continue;
|
|
993
|
-
const meta = await fetchRepoMeta(repo.owner, repo.name, token, cache);
|
|
999
|
+
const meta = await fetchRepoMeta(repo.owner, repo.name, token, cache, metaStats);
|
|
1000
|
+
if (metaStats.transient > 0) {
|
|
1001
|
+
console.warn(
|
|
1002
|
+
`[acceptance] ${login}: per-repo metadata transient failure (${metaStats.transient}) \u2014 degrading to 'rate-limited' rather than a fabricated count`
|
|
1003
|
+
);
|
|
1004
|
+
return emptyCredential("rate-limited");
|
|
1005
|
+
}
|
|
994
1006
|
if (!meta) continue;
|
|
995
1007
|
if (meta.private) continue;
|
|
996
1008
|
if (meta.archived || meta.fork) continue;
|
|
997
1009
|
if (meta.stars < gates.minStars) continue;
|
|
998
1010
|
if (meta.contributors !== void 0 && meta.contributors < gates.minContributors) continue;
|
|
999
1011
|
qualifyingTotal += 1;
|
|
1012
|
+
distinctOrgSet.add(ownerLc);
|
|
1000
1013
|
const mergedAt = item.pull_request?.merged_at ?? item.closed_at ?? item.created_at;
|
|
1001
1014
|
const rawDomains = [meta.language ?? "", ...meta.topics].filter(Boolean);
|
|
1002
1015
|
const domainTags = [...new Set(normalize(rawDomains))];
|
|
@@ -1022,7 +1035,14 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
1022
1035
|
lastMergedAt: b.lastMergedAt
|
|
1023
1036
|
};
|
|
1024
1037
|
}
|
|
1025
|
-
return {
|
|
1038
|
+
return {
|
|
1039
|
+
status: "ok",
|
|
1040
|
+
byDomain: finalDomains,
|
|
1041
|
+
qualifyingTotal,
|
|
1042
|
+
qualifyingPRs,
|
|
1043
|
+
distinctOrgs: distinctOrgSet.size,
|
|
1044
|
+
computedAt
|
|
1045
|
+
};
|
|
1026
1046
|
}
|
|
1027
1047
|
async function computeAcceptanceCredential(login, token, cache = /* @__PURE__ */ new Map()) {
|
|
1028
1048
|
if (!token) return emptyCredential("no-token");
|
|
@@ -1036,6 +1056,61 @@ async function computeAcceptanceCredentialPublic(login, token, cache = /* @__PUR
|
|
|
1036
1056
|
const gates = opts?.relaxGates ? { minStars: 0, minContributors: 0 } : void 0;
|
|
1037
1057
|
return computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates);
|
|
1038
1058
|
}
|
|
1059
|
+
async function fetchOpenExternalPRs(login, token, cache = /* @__PURE__ */ new Map(), gates = {
|
|
1060
|
+
minStars: MIN_STARS,
|
|
1061
|
+
minContributors: MIN_CONTRIBUTORS
|
|
1062
|
+
}) {
|
|
1063
|
+
if (!token) return [];
|
|
1064
|
+
const loginLc = login.toLowerCase();
|
|
1065
|
+
let ownedOrgs;
|
|
1066
|
+
try {
|
|
1067
|
+
ownedOrgs = await fetchPublicOrgs(login, token);
|
|
1068
|
+
} catch {
|
|
1069
|
+
return null;
|
|
1070
|
+
}
|
|
1071
|
+
let items;
|
|
1072
|
+
try {
|
|
1073
|
+
const q = encodeURIComponent(`type:pr is:open is:public author:${login} -user:${login} sort:updated`);
|
|
1074
|
+
const res = await ghFetch(
|
|
1075
|
+
`/search/issues?q=${q}&per_page=${OPEN_PR_PAGE}`,
|
|
1076
|
+
token
|
|
1077
|
+
);
|
|
1078
|
+
items = res.items ?? [];
|
|
1079
|
+
} catch (err) {
|
|
1080
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1081
|
+
console.warn("[open-prs] search failed:", msg);
|
|
1082
|
+
return null;
|
|
1083
|
+
}
|
|
1084
|
+
const metaStats = { transient: 0 };
|
|
1085
|
+
const out = [];
|
|
1086
|
+
for (const item of items) {
|
|
1087
|
+
const repo = parseRepoUrl(item.repository_url);
|
|
1088
|
+
if (!repo) continue;
|
|
1089
|
+
const ownerLc = repo.owner.toLowerCase();
|
|
1090
|
+
if (ownerLc === loginLc) continue;
|
|
1091
|
+
if (ownedOrgs.has(ownerLc)) continue;
|
|
1092
|
+
if (isTrivialPRTitle(item.title)) continue;
|
|
1093
|
+
const meta = await fetchRepoMeta(repo.owner, repo.name, token, cache, metaStats);
|
|
1094
|
+
if (metaStats.transient > 0) {
|
|
1095
|
+
console.warn(
|
|
1096
|
+
`[open-prs] ${login}: per-repo metadata transient failure (${metaStats.transient}) \u2014 returning null (keep prior strip)`
|
|
1097
|
+
);
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
if (!meta) continue;
|
|
1101
|
+
if (meta.private) continue;
|
|
1102
|
+
if (meta.archived || meta.fork) continue;
|
|
1103
|
+
if (meta.stars < gates.minStars) continue;
|
|
1104
|
+
if (meta.contributors !== void 0 && meta.contributors < gates.minContributors) continue;
|
|
1105
|
+
out.push({
|
|
1106
|
+
title: item.title,
|
|
1107
|
+
url: item.html_url,
|
|
1108
|
+
repoFullName: `${repo.owner}/${repo.name}`,
|
|
1109
|
+
openedAt: item.created_at
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
return out;
|
|
1113
|
+
}
|
|
1039
1114
|
function acceptanceCountForDomains(cred, domains) {
|
|
1040
1115
|
if (cred.status !== "ok") return 0;
|
|
1041
1116
|
let max = 0;
|
|
@@ -1107,7 +1182,78 @@ function deriveResumeTrend(cred, repoRecency, now = Date.now()) {
|
|
|
1107
1182
|
}
|
|
1108
1183
|
return scored.sort((a, b) => b.weight - a.weight).slice(0, 12).map((s) => s.t);
|
|
1109
1184
|
}
|
|
1110
|
-
|
|
1185
|
+
function parseGitHubRef(url) {
|
|
1186
|
+
const m = String(url ?? "").match(/github\.com\/([^/]+)\/([^/]+)\/(issues|pull)\/(\d+)/);
|
|
1187
|
+
if (!m) return null;
|
|
1188
|
+
return { owner: m[1], repo: m[2], number: parseInt(m[4], 10), kind: m[3] === "pull" ? "pull" : "issue" };
|
|
1189
|
+
}
|
|
1190
|
+
async function ghGraphQL(query, variables, token, signal) {
|
|
1191
|
+
const res = await fetch("https://api.github.com/graphql", {
|
|
1192
|
+
method: "POST",
|
|
1193
|
+
headers: { ...ghHeaders(token), "Content-Type": "application/json" },
|
|
1194
|
+
body: JSON.stringify({ query, variables }),
|
|
1195
|
+
signal
|
|
1196
|
+
});
|
|
1197
|
+
if (!res.ok) throw new Error(`GitHub GraphQL: HTTP ${res.status}`);
|
|
1198
|
+
const json = await res.json();
|
|
1199
|
+
if (json.errors?.length) throw new Error("GitHub GraphQL errors: " + JSON.stringify(json.errors));
|
|
1200
|
+
return json;
|
|
1201
|
+
}
|
|
1202
|
+
async function resolveClosingIssues(owner, name, number, body, token, signal) {
|
|
1203
|
+
if (token) {
|
|
1204
|
+
try {
|
|
1205
|
+
const q = `query($o:String!,$n:String!,$p:Int!){repository(owner:$o,name:$n){pullRequest(number:$p){closingIssuesReferences(first:20){nodes{number}}}}}`;
|
|
1206
|
+
const r = await ghGraphQL(q, { o: owner, n: name, p: number }, token, signal);
|
|
1207
|
+
const nodes = r.data?.repository?.pullRequest?.closingIssuesReferences?.nodes ?? [];
|
|
1208
|
+
return { closesIssues: nodes.map((x) => x.number), linkageSource: "graphql" };
|
|
1209
|
+
} catch {
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
const nums = /* @__PURE__ */ new Set();
|
|
1213
|
+
const re = /\b(?:clos(?:e|es|ed)|fix(?:es|ed)?|resolv(?:e|es|ed))\s+#(\d+)/gi;
|
|
1214
|
+
let m;
|
|
1215
|
+
while ((m = re.exec(body)) !== null) nums.add(parseInt(m[1], 10));
|
|
1216
|
+
return { closesIssues: [...nums], linkageSource: nums.size ? "body-keyword" : "none" };
|
|
1217
|
+
}
|
|
1218
|
+
async function fetchPRScoringFacts(prUrl, token, signal) {
|
|
1219
|
+
const ref = parseGitHubRef(prUrl);
|
|
1220
|
+
if (!ref || ref.kind !== "pull") return null;
|
|
1221
|
+
const { owner, repo, number } = ref;
|
|
1222
|
+
const sig = signal ?? AbortSignal.timeout(1e4);
|
|
1223
|
+
let pr;
|
|
1224
|
+
try {
|
|
1225
|
+
pr = await ghFetch(`/repos/${owner}/${repo}/pulls/${number}`, token, sig);
|
|
1226
|
+
} catch {
|
|
1227
|
+
return null;
|
|
1228
|
+
}
|
|
1229
|
+
let repoMeta = null;
|
|
1230
|
+
try {
|
|
1231
|
+
repoMeta = await ghFetch(`/repos/${owner}/${repo}`, token, sig);
|
|
1232
|
+
} catch {
|
|
1233
|
+
}
|
|
1234
|
+
const contributors = await repoContributorCount(owner, repo, token, sig);
|
|
1235
|
+
const { closesIssues, linkageSource } = await resolveClosingIssues(owner, repo, number, pr.body ?? "", token, sig);
|
|
1236
|
+
return {
|
|
1237
|
+
repo: `${owner}/${repo}`,
|
|
1238
|
+
prNumber: number,
|
|
1239
|
+
prUrl: pr.html_url,
|
|
1240
|
+
merged: pr.merged === true,
|
|
1241
|
+
mergedAt: pr.merged_at ?? null,
|
|
1242
|
+
authorId: pr.user?.id ?? null,
|
|
1243
|
+
authorLogin: pr.user?.login ?? null,
|
|
1244
|
+
mergedById: pr.merged_by?.id ?? null,
|
|
1245
|
+
mergedByLogin: pr.merged_by?.login ?? null,
|
|
1246
|
+
closesIssues,
|
|
1247
|
+
linkageSource,
|
|
1248
|
+
repoStars: repoMeta?.stargazers_count ?? null,
|
|
1249
|
+
repoContributors: contributors ?? null,
|
|
1250
|
+
repoArchived: !!repoMeta?.archived,
|
|
1251
|
+
repoFork: !!repoMeta?.fork,
|
|
1252
|
+
repoPrivate: !!repoMeta?.private,
|
|
1253
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1111
1257
|
var init_github = __esm({
|
|
1112
1258
|
"../../packages/core/src/github.ts"() {
|
|
1113
1259
|
"use strict";
|
|
@@ -1115,6 +1261,8 @@ var init_github = __esm({
|
|
|
1115
1261
|
init_contribution_gate();
|
|
1116
1262
|
TRACTION_TOP_N = 6;
|
|
1117
1263
|
CANDIDATE_PR_PAGE = 50;
|
|
1264
|
+
OPEN_PR_PAGE = 20;
|
|
1265
|
+
TRANSIENT_META_ERROR = /HTTP 403|HTTP 429|rate limit|HTTP 5\d\d|timeout|network|fetch failed/i;
|
|
1118
1266
|
RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
1119
1267
|
RESUME_MIN_SCORE = 0.05;
|
|
1120
1268
|
}
|
|
@@ -2792,6 +2940,20 @@ var init_contribution_classify = __esm({
|
|
|
2792
2940
|
});
|
|
2793
2941
|
|
|
2794
2942
|
// ../../packages/core/src/feeds/contributions.ts
|
|
2943
|
+
function readReqGapMs() {
|
|
2944
|
+
const raw = process.env["CONTRIB_REQ_GAP_MS"];
|
|
2945
|
+
if (raw == null) return DEFAULT_REQ_GAP_MS;
|
|
2946
|
+
const n = Number.parseInt(raw, 10);
|
|
2947
|
+
if (Number.isNaN(n)) return DEFAULT_REQ_GAP_MS;
|
|
2948
|
+
return Math.min(Math.max(n, 0), 1e3);
|
|
2949
|
+
}
|
|
2950
|
+
function readBuildBudgetMs() {
|
|
2951
|
+
const raw = process.env["CONTRIB_BUILD_BUDGET_MS"];
|
|
2952
|
+
if (raw == null) return DEFAULT_BUILD_BUDGET_MS;
|
|
2953
|
+
const n = Number.parseInt(raw, 10);
|
|
2954
|
+
if (Number.isNaN(n)) return DEFAULT_BUILD_BUDGET_MS;
|
|
2955
|
+
return Math.min(Math.max(n, MIN_BUILD_BUDGET_MS), MAX_BUILD_BUDGET_MS);
|
|
2956
|
+
}
|
|
2795
2957
|
function authHeaders2() {
|
|
2796
2958
|
const token = process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
|
|
2797
2959
|
const h = {
|
|
@@ -2812,10 +2974,55 @@ function repoFullNameFromApiUrl2(url) {
|
|
|
2812
2974
|
const m = url.match(/\/repos\/([^/]+)\/([^/]+)\/?$/);
|
|
2813
2975
|
return m ? `${m[1]}/${m[2]}` : null;
|
|
2814
2976
|
}
|
|
2815
|
-
function makeClient(fetchImpl) {
|
|
2977
|
+
function makeClient(fetchImpl, cfg) {
|
|
2978
|
+
const startedAt = cfg.now();
|
|
2979
|
+
let lastRequestAt = 0;
|
|
2980
|
+
let pacedMs = 0;
|
|
2981
|
+
let secondaryHits = 0;
|
|
2982
|
+
let aborted = false;
|
|
2983
|
+
let secondaryAborted = false;
|
|
2984
|
+
let budgetAborted = false;
|
|
2985
|
+
let coreHealthyAtStart = false;
|
|
2986
|
+
async function noteAndMaybeBackOff(res) {
|
|
2987
|
+
if (res.status !== 403) return;
|
|
2988
|
+
const remaining = res.headers.get("x-ratelimit-remaining");
|
|
2989
|
+
const retryAfter = res.headers.get("retry-after");
|
|
2990
|
+
const positiveSecondary = retryAfter != null || remaining != null && remaining !== "0";
|
|
2991
|
+
const isSecondary = positiveSecondary || coreHealthyAtStart;
|
|
2992
|
+
if (!isSecondary) return;
|
|
2993
|
+
secondaryHits++;
|
|
2994
|
+
if (secondaryHits >= 2) {
|
|
2995
|
+
aborted = true;
|
|
2996
|
+
secondaryAborted = true;
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
if (cfg.paceEnabled) {
|
|
3000
|
+
const trimmed = (retryAfter ?? "").trim();
|
|
3001
|
+
const parsed = trimmed.length === 0 ? Number.NaN : Number(trimmed);
|
|
3002
|
+
const sec = Number.isNaN(parsed) ? SECONDARY_BACKOFF_CAP_S : Math.min(Math.max(parsed, 0), SECONDARY_BACKOFF_CAP_S);
|
|
3003
|
+
const remaining2 = Math.max(0, cfg.budgetMs - (cfg.now() - startedAt));
|
|
3004
|
+
await cfg.sleep(Math.min(sec * 1e3, remaining2));
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
2816
3007
|
async function raw(path) {
|
|
3008
|
+
if (aborted) return null;
|
|
3009
|
+
if (cfg.now() - startedAt > cfg.budgetMs) {
|
|
3010
|
+
aborted = true;
|
|
3011
|
+
budgetAborted = true;
|
|
3012
|
+
return null;
|
|
3013
|
+
}
|
|
3014
|
+
if (cfg.paceEnabled && cfg.gapMs > 0) {
|
|
3015
|
+
const wait = cfg.gapMs - (cfg.now() - lastRequestAt);
|
|
3016
|
+
if (wait > 0) {
|
|
3017
|
+
await cfg.sleep(wait);
|
|
3018
|
+
pacedMs += wait;
|
|
3019
|
+
}
|
|
3020
|
+
lastRequestAt = cfg.now();
|
|
3021
|
+
}
|
|
2817
3022
|
try {
|
|
2818
|
-
|
|
3023
|
+
const res = await fetchImpl(`${GITHUB_API2}${path}`, { headers: authHeaders2() });
|
|
3024
|
+
await noteAndMaybeBackOff(res);
|
|
3025
|
+
return res;
|
|
2819
3026
|
} catch {
|
|
2820
3027
|
return null;
|
|
2821
3028
|
}
|
|
@@ -2831,7 +3038,42 @@ function makeClient(fetchImpl) {
|
|
|
2831
3038
|
return null;
|
|
2832
3039
|
}
|
|
2833
3040
|
}
|
|
2834
|
-
|
|
3041
|
+
async function probe(path) {
|
|
3042
|
+
const bound = cfg.probeTimeoutMs;
|
|
3043
|
+
let timer;
|
|
3044
|
+
const fetchP = fetchImpl(`${GITHUB_API2}${path}`, {
|
|
3045
|
+
headers: authHeaders2()
|
|
3046
|
+
}).then(
|
|
3047
|
+
(r) => r,
|
|
3048
|
+
() => null
|
|
3049
|
+
);
|
|
3050
|
+
try {
|
|
3051
|
+
const res = bound == null ? await fetchP : await Promise.race([
|
|
3052
|
+
fetchP,
|
|
3053
|
+
new Promise((resolve) => {
|
|
3054
|
+
timer = setTimeout(() => resolve(null), bound);
|
|
3055
|
+
})
|
|
3056
|
+
]);
|
|
3057
|
+
if (!res || !res.ok) return null;
|
|
3058
|
+
return await res.json();
|
|
3059
|
+
} catch {
|
|
3060
|
+
return null;
|
|
3061
|
+
} finally {
|
|
3062
|
+
if (timer) clearTimeout(timer);
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
function setSecondaryHint(coreHealthy) {
|
|
3066
|
+
coreHealthyAtStart = coreHealthy;
|
|
3067
|
+
}
|
|
3068
|
+
function getStats() {
|
|
3069
|
+
return {
|
|
3070
|
+
pacedMs,
|
|
3071
|
+
secondaryAborted: secondaryAborted ? 1 : 0,
|
|
3072
|
+
budgetAborted: budgetAborted ? 1 : 0,
|
|
3073
|
+
elapsedMs: cfg.now() - startedAt
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
return { raw, json, probe, setSecondaryHint, getStats };
|
|
2835
3077
|
}
|
|
2836
3078
|
async function contributorCount(client, fullName) {
|
|
2837
3079
|
const res = await client.raw(`/repos/${fullName}/contributors?per_page=1&anon=false`);
|
|
@@ -2860,6 +3102,10 @@ ${pr.body ?? ""}`.matchAll(/#(\d+)\b/g)) {
|
|
|
2860
3102
|
}
|
|
2861
3103
|
return refs;
|
|
2862
3104
|
}
|
|
3105
|
+
async function fetchRateLimit(client) {
|
|
3106
|
+
const r = await client.probe("/rate_limit");
|
|
3107
|
+
return r?.resources ?? null;
|
|
3108
|
+
}
|
|
2863
3109
|
async function searchContribIssues(client, queries) {
|
|
2864
3110
|
const byUrl = /* @__PURE__ */ new Map();
|
|
2865
3111
|
for (const q of queries) {
|
|
@@ -2876,8 +3122,21 @@ async function searchContribIssues(client, queries) {
|
|
|
2876
3122
|
);
|
|
2877
3123
|
}
|
|
2878
3124
|
async function aggregateContributions(opts = {}) {
|
|
2879
|
-
const
|
|
3125
|
+
const paceEnabled = opts.paceEnabled ?? !opts.fetchImpl;
|
|
3126
|
+
const client = makeClient(opts.fetchImpl ?? fetchWithTimeout, {
|
|
3127
|
+
paceEnabled,
|
|
3128
|
+
gapMs: readReqGapMs(),
|
|
3129
|
+
budgetMs: readBuildBudgetMs(),
|
|
3130
|
+
sleep: opts.sleepImpl ?? realSleep,
|
|
3131
|
+
now: opts.nowImpl ?? Date.now,
|
|
3132
|
+
// Bound the unguarded probe on the REAL network only; injected-fetch tests get
|
|
3133
|
+
// null so the probe stays deterministic (and its shared spy sleeper untouched).
|
|
3134
|
+
probeTimeoutMs: opts.fetchImpl ? null : PROBE_TIMEOUT_MS
|
|
3135
|
+
});
|
|
2880
3136
|
const queries = opts.queries ?? CONTRIB_SEARCH_QUERIES;
|
|
3137
|
+
const startRl = await fetchRateLimit(client);
|
|
3138
|
+
const coreHealthyAtStart = (startRl?.core?.remaining ?? 0) >= 500;
|
|
3139
|
+
client.setSecondaryHint(coreHealthyAtStart);
|
|
2881
3140
|
const issues = (await searchContribIssues(client, queries)).slice(0, MAX_CONTRIB_ISSUES_SCANNED);
|
|
2882
3141
|
const repoCache = /* @__PURE__ */ new Map();
|
|
2883
3142
|
const contribCache = /* @__PURE__ */ new Map();
|
|
@@ -2904,6 +3163,9 @@ async function aggregateContributions(opts = {}) {
|
|
|
2904
3163
|
const jobs = [];
|
|
2905
3164
|
const seen = /* @__PURE__ */ new Set();
|
|
2906
3165
|
const perRepo = /* @__PURE__ */ new Map();
|
|
3166
|
+
let metaNull = 0;
|
|
3167
|
+
let contribUndefined = 0;
|
|
3168
|
+
let prRefsNull = 0;
|
|
2907
3169
|
for (const issue of issues) {
|
|
2908
3170
|
if (jobs.length >= MAX_CONTRIB_ITEMS) break;
|
|
2909
3171
|
const fullName = repoFullNameFromApiUrl2(issue.repository_url);
|
|
@@ -2914,9 +3176,13 @@ async function aggregateContributions(opts = {}) {
|
|
|
2914
3176
|
if (isAssigned(issue)) continue;
|
|
2915
3177
|
if ((perRepo.get(fullName) ?? 0) >= MAX_BOUNTIES_PER_DISCOVERED_REPO) continue;
|
|
2916
3178
|
const repo = await repoMeta(fullName);
|
|
2917
|
-
if (!repo)
|
|
3179
|
+
if (!repo) {
|
|
3180
|
+
metaNull++;
|
|
3181
|
+
continue;
|
|
3182
|
+
}
|
|
2918
3183
|
const title = decodeEntities(issue.title).trim();
|
|
2919
3184
|
const contributors = await repoContribCount(fullName);
|
|
3185
|
+
if (contributors === void 0) contribUndefined++;
|
|
2920
3186
|
if (!passesContributionGate({
|
|
2921
3187
|
fullName,
|
|
2922
3188
|
stars: repo.stargazers_count,
|
|
@@ -2932,6 +3198,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
2932
3198
|
const labels = labelNames2(issue.labels);
|
|
2933
3199
|
if (looksLikeContentTask({ title, body, labels })) continue;
|
|
2934
3200
|
const prRefs = await repoPRRefs(fullName);
|
|
3201
|
+
if (prRefs === null) prRefsNull++;
|
|
2935
3202
|
if (prRefs && prRefs.has(issue.number)) continue;
|
|
2936
3203
|
const openPRsAtDiscovery = prRefs ? 0 : void 0;
|
|
2937
3204
|
const tags = normalize(
|
|
@@ -2971,9 +3238,19 @@ async function aggregateContributions(opts = {}) {
|
|
|
2971
3238
|
raw: issue
|
|
2972
3239
|
});
|
|
2973
3240
|
}
|
|
3241
|
+
if (!opts.fetchImpl) {
|
|
3242
|
+
const rl = await fetchRateLimit(client);
|
|
3243
|
+
const core = rl?.core ? `${rl.core.remaining}/${rl.core.limit}` : "n/a";
|
|
3244
|
+
const search = rl?.search ? `${rl.search.remaining}/${rl.search.limit}` : "n/a";
|
|
3245
|
+
const noToken = !(process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"]);
|
|
3246
|
+
const { pacedMs, secondaryAborted, budgetAborted, elapsedMs } = client.getStats();
|
|
3247
|
+
console.info(
|
|
3248
|
+
`[contribute] build metrics \u2014 scanned=${issues.length} reposDistinct=${repoCache.size} emitted=${jobs.length} metaNull=${metaNull} contribUndefined=${contribUndefined} prRefsNull=${prRefsNull} paced=${pacedMs} secondaryAborted=${secondaryAborted} budgetAborted=${budgetAborted} core=${core} search=${search} elapsed=${elapsedMs}` + (noToken ? " (NO TOKEN \u2192 60/hr)" : "")
|
|
3249
|
+
);
|
|
3250
|
+
}
|
|
2974
3251
|
return jobs;
|
|
2975
3252
|
}
|
|
2976
|
-
var GITHUB_API2, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2, MAX_CONTRIB_ITEMS, MAX_CONTRIB_ISSUES_SCANNED;
|
|
3253
|
+
var GITHUB_API2, DEFAULT_REQ_GAP_MS, SECONDARY_BACKOFF_CAP_S, DEFAULT_BUILD_BUDGET_MS, MIN_BUILD_BUDGET_MS, MAX_BUILD_BUDGET_MS, PROBE_TIMEOUT_MS, realSleep, CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2, MAX_CONTRIB_ITEMS, MAX_CONTRIB_ISSUES_SCANNED;
|
|
2977
3254
|
var init_contributions = __esm({
|
|
2978
3255
|
"../../packages/core/src/feeds/contributions.ts"() {
|
|
2979
3256
|
"use strict";
|
|
@@ -2985,15 +3262,32 @@ var init_contributions = __esm({
|
|
|
2985
3262
|
init_github_bounties();
|
|
2986
3263
|
init_http();
|
|
2987
3264
|
GITHUB_API2 = "https://api.github.com";
|
|
2988
|
-
|
|
3265
|
+
DEFAULT_REQ_GAP_MS = 75;
|
|
3266
|
+
SECONDARY_BACKOFF_CAP_S = 30;
|
|
3267
|
+
DEFAULT_BUILD_BUDGET_MS = 9e4;
|
|
3268
|
+
MIN_BUILD_BUDGET_MS = 1e4;
|
|
3269
|
+
MAX_BUILD_BUDGET_MS = 9e4;
|
|
3270
|
+
PROBE_TIMEOUT_MS = 3e3;
|
|
3271
|
+
realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
3272
|
+
CONTRIB_LABEL_QUERIES = [
|
|
2989
3273
|
'label:"good first issue" type:issue state:open',
|
|
2990
|
-
'label:"help wanted" type:issue state:open',
|
|
2991
3274
|
'label:"good-first-issue" type:issue state:open',
|
|
2992
|
-
'label:"help
|
|
3275
|
+
'label:"help wanted" type:issue state:open',
|
|
3276
|
+
'label:"help-wanted" type:issue state:open',
|
|
3277
|
+
'label:"up-for-grabs" type:issue state:open'
|
|
3278
|
+
];
|
|
3279
|
+
CONTRIB_LANGUAGE_QUERIES = [
|
|
3280
|
+
...["rust", "go", "python", "c++", "ruby"].map(
|
|
3281
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
3282
|
+
),
|
|
3283
|
+
...["rust", "go"].map(
|
|
3284
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
3285
|
+
)
|
|
2993
3286
|
];
|
|
3287
|
+
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
2994
3288
|
SEARCH_PER_PAGE2 = 100;
|
|
2995
3289
|
MAX_CONTRIB_ITEMS = 150;
|
|
2996
|
-
MAX_CONTRIB_ISSUES_SCANNED =
|
|
3290
|
+
MAX_CONTRIB_ISSUES_SCANNED = 600;
|
|
2997
3291
|
}
|
|
2998
3292
|
});
|
|
2999
3293
|
|
|
@@ -3091,6 +3385,36 @@ var init_indexer = __esm({
|
|
|
3091
3385
|
}
|
|
3092
3386
|
});
|
|
3093
3387
|
|
|
3388
|
+
// ../../packages/core/src/credit.ts
|
|
3389
|
+
function verifyClaimCredit(claim, facts) {
|
|
3390
|
+
const reasons = [];
|
|
3391
|
+
const fail = (code, message) => reasons.push({ code, message });
|
|
3392
|
+
const norm = (r) => r.trim().toLowerCase();
|
|
3393
|
+
if (norm(facts.repo) !== norm(claim.repo))
|
|
3394
|
+
fail("repo-mismatch", `PR is in ${facts.repo}, claim is against ${claim.repo}`);
|
|
3395
|
+
if (!facts.merged) fail("not-merged", `PR #${facts.prNumber} is not merged`);
|
|
3396
|
+
if (facts.authorId == null || facts.authorId !== claim.claimantId)
|
|
3397
|
+
fail("author-mismatch", `PR author id ${facts.authorId} !== claimant id ${claim.claimantId}`);
|
|
3398
|
+
if (facts.merged && facts.mergedById != null && facts.authorId != null && facts.mergedById === facts.authorId)
|
|
3399
|
+
fail("self-merged", `PR was merged by its own author (id ${facts.authorId})`);
|
|
3400
|
+
if (claim.claimedIssueNumber != null) {
|
|
3401
|
+
if (facts.closesIssues.length === 0)
|
|
3402
|
+
fail("issue-linkage-missing", `PR closes no issue; claim names #${claim.claimedIssueNumber}`);
|
|
3403
|
+
else if (!facts.closesIssues.includes(claim.claimedIssueNumber))
|
|
3404
|
+
fail(
|
|
3405
|
+
"issue-linkage-mismatch",
|
|
3406
|
+
`PR closes ${facts.closesIssues.map((n) => "#" + n).join(", ")}; claim names #${claim.claimedIssueNumber}`
|
|
3407
|
+
);
|
|
3408
|
+
}
|
|
3409
|
+
if (reasons.length === 0) reasons.push({ code: "ok", message: "all credit predicates hold" });
|
|
3410
|
+
return { ok: reasons.every((r) => r.code === "ok"), reasons };
|
|
3411
|
+
}
|
|
3412
|
+
var init_credit = __esm({
|
|
3413
|
+
"../../packages/core/src/credit.ts"() {
|
|
3414
|
+
"use strict";
|
|
3415
|
+
}
|
|
3416
|
+
});
|
|
3417
|
+
|
|
3094
3418
|
// ../../packages/core/src/intro.ts
|
|
3095
3419
|
function buildIntroPayload(input) {
|
|
3096
3420
|
const payload = {
|
|
@@ -6436,13 +6760,15 @@ function deriveLegibleProfile(credential, recency, traction, seniorityBand) {
|
|
|
6436
6760
|
daysAgo = Math.max(0, Math.round(ageDays2));
|
|
6437
6761
|
recencyBadge = { lastMergedAt: mostRecent, state: ageDays2 <= thresholdDays ? "live" : "dormant" };
|
|
6438
6762
|
}
|
|
6439
|
-
const
|
|
6763
|
+
const exactOrgCount = typeof credential.distinctOrgs === "number" && credential.distinctOrgs > 0;
|
|
6764
|
+
const orgCount = exactOrgCount ? credential.distinctOrgs : Object.values(domains).reduce((m, d) => Math.max(m, d.distinctOrgs), 0);
|
|
6440
6765
|
let proofSentence;
|
|
6441
6766
|
if (!ok) {
|
|
6442
6767
|
proofSentence = "Contribution credential unavailable \u2014 could not verify.";
|
|
6443
6768
|
} else {
|
|
6444
6769
|
const prs = credential.qualifyingTotal;
|
|
6445
|
-
|
|
6770
|
+
const orgPhrase = exactOrgCount ? `${orgCount}` : `at least ${orgCount}`;
|
|
6771
|
+
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
6772
|
if (daysAgo !== void 0) s += ` \u2014 most recent ${daysAgo}d ago`;
|
|
6447
6773
|
proofSentence = `${s}.`;
|
|
6448
6774
|
}
|
|
@@ -6680,7 +7006,9 @@ __export(src_exports, {
|
|
|
6680
7006
|
expandWeighted: () => expandWeighted,
|
|
6681
7007
|
extractSkillTags: () => extractSkillTags,
|
|
6682
7008
|
fetchGitHubProfile: () => fetchGitHubProfile,
|
|
7009
|
+
fetchOpenExternalPRs: () => fetchOpenExternalPRs,
|
|
6683
7010
|
fetchOwnedRepoTraction: () => fetchOwnedRepoTraction,
|
|
7011
|
+
fetchPRScoringFacts: () => fetchPRScoringFacts,
|
|
6684
7012
|
fetchRepoRecency: () => fetchRepoRecency,
|
|
6685
7013
|
flattenTiers: () => flattenTiers,
|
|
6686
7014
|
funnelCounts: () => funnelCounts,
|
|
@@ -6711,6 +7039,7 @@ __export(src_exports, {
|
|
|
6711
7039
|
opire: () => opire,
|
|
6712
7040
|
opportunityShortToken: () => opportunityShortToken,
|
|
6713
7041
|
pageMatches: () => pageMatches,
|
|
7042
|
+
parseGitHubRef: () => parseGitHubRef,
|
|
6714
7043
|
passesContributionGate: () => passesContributionGate,
|
|
6715
7044
|
passesMaturityGate: () => passesMaturityGate,
|
|
6716
7045
|
personCardToJob: () => personCardToJob,
|
|
@@ -6727,6 +7056,7 @@ __export(src_exports, {
|
|
|
6727
7056
|
validateGraph: () => validateGraph,
|
|
6728
7057
|
validateIntroPayload: () => validateIntroPayload,
|
|
6729
7058
|
validateTargetContact: () => validateTargetContact,
|
|
7059
|
+
verifyClaimCredit: () => verifyClaimCredit,
|
|
6730
7060
|
workable: () => workable,
|
|
6731
7061
|
wwr: () => wwr
|
|
6732
7062
|
});
|
|
@@ -6741,6 +7071,7 @@ var init_src = __esm({
|
|
|
6741
7071
|
init_indexer();
|
|
6742
7072
|
init_partners();
|
|
6743
7073
|
init_github();
|
|
7074
|
+
init_credit();
|
|
6744
7075
|
init_intro();
|
|
6745
7076
|
init_directoryThreshold();
|
|
6746
7077
|
init_chatCrypto();
|
|
@@ -6759,9 +7090,9 @@ var init_keytar = __esm({
|
|
|
6759
7090
|
}
|
|
6760
7091
|
});
|
|
6761
7092
|
|
|
6762
|
-
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
7093
|
+
// node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/claim-frictionless/node_modules/keytar/build/Release/keytar.node
|
|
6763
7094
|
var require_keytar = __commonJS({
|
|
6764
|
-
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
7095
|
+
"node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/claim-frictionless/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
6765
7096
|
"use strict";
|
|
6766
7097
|
init_keytar();
|
|
6767
7098
|
try {
|