terminalhire 0.26.0 → 0.26.2

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.
@@ -945,6 +945,187 @@ var init_rigor = __esm({
945
945
  }
946
946
  });
947
947
 
948
+ // ../../packages/core/src/gh-governor.ts
949
+ function readReqGapMs() {
950
+ const raw = process.env["CONTRIB_REQ_GAP_MS"];
951
+ if (raw == null) return DEFAULT_REQ_GAP_MS;
952
+ const n = Number.parseInt(raw, 10);
953
+ if (Number.isNaN(n)) return DEFAULT_REQ_GAP_MS;
954
+ return Math.min(Math.max(n, 0), 1e3);
955
+ }
956
+ function readBuildBudgetMs() {
957
+ const raw = process.env["CONTRIB_BUILD_BUDGET_MS"];
958
+ if (raw == null) return DEFAULT_BUILD_BUDGET_MS;
959
+ const n = Number.parseInt(raw, 10);
960
+ if (Number.isNaN(n)) return DEFAULT_BUILD_BUDGET_MS;
961
+ return Math.min(Math.max(n, MIN_BUILD_BUDGET_MS), MAX_BUILD_BUDGET_MS);
962
+ }
963
+ function makeDefaultGovernorConfig(o) {
964
+ return {
965
+ paceEnabled: o.paceEnabled,
966
+ gapMs: readReqGapMs(),
967
+ budgetMs: readBuildBudgetMs(),
968
+ sleep: o.sleep ?? realSleep,
969
+ now: o.now ?? Date.now,
970
+ probeTimeoutMs: o.probeTimeoutMs ?? (o.paceEnabled ? PROBE_TIMEOUT_MS : null)
971
+ };
972
+ }
973
+ function makeGitHubGovernor(fetchImpl, cfg) {
974
+ const startedAt = cfg.now();
975
+ let lastRequestAt = 0;
976
+ let pacedMs = 0;
977
+ let secondaryHits = 0;
978
+ let aborted = false;
979
+ let secondaryAborted = false;
980
+ let budgetAborted = false;
981
+ let gqlCost = 0;
982
+ let gqlRemaining = null;
983
+ let coreHealthyAtStart = false;
984
+ async function noteAndMaybeBackOff(res) {
985
+ if (res.status !== 403) return;
986
+ const remaining = res.headers.get("x-ratelimit-remaining");
987
+ const retryAfter = res.headers.get("retry-after");
988
+ const positiveSecondary = retryAfter != null || remaining != null && remaining !== "0";
989
+ const isSecondary = positiveSecondary || coreHealthyAtStart;
990
+ if (!isSecondary) return;
991
+ await recordSecondaryStrike(retryAfter);
992
+ }
993
+ async function recordSecondaryStrike(retryAfter) {
994
+ secondaryHits++;
995
+ if (secondaryHits >= 2) {
996
+ aborted = true;
997
+ secondaryAborted = true;
998
+ return;
999
+ }
1000
+ if (cfg.paceEnabled) {
1001
+ const trimmed = (retryAfter ?? "").trim();
1002
+ const parsed = trimmed.length === 0 ? Number.NaN : Number(trimmed);
1003
+ const sec = Number.isNaN(parsed) ? SECONDARY_BACKOFF_CAP_S : Math.min(Math.max(parsed, 0), SECONDARY_BACKOFF_CAP_S);
1004
+ const remainingBudget = Math.max(0, cfg.budgetMs - (cfg.now() - startedAt));
1005
+ await cfg.sleep(Math.min(sec * 1e3, remainingBudget));
1006
+ }
1007
+ }
1008
+ async function noteGraphQLAndMaybeBackOff(res, body) {
1009
+ const b = body ?? {};
1010
+ const rl = b.data?.rateLimit;
1011
+ if (rl) {
1012
+ if (typeof rl.cost === "number") gqlCost += rl.cost;
1013
+ if (typeof rl.remaining === "number") gqlRemaining = rl.remaining;
1014
+ }
1015
+ const remainingHdr = res.headers?.get("x-ratelimit-remaining") ?? null;
1016
+ const retryAfter = res.headers?.get("retry-after") ?? null;
1017
+ const headerRate = retryAfter != null || remainingHdr === "0";
1018
+ const errs = Array.isArray(b.errors) ? b.errors : [];
1019
+ const bodyRate = errs.some((e) => e?.type === "RATE_LIMITED" || /rate limit/i.test(String(e?.message ?? ""))) || typeof rl?.remaining === "number" && rl.remaining <= 0;
1020
+ if (headerRate || bodyRate) await recordSecondaryStrike(retryAfter);
1021
+ }
1022
+ async function preflight() {
1023
+ if (aborted) return false;
1024
+ if (cfg.now() - startedAt >= cfg.budgetMs) {
1025
+ aborted = true;
1026
+ budgetAborted = true;
1027
+ return false;
1028
+ }
1029
+ if (cfg.paceEnabled && cfg.gapMs > 0) {
1030
+ const wait = cfg.gapMs - (cfg.now() - lastRequestAt);
1031
+ if (wait > 0) {
1032
+ await cfg.sleep(wait);
1033
+ pacedMs += wait;
1034
+ if (cfg.now() - startedAt >= cfg.budgetMs) {
1035
+ aborted = true;
1036
+ budgetAborted = true;
1037
+ return false;
1038
+ }
1039
+ }
1040
+ lastRequestAt = cfg.now();
1041
+ }
1042
+ return true;
1043
+ }
1044
+ async function get(url, init) {
1045
+ if (!await preflight()) return null;
1046
+ try {
1047
+ const res = await fetchImpl(url, init);
1048
+ await noteAndMaybeBackOff(res);
1049
+ return res;
1050
+ } catch {
1051
+ return null;
1052
+ }
1053
+ }
1054
+ async function graphql(url, init) {
1055
+ if (!await preflight()) return null;
1056
+ let res;
1057
+ try {
1058
+ res = await fetchImpl(url, init);
1059
+ } catch {
1060
+ return null;
1061
+ }
1062
+ let body;
1063
+ try {
1064
+ body = await res.json();
1065
+ } catch {
1066
+ return null;
1067
+ }
1068
+ await noteGraphQLAndMaybeBackOff(res, body);
1069
+ if (!res.ok) return null;
1070
+ return body;
1071
+ }
1072
+ async function probe(url, init) {
1073
+ const bound = cfg.probeTimeoutMs;
1074
+ let timer;
1075
+ const fetchP = fetchImpl(url, init).then(
1076
+ (r) => r,
1077
+ () => null
1078
+ );
1079
+ try {
1080
+ const res = bound == null ? await fetchP : await Promise.race([
1081
+ fetchP,
1082
+ new Promise((resolve) => {
1083
+ timer = setTimeout(() => resolve(null), bound);
1084
+ })
1085
+ ]);
1086
+ if (!res || !res.ok) return null;
1087
+ return await res.json();
1088
+ } catch {
1089
+ return null;
1090
+ } finally {
1091
+ if (timer) clearTimeout(timer);
1092
+ }
1093
+ }
1094
+ function setSecondaryHint(coreHealthy) {
1095
+ coreHealthyAtStart = coreHealthy;
1096
+ }
1097
+ function getStats() {
1098
+ return {
1099
+ pacedMs,
1100
+ secondaryAborted: secondaryAborted ? 1 : 0,
1101
+ budgetAborted: budgetAborted ? 1 : 0,
1102
+ elapsedMs: cfg.now() - startedAt,
1103
+ gqlCost,
1104
+ gqlRemaining
1105
+ };
1106
+ }
1107
+ function tripped() {
1108
+ return secondaryAborted;
1109
+ }
1110
+ function budgetExhausted() {
1111
+ return budgetAborted || cfg.now() - startedAt >= cfg.budgetMs;
1112
+ }
1113
+ return { get, graphql, probe, setSecondaryHint, getStats, tripped, budgetExhausted };
1114
+ }
1115
+ var DEFAULT_REQ_GAP_MS, SECONDARY_BACKOFF_CAP_S, DEFAULT_BUILD_BUDGET_MS, MIN_BUILD_BUDGET_MS, MAX_BUILD_BUDGET_MS, PROBE_TIMEOUT_MS, realSleep;
1116
+ var init_gh_governor = __esm({
1117
+ "../../packages/core/src/gh-governor.ts"() {
1118
+ "use strict";
1119
+ DEFAULT_REQ_GAP_MS = 75;
1120
+ SECONDARY_BACKOFF_CAP_S = 30;
1121
+ DEFAULT_BUILD_BUDGET_MS = 9e4;
1122
+ MIN_BUILD_BUDGET_MS = 1e4;
1123
+ MAX_BUILD_BUDGET_MS = 9e4;
1124
+ PROBE_TIMEOUT_MS = 3e3;
1125
+ realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
1126
+ }
1127
+ });
1128
+
948
1129
  // ../../packages/core/src/github.ts
949
1130
  function ghHeaders(token) {
950
1131
  const headers = {
@@ -1425,11 +1606,9 @@ async function fetchRepoReceptivity(fullName, opts = {}) {
1425
1606
  const doFetch = opts.fetchImpl ?? fetch;
1426
1607
  const now = opts.now ?? Date.now();
1427
1608
  try {
1428
- const res = await doFetch(
1429
- `https://api.github.com/repos/${fullName}/pulls?state=closed&per_page=50&sort=updated&direction=desc`,
1430
- { headers: ghHeaders(opts.token) }
1431
- );
1432
- if (!res.ok) return null;
1609
+ const url = `https://api.github.com/repos/${fullName}/pulls?state=closed&per_page=50&sort=updated&direction=desc`;
1610
+ const res = opts.governor ? await opts.governor.get(url, { headers: ghHeaders(opts.token) }) : await doFetch(url, { headers: ghHeaders(opts.token) });
1611
+ if (!res || !res.ok) return null;
1433
1612
  const prs = await res.json();
1434
1613
  if (!Array.isArray(prs)) return null;
1435
1614
  const external = prs.filter(isExternalAuthor);
@@ -1514,25 +1693,34 @@ function parseGitHubRef(url) {
1514
1693
  if (!m) return null;
1515
1694
  return { owner: m[1], repo: m[2], number: parseInt(m[4], 10), kind: m[3] === "pull" ? "pull" : "issue" };
1516
1695
  }
1517
- async function ghGraphQL(query, variables, token, signal) {
1518
- const res = await fetch("https://api.github.com/graphql", {
1696
+ async function ghGraphQL(query, variables, token, signal, governor) {
1697
+ const init = {
1519
1698
  method: "POST",
1520
1699
  headers: { ...ghHeaders(token), "Content-Type": "application/json" },
1521
1700
  body: JSON.stringify({ query, variables }),
1522
1701
  signal
1523
- });
1702
+ };
1703
+ if (governor) {
1704
+ const json2 = await governor.graphql(GITHUB_GRAPHQL_URL, init);
1705
+ if (json2 === null) return null;
1706
+ if (json2.errors?.length) throw new Error("GitHub GraphQL errors: " + JSON.stringify(json2.errors));
1707
+ return json2;
1708
+ }
1709
+ const res = await fetch(GITHUB_GRAPHQL_URL, init);
1524
1710
  if (!res.ok) throw new Error(`GitHub GraphQL: HTTP ${res.status}`);
1525
1711
  const json = await res.json();
1526
1712
  if (json.errors?.length) throw new Error("GitHub GraphQL errors: " + JSON.stringify(json.errors));
1527
1713
  return json;
1528
1714
  }
1529
- async function resolveClosingIssues(owner, name, number, body, token, signal) {
1715
+ async function resolveClosingIssues(owner, name, number, body, token, signal, governor) {
1530
1716
  if (token) {
1531
1717
  try {
1532
- const q = `query($o:String!,$n:String!,$p:Int!){repository(owner:$o,name:$n){pullRequest(number:$p){closingIssuesReferences(first:20){nodes{number}}}}}`;
1533
- const r = await ghGraphQL(q, { o: owner, n: name, p: number }, token, signal);
1534
- const nodes = r.data?.repository?.pullRequest?.closingIssuesReferences?.nodes ?? [];
1535
- return { closesIssues: nodes.map((x) => x.number), linkageSource: "graphql" };
1718
+ const q = `query($o:String!,$n:String!,$p:Int!){repository(owner:$o,name:$n){pullRequest(number:$p){closingIssuesReferences(first:20){nodes{number}}}}rateLimit{cost remaining}}`;
1719
+ const r = await ghGraphQL(q, { o: owner, n: name, p: number }, token, signal, governor);
1720
+ if (r) {
1721
+ const nodes = r.data?.repository?.pullRequest?.closingIssuesReferences?.nodes ?? [];
1722
+ return { closesIssues: nodes.map((x) => x.number), linkageSource: "graphql" };
1723
+ }
1536
1724
  } catch {
1537
1725
  }
1538
1726
  }
@@ -1542,11 +1730,19 @@ async function resolveClosingIssues(owner, name, number, body, token, signal) {
1542
1730
  while ((m = re.exec(body)) !== null) nums.add(parseInt(m[1], 10));
1543
1731
  return { closesIssues: [...nums], linkageSource: nums.size ? "body-keyword" : "none" };
1544
1732
  }
1545
- async function fetchPRScoringFacts(prUrl, token, signal) {
1733
+ function makeScoringGovernor(governor) {
1734
+ return governor ?? makeGitHubGovernor(
1735
+ ((url, init) => fetch(url, init)),
1736
+ makeDefaultGovernorConfig({ paceEnabled: false })
1737
+ );
1738
+ }
1739
+ async function fetchPRScoringFacts(prUrl, token, signal, governor) {
1546
1740
  const ref = parseGitHubRef(prUrl);
1547
1741
  if (!ref || ref.kind !== "pull") return null;
1548
1742
  const { owner, repo, number } = ref;
1549
1743
  const sig = signal ?? AbortSignal.timeout(1e4);
1744
+ const gov = makeScoringGovernor(governor);
1745
+ if (gov.tripped() || gov.budgetExhausted()) return null;
1550
1746
  let pr;
1551
1747
  try {
1552
1748
  pr = await ghFetch(`/repos/${owner}/${repo}/pulls/${number}`, token, sig);
@@ -1554,22 +1750,26 @@ async function fetchPRScoringFacts(prUrl, token, signal) {
1554
1750
  return null;
1555
1751
  }
1556
1752
  let repoMeta = null;
1557
- try {
1558
- repoMeta = await ghFetch(`/repos/${owner}/${repo}`, token, sig);
1559
- } catch {
1753
+ if (!gov.tripped() && !gov.budgetExhausted()) {
1754
+ try {
1755
+ repoMeta = await ghFetch(`/repos/${owner}/${repo}`, token, sig);
1756
+ } catch {
1757
+ }
1560
1758
  }
1561
- const contributors = await repoContributorCount(owner, repo, token, sig);
1562
- const { closesIssues, linkageSource } = await resolveClosingIssues(owner, repo, number, pr.body ?? "", token, sig);
1759
+ const contributors = gov.tripped() || gov.budgetExhausted() ? null : await repoContributorCount(owner, repo, token, sig);
1760
+ const { closesIssues, linkageSource } = await resolveClosingIssues(owner, repo, number, pr.body ?? "", token, sig, gov);
1563
1761
  let reviewerAssociations;
1564
- try {
1565
- const reviews = await ghFetch(
1566
- `/repos/${owner}/${repo}/pulls/${number}/reviews?per_page=100`,
1567
- token,
1568
- sig
1569
- );
1570
- reviewerAssociations = reviews.map((r) => r.author_association);
1571
- } catch {
1572
- reviewerAssociations = void 0;
1762
+ if (!gov.tripped() && !gov.budgetExhausted()) {
1763
+ try {
1764
+ const reviews = await ghFetch(
1765
+ `/repos/${owner}/${repo}/pulls/${number}/reviews?per_page=100`,
1766
+ token,
1767
+ sig
1768
+ );
1769
+ reviewerAssociations = reviews.map((r) => r.author_association);
1770
+ } catch {
1771
+ reviewerAssociations = void 0;
1772
+ }
1573
1773
  }
1574
1774
  return {
1575
1775
  repo: `${owner}/${repo}`,
@@ -1596,7 +1796,7 @@ async function fetchPRScoringFacts(prUrl, token, signal) {
1596
1796
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
1597
1797
  };
1598
1798
  }
1599
- var TRACTION_TOP_N, MAINTAINER_ENRICH_MAX, CANDIDATE_PR_PAGE, MAX_ENRICH_PRS, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE, RECEPTIVITY_RECENCY_DAYS, RECEPTIVITY_RECENCY_FLOOR;
1799
+ var TRACTION_TOP_N, MAINTAINER_ENRICH_MAX, CANDIDATE_PR_PAGE, MAX_ENRICH_PRS, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE, RECEPTIVITY_RECENCY_DAYS, RECEPTIVITY_RECENCY_FLOOR, GITHUB_GRAPHQL_URL;
1600
1800
  var init_github = __esm({
1601
1801
  "../../packages/core/src/github.ts"() {
1602
1802
  "use strict";
@@ -1604,6 +1804,7 @@ var init_github = __esm({
1604
1804
  init_contribution_gate();
1605
1805
  init_contribution_gate();
1606
1806
  init_rigor();
1807
+ init_gh_governor();
1607
1808
  TRACTION_TOP_N = 6;
1608
1809
  MAINTAINER_ENRICH_MAX = 25;
1609
1810
  CANDIDATE_PR_PAGE = 50;
@@ -1614,6 +1815,7 @@ var init_github = __esm({
1614
1815
  RESUME_MIN_SCORE = 0.05;
1615
1816
  RECEPTIVITY_RECENCY_DAYS = 180;
1616
1817
  RECEPTIVITY_RECENCY_FLOOR = 0.1;
1818
+ GITHUB_GRAPHQL_URL = "https://api.github.com/graphql";
1617
1819
  }
1618
1820
  });
1619
1821
 
@@ -1694,34 +1896,45 @@ function mergeSoftCoverage(covMap, softTags, cap) {
1694
1896
  }
1695
1897
  return covMap;
1696
1898
  }
1899
+ function tagKernel(job, ctx) {
1900
+ const { expanded, covMap, maxDevScore, skillTags } = ctx;
1901
+ const details = [];
1902
+ let jobMatchScore = 0;
1903
+ let jobMaxScore = 0;
1904
+ const devCovByTag = /* @__PURE__ */ new Map();
1905
+ for (const tag of job.tags) {
1906
+ const w = backgroundIdf(tag);
1907
+ jobMaxScore += w;
1908
+ const covHit = covMap.get(tag);
1909
+ if (covHit) jobMatchScore += w * Math.pow(covHit.weight, SHARPEN);
1910
+ const fpHit = expanded.get(tag);
1911
+ if (fpHit) {
1912
+ const credit = Math.pow(fpHit.weight, SHARPEN);
1913
+ details.push({ tag, weight: fpHit.weight, via: fpHit.via });
1914
+ if (credit > (devCovByTag.get(fpHit.via) ?? 0)) devCovByTag.set(fpHit.via, credit);
1915
+ }
1916
+ }
1917
+ let devScore = 0;
1918
+ for (const t of skillTags) devScore += backgroundIdf(t) * (devCovByTag.get(t) ?? 0);
1919
+ const devCov = maxDevScore > 0 ? Math.min(1, devScore / maxDevScore) : 0;
1920
+ const jobCov = jobMaxScore > 0 ? Math.min(1, jobMatchScore / jobMaxScore) : 0;
1921
+ return { tagComponent: harmonicMean(devCov, jobCov), details };
1922
+ }
1923
+ function relevanceScore(fp, job, softTags = []) {
1924
+ const expanded = expandWeighted(fp.skillTags);
1925
+ const covMap = softTags.length > 0 ? mergeSoftCoverage(new Map(expanded), softTags, INTEREST_CAP) : expanded;
1926
+ const maxDevScore = fp.skillTags.reduce((acc, t) => acc + backgroundIdf(t), 0);
1927
+ return tagKernel(job, { expanded, covMap, maxDevScore, skillTags: fp.skillTags }).tagComponent;
1928
+ }
1697
1929
  function match(fp, jobs, limit = 5, now = Date.now(), opts = {}) {
1698
1930
  const idfOf = backgroundIdf;
1699
1931
  const expanded = expandWeighted(fp.skillTags);
1700
1932
  const covMap = opts.softTags && opts.softTags.length > 0 ? mergeSoftCoverage(new Map(expanded), opts.softTags, INTEREST_CAP) : expanded;
1701
1933
  const maxDevScore = fp.skillTags.reduce((acc, t) => acc + idfOf(t), 0);
1934
+ const ctx = { expanded, covMap, maxDevScore, skillTags: fp.skillTags };
1702
1935
  const candidates = jobs.filter((j) => passesFilters(fp, j));
1703
1936
  const scored = candidates.map((job) => {
1704
- const details = [];
1705
- let jobMatchScore = 0;
1706
- let jobMaxScore = 0;
1707
- const devCovByTag = /* @__PURE__ */ new Map();
1708
- for (const tag of job.tags) {
1709
- const w = idfOf(tag);
1710
- jobMaxScore += w;
1711
- const covHit = covMap.get(tag);
1712
- if (covHit) jobMatchScore += w * Math.pow(covHit.weight, SHARPEN);
1713
- const fpHit = expanded.get(tag);
1714
- if (fpHit) {
1715
- const credit = Math.pow(fpHit.weight, SHARPEN);
1716
- details.push({ tag, weight: fpHit.weight, via: fpHit.via });
1717
- if (credit > (devCovByTag.get(fpHit.via) ?? 0)) devCovByTag.set(fpHit.via, credit);
1718
- }
1719
- }
1720
- let devScore = 0;
1721
- for (const t of fp.skillTags) devScore += idfOf(t) * (devCovByTag.get(t) ?? 0);
1722
- const devCov = maxDevScore > 0 ? Math.min(1, devScore / maxDevScore) : 0;
1723
- const jobCov = jobMaxScore > 0 ? Math.min(1, jobMatchScore / jobMaxScore) : 0;
1724
- const tagComponent = harmonicMean(devCov, jobCov);
1937
+ const { tagComponent, details } = tagKernel(job, ctx);
1725
1938
  if (tagComponent === 0) return null;
1726
1939
  const coreTags = job.coreTags ?? coreTagsFromTitle(job.title);
1727
1940
  let coreComponent = tagComponent;
@@ -3256,6 +3469,7 @@ function hasContentSignal(title, body, labels) {
3256
3469
  ${body}`;
3257
3470
  if (CONTENT_ADD_RE.test(text)) return true;
3258
3471
  if (ADD_TO_CORPUS_RE.test(text)) return true;
3472
+ if (NUMBERED_SEED_RE.test(title)) return true;
3259
3473
  if (TRANSLATE_RE.test(text)) return true;
3260
3474
  if (TYPO_RE.test(text)) return true;
3261
3475
  return false;
@@ -3271,7 +3485,7 @@ function classifyContributionKind(input) {
3271
3485
  function looksLikeContentTask(input) {
3272
3486
  return classifyContributionKind(input) === "content";
3273
3487
  }
3274
- var CONTENT_LABEL_RE, CODE_LABEL_RE, CODE_TERM_RE, CODE_EXCEPTION_RE, CODE_FENCE_RE, FILE_PATH_RE, CONTENT_ADD_RE, ADD_TO_CORPUS_RE, TRANSLATE_RE, TYPO_RE;
3488
+ var CONTENT_LABEL_RE, CODE_LABEL_RE, CODE_TERM_RE, CODE_EXCEPTION_RE, CODE_FENCE_RE, FILE_PATH_RE, CONTENT_NOUN_STRONG, CONTENT_NOUN_BROAD, CONTENT_ADD_RE, NUMBERED_SEED_RE, ADD_TO_CORPUS_RE, TRANSLATE_RE, TYPO_RE;
3275
3489
  var init_contribution_classify = __esm({
3276
3490
  "../../packages/core/src/feeds/contribution-classify.ts"() {
3277
3491
  "use strict";
@@ -3281,7 +3495,16 @@ var init_contribution_classify = __esm({
3281
3495
  CODE_EXCEPTION_RE = /exception|stacktrace|segfault|traceback/i;
3282
3496
  CODE_FENCE_RE = /```|(?:^|\n)\s{4,}\S/;
3283
3497
  FILE_PATH_RE = /\b[\w./-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|java|kt|scala|c|cc|cpp|cxx|h|hpp|cs|php|swift|m|mm|sh|bash|zsh|sql|graphql|proto|css|scss|sass|less|vue|svelte|toml|ini|gradle|dockerfile)\b/i;
3284
- CONTENT_ADD_RE = /\badd(?:ing|s)?\s+(?:\w+\s+){0,4}?(?:proverbs?|words?|phrases?|sayings?|quotes?|quotations?|translations?|entry|entries|definitions?|terms?|idioms?|synonyms?|antonyms?|acronyms?|abbreviations?)\b/i;
3498
+ CONTENT_NOUN_STRONG = String.raw`proverbs?|words?|phrases?|sayings?|quotes?|quotations?|translations?|entry|entries|definitions?|terms?|idioms?|synonyms?|antonyms?|acronyms?|abbreviations?`;
3499
+ CONTENT_NOUN_BROAD = String.raw`trivia\s+questions?|grammar\s+points?|trivia|facts?|quiz(?:zes)?|flash\s?cards?|vocab(?:ulary)?|lessons?|kanji`;
3500
+ CONTENT_ADD_RE = new RegExp(
3501
+ String.raw`\badd(?:ing|s)?\s+(?:\w+\s+){0,4}?(?:${CONTENT_NOUN_STRONG})\b`,
3502
+ "i"
3503
+ );
3504
+ NUMBERED_SEED_RE = new RegExp(
3505
+ String.raw`\badd(?:ing|s)?\s+(?:\w+\s+){0,4}?(?:${CONTENT_NOUN_STRONG}|${CONTENT_NOUN_BROAD})\s*#?\s*\d{1,3}\s*$`,
3506
+ "i"
3507
+ );
3285
3508
  ADD_TO_CORPUS_RE = /\badd\b[\s\S]*?\bto\s+(?:the\s+)?(?:word\s?list|dictionary|glossary|phrasebook)\b/i;
3286
3509
  TRANSLATE_RE = /\b(?:translate|translating|translation|localize|localise|localization|localisation)\b/i;
3287
3510
  TYPO_RE = /\bfix(?:ing)?\s+(?:a\s+|the\s+|some\s+)?typos?\b/i;
@@ -3289,20 +3512,6 @@ var init_contribution_classify = __esm({
3289
3512
  });
3290
3513
 
3291
3514
  // ../../packages/core/src/feeds/contributions.ts
3292
- function readReqGapMs() {
3293
- const raw = process.env["CONTRIB_REQ_GAP_MS"];
3294
- if (raw == null) return DEFAULT_REQ_GAP_MS;
3295
- const n = Number.parseInt(raw, 10);
3296
- if (Number.isNaN(n)) return DEFAULT_REQ_GAP_MS;
3297
- return Math.min(Math.max(n, 0), 1e3);
3298
- }
3299
- function readBuildBudgetMs() {
3300
- const raw = process.env["CONTRIB_BUILD_BUDGET_MS"];
3301
- if (raw == null) return DEFAULT_BUILD_BUDGET_MS;
3302
- const n = Number.parseInt(raw, 10);
3303
- if (Number.isNaN(n)) return DEFAULT_BUILD_BUDGET_MS;
3304
- return Math.min(Math.max(n, MIN_BUILD_BUDGET_MS), MAX_BUILD_BUDGET_MS);
3305
- }
3306
3515
  function authHeaders2() {
3307
3516
  const token = process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
3308
3517
  const h = {
@@ -3324,57 +3533,9 @@ function repoFullNameFromApiUrl2(url) {
3324
3533
  return m ? `${m[1]}/${m[2]}` : null;
3325
3534
  }
3326
3535
  function makeClient(fetchImpl, cfg) {
3327
- const startedAt = cfg.now();
3328
- let lastRequestAt = 0;
3329
- let pacedMs = 0;
3330
- let secondaryHits = 0;
3331
- let aborted = false;
3332
- let secondaryAborted = false;
3333
- let budgetAborted = false;
3334
- let coreHealthyAtStart = false;
3335
- async function noteAndMaybeBackOff(res) {
3336
- if (res.status !== 403) return;
3337
- const remaining = res.headers.get("x-ratelimit-remaining");
3338
- const retryAfter = res.headers.get("retry-after");
3339
- const positiveSecondary = retryAfter != null || remaining != null && remaining !== "0";
3340
- const isSecondary = positiveSecondary || coreHealthyAtStart;
3341
- if (!isSecondary) return;
3342
- secondaryHits++;
3343
- if (secondaryHits >= 2) {
3344
- aborted = true;
3345
- secondaryAborted = true;
3346
- return;
3347
- }
3348
- if (cfg.paceEnabled) {
3349
- const trimmed = (retryAfter ?? "").trim();
3350
- const parsed = trimmed.length === 0 ? Number.NaN : Number(trimmed);
3351
- const sec = Number.isNaN(parsed) ? SECONDARY_BACKOFF_CAP_S : Math.min(Math.max(parsed, 0), SECONDARY_BACKOFF_CAP_S);
3352
- const remaining2 = Math.max(0, cfg.budgetMs - (cfg.now() - startedAt));
3353
- await cfg.sleep(Math.min(sec * 1e3, remaining2));
3354
- }
3355
- }
3536
+ const gov = makeGitHubGovernor(fetchImpl, cfg);
3356
3537
  async function raw(path) {
3357
- if (aborted) return null;
3358
- if (cfg.now() - startedAt > cfg.budgetMs) {
3359
- aborted = true;
3360
- budgetAborted = true;
3361
- return null;
3362
- }
3363
- if (cfg.paceEnabled && cfg.gapMs > 0) {
3364
- const wait = cfg.gapMs - (cfg.now() - lastRequestAt);
3365
- if (wait > 0) {
3366
- await cfg.sleep(wait);
3367
- pacedMs += wait;
3368
- }
3369
- lastRequestAt = cfg.now();
3370
- }
3371
- try {
3372
- const res = await fetchImpl(`${GITHUB_API2}${path}`, { headers: authHeaders2() });
3373
- await noteAndMaybeBackOff(res);
3374
- return res;
3375
- } catch {
3376
- return null;
3377
- }
3538
+ return gov.get(`${GITHUB_API2}${path}`, { headers: authHeaders2() });
3378
3539
  }
3379
3540
  async function json(path) {
3380
3541
  const res = await raw(path);
@@ -3388,41 +3549,9 @@ function makeClient(fetchImpl, cfg) {
3388
3549
  }
3389
3550
  }
3390
3551
  async function probe(path) {
3391
- const bound = cfg.probeTimeoutMs;
3392
- let timer;
3393
- const fetchP = fetchImpl(`${GITHUB_API2}${path}`, {
3394
- headers: authHeaders2()
3395
- }).then(
3396
- (r) => r,
3397
- () => null
3398
- );
3399
- try {
3400
- const res = bound == null ? await fetchP : await Promise.race([
3401
- fetchP,
3402
- new Promise((resolve) => {
3403
- timer = setTimeout(() => resolve(null), bound);
3404
- })
3405
- ]);
3406
- if (!res || !res.ok) return null;
3407
- return await res.json();
3408
- } catch {
3409
- return null;
3410
- } finally {
3411
- if (timer) clearTimeout(timer);
3412
- }
3552
+ return gov.probe(`${GITHUB_API2}${path}`, { headers: authHeaders2() });
3413
3553
  }
3414
- function setSecondaryHint(coreHealthy) {
3415
- coreHealthyAtStart = coreHealthy;
3416
- }
3417
- function getStats() {
3418
- return {
3419
- pacedMs,
3420
- secondaryAborted: secondaryAborted ? 1 : 0,
3421
- budgetAborted: budgetAborted ? 1 : 0,
3422
- elapsedMs: cfg.now() - startedAt
3423
- };
3424
- }
3425
- return { raw, json, probe, setSecondaryHint, getStats };
3554
+ return { raw, json, probe, setSecondaryHint: gov.setSecondaryHint, getStats: gov.getStats };
3426
3555
  }
3427
3556
  async function contributorCount(client, fullName) {
3428
3557
  const res = await client.raw(`/repos/${fullName}/contributors?per_page=1&anon=false`);
@@ -3521,10 +3650,63 @@ async function aggregateContributions(opts = {}) {
3521
3650
  const repoCache = /* @__PURE__ */ new Map();
3522
3651
  const contribCache = /* @__PURE__ */ new Map();
3523
3652
  const prRefsCache = /* @__PURE__ */ new Map();
3653
+ const xbuild = opts.repoMetaCache;
3654
+ const servedFromXbuild = /* @__PURE__ */ new Set();
3655
+ const persistedXbuild = /* @__PURE__ */ new Set();
3656
+ const xbuildTried = /* @__PURE__ */ new Set();
3657
+ async function primeFromXbuild(key, fullName) {
3658
+ if (!xbuild || xbuildTried.has(key)) return;
3659
+ xbuildTried.add(key);
3660
+ if (repoCache.has(key) && contribCache.has(key)) return;
3661
+ let cached = null;
3662
+ try {
3663
+ cached = await xbuild.get(key);
3664
+ } catch {
3665
+ return;
3666
+ }
3667
+ if (!cached) return;
3668
+ if (!repoCache.has(key)) {
3669
+ const owner = fullName.split("/")[0] ?? "";
3670
+ repoCache.set(key, {
3671
+ full_name: fullName,
3672
+ stargazers_count: cached.stars,
3673
+ archived: cached.archived,
3674
+ disabled: cached.disabled,
3675
+ fork: cached.fork,
3676
+ language: cached.language,
3677
+ owner: { login: owner }
3678
+ });
3679
+ }
3680
+ if (!contribCache.has(key)) {
3681
+ contribCache.set(key, cached.contributors);
3682
+ servedFromXbuild.add(key);
3683
+ }
3684
+ }
3685
+ async function persistRepoMeta(fullName, repo, contributors) {
3686
+ if (!xbuild) return;
3687
+ const key = repoKey(fullName);
3688
+ if (servedFromXbuild.has(key) || persistedXbuild.has(key)) return;
3689
+ if (contributors === void 0) return;
3690
+ persistedXbuild.add(key);
3691
+ try {
3692
+ await xbuild.set(key, {
3693
+ stars: repo.stargazers_count,
3694
+ contributors,
3695
+ language: repo.language,
3696
+ archived: repo.archived,
3697
+ fork: repo.fork,
3698
+ disabled: repo.disabled
3699
+ });
3700
+ } catch {
3701
+ }
3702
+ }
3524
3703
  async function repoMeta(fullName) {
3525
3704
  const key = repoKey(fullName);
3526
3705
  const hit = repoCache.get(key);
3527
3706
  if (hit !== void 0) return hit;
3707
+ await primeFromXbuild(key, fullName);
3708
+ const primed = repoCache.get(key);
3709
+ if (primed !== void 0) return primed;
3528
3710
  const r = await client.json(`/repos/${fullName}`) ?? null;
3529
3711
  repoCache.set(key, r);
3530
3712
  return r;
@@ -3532,6 +3714,8 @@ async function aggregateContributions(opts = {}) {
3532
3714
  async function repoContribCount(fullName) {
3533
3715
  const key = repoKey(fullName);
3534
3716
  if (contribCache.has(key)) return contribCache.get(key);
3717
+ await primeFromXbuild(key, fullName);
3718
+ if (contribCache.has(key)) return contribCache.get(key);
3535
3719
  const n = await contributorCount(client, fullName);
3536
3720
  contribCache.set(key, n);
3537
3721
  return n;
@@ -3558,14 +3742,18 @@ async function aggregateContributions(opts = {}) {
3558
3742
  if (isDenylistedRepo(fullName)) continue;
3559
3743
  if (isAssigned(issue)) continue;
3560
3744
  if ((perRepo.get(repoKey(fullName)) ?? 0) >= MAX_BOUNTIES_PER_DISCOVERED_REPO) continue;
3745
+ const title = decodeEntities(issue.title).trim();
3746
+ const body = issue.body ? decodeEntities(issue.body) : "";
3747
+ const labels = labelNames2(issue.labels);
3748
+ if (looksLikeContentTask({ title, body, labels })) continue;
3561
3749
  const repo = await repoMeta(fullName);
3562
3750
  if (!repo) {
3563
3751
  metaNull++;
3564
3752
  continue;
3565
3753
  }
3566
- const title = decodeEntities(issue.title).trim();
3567
3754
  const contributors = await repoContribCount(fullName);
3568
3755
  if (contributors === void 0) contribUndefined++;
3756
+ await persistRepoMeta(fullName, repo, contributors);
3569
3757
  if (!passesContributionGate({
3570
3758
  fullName,
3571
3759
  stars: repo.stargazers_count,
@@ -3577,13 +3765,9 @@ async function aggregateContributions(opts = {}) {
3577
3765
  continue;
3578
3766
  }
3579
3767
  if (repo.disabled) continue;
3580
- const body = issue.body ? decodeEntities(issue.body) : "";
3581
- const labels = labelNames2(issue.labels);
3582
- if (looksLikeContentTask({ title, body, labels })) continue;
3583
3768
  const prRefs = await repoPRRefs(fullName);
3584
3769
  if (prRefs === null) prRefsNull++;
3585
- if (prRefs && prRefs.has(issue.number)) continue;
3586
- const openPRsAtDiscovery = prRefs ? 0 : void 0;
3770
+ const openPRsAtDiscovery = prRefs ? prRefs.has(issue.number) ? 1 : 0 : void 0;
3587
3771
  const tags = normalize(
3588
3772
  tokenize4([title, repo.language ?? "", labels.join(" "), body.slice(0, 2e3)].join(" "))
3589
3773
  );
@@ -3674,6 +3858,7 @@ async function aggregateContributions(opts = {}) {
3674
3858
  if (repo.disabled) continue;
3675
3859
  const contributors = await repoContribCount(fullName);
3676
3860
  if (contributors === void 0) contribUndefined++;
3861
+ await persistRepoMeta(fullName, repo, contributors);
3677
3862
  if (repo.archived || repo.fork || repo.stargazers_count < MIN_STARS || contributors === void 0 || contributors < MIN_CONTRIBUTORS) {
3678
3863
  continue;
3679
3864
  }
@@ -3706,8 +3891,7 @@ async function aggregateContributions(opts = {}) {
3706
3891
  if (looksLikeContentTask({ title, body, labels })) continue;
3707
3892
  const prRefs = await repoPRRefs(fullName);
3708
3893
  if (prRefs === null) prRefsNull++;
3709
- if (prRefs && prRefs.has(issue.number)) continue;
3710
- const openPRsAtDiscovery = prRefs ? 0 : void 0;
3894
+ const openPRsAtDiscovery = prRefs ? prRefs.has(issue.number) ? 1 : 0 : void 0;
3711
3895
  const tags = normalize(
3712
3896
  tokenize4([title, repo.language ?? "", labels.join(" "), body.slice(0, 2e3)].join(" "))
3713
3897
  );
@@ -3738,9 +3922,9 @@ async function aggregateContributions(opts = {}) {
3738
3922
  const core = rl?.core ? `${rl.core.remaining}/${rl.core.limit}` : "n/a";
3739
3923
  const search = rl?.search ? `${rl.search.remaining}/${rl.search.limit}` : "n/a";
3740
3924
  const noToken = !(process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"]);
3741
- const { pacedMs, secondaryAborted, budgetAborted, elapsedMs } = client.getStats();
3925
+ const { pacedMs, secondaryAborted, budgetAborted, elapsedMs, gqlCost, gqlRemaining } = client.getStats();
3742
3926
  console.info(
3743
- `[contribute] build metrics \u2014 scanned=${issues.length} reposDistinct=${repoCache.size} emitted=${jobs.length} discovered=${discoveredEmitted} metaNull=${metaNull} contribUndefined=${contribUndefined} prRefsNull=${prRefsNull} paced=${pacedMs} secondaryAborted=${secondaryAborted} budgetAborted=${budgetAborted} core=${core} search=${search} elapsed=${elapsedMs}` + (noToken ? " (NO TOKEN \u2192 60/hr)" : "")
3927
+ `[contribute] build metrics \u2014 scanned=${issues.length} reposDistinct=${repoCache.size} emitted=${jobs.length} discovered=${discoveredEmitted} metaNull=${metaNull} contribUndefined=${contribUndefined} prRefsNull=${prRefsNull} paced=${pacedMs} secondaryAborted=${secondaryAborted} budgetAborted=${budgetAborted} core=${core} search=${search} gqlCost=${gqlCost} gqlRemaining=${gqlRemaining ?? "n/a"} elapsed=${elapsedMs}` + (noToken ? " (NO TOKEN \u2192 60/hr)" : "")
3744
3928
  );
3745
3929
  if (discoveryBudgetStopped) {
3746
3930
  console.warn(
@@ -3750,7 +3934,7 @@ async function aggregateContributions(opts = {}) {
3750
3934
  }
3751
3935
  return jobs;
3752
3936
  }
3753
- 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, MAX_DISCOVERED_REPOS, MAX_ISSUES_PER_DISCOVERED_REPO, DISCOVERY_REPOS_PER_TERM, DISCOVERY_VOCAB_TERMS, DISCOVERY_ISSUE_LABELS, repoKey;
3937
+ var GITHUB_API2, CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2, MAX_CONTRIB_ITEMS, MAX_CONTRIB_ISSUES_SCANNED, MAX_DISCOVERED_REPOS, MAX_ISSUES_PER_DISCOVERED_REPO, DISCOVERY_REPOS_PER_TERM, DISCOVERY_VOCAB_TERMS, DISCOVERY_ISSUE_LABELS, repoKey;
3754
3938
  var init_contributions = __esm({
3755
3939
  "../../packages/core/src/feeds/contributions.ts"() {
3756
3940
  "use strict";
@@ -3761,14 +3945,8 @@ var init_contributions = __esm({
3761
3945
  init_contribution_classify();
3762
3946
  init_github_bounties();
3763
3947
  init_http();
3948
+ init_gh_governor();
3764
3949
  GITHUB_API2 = "https://api.github.com";
3765
- DEFAULT_REQ_GAP_MS = 75;
3766
- SECONDARY_BACKOFF_CAP_S = 30;
3767
- DEFAULT_BUILD_BUDGET_MS = 9e4;
3768
- MIN_BUILD_BUDGET_MS = 1e4;
3769
- MAX_BUILD_BUDGET_MS = 9e4;
3770
- PROBE_TIMEOUT_MS = 3e3;
3771
- realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
3772
3950
  CONTRIB_LABEL_QUERIES = [
3773
3951
  'label:"good first issue" type:issue state:open',
3774
3952
  'label:"good-first-issue" type:issue state:open',
@@ -3986,12 +4164,22 @@ async function enrichWinnability(jobs, contribute, w) {
3986
4164
  const repos = [...byRepo.keys()].sort((a, b) => starsOf(b) - starsOf(a));
3987
4165
  const scored = repos.slice(0, maxRepos);
3988
4166
  const cappedOut = repos.length - scored.length;
4167
+ const gov = w.governor ?? makeGitHubGovernor(
4168
+ w.fetchImpl ?? fetch,
4169
+ makeDefaultGovernorConfig({ paceEnabled: !w.fetchImpl })
4170
+ );
4171
+ let stoppedEarly = false;
3989
4172
  for (const repo of scored) {
4173
+ if (gov.tripped() || gov.budgetExhausted()) {
4174
+ stoppedEarly = true;
4175
+ break;
4176
+ }
3990
4177
  const targets = byRepo.get(repo) ?? [];
3991
4178
  const receptivity = await fetchRepoReceptivity(repo, {
3992
4179
  token: w.token,
3993
4180
  fetchImpl: w.fetchImpl,
3994
- now
4181
+ now,
4182
+ governor: gov
3995
4183
  });
3996
4184
  const stars = starsOf(repo);
3997
4185
  const prev = priorStars[repo];
@@ -4020,6 +4208,12 @@ async function enrichWinnability(jobs, contribute, w) {
4020
4208
  }
4021
4209
  }
4022
4210
  }
4211
+ if (stoppedEarly) {
4212
+ const reason = gov.tripped() ? "secondary-abuse breaker" : "wall-clock budget";
4213
+ console.warn(
4214
+ `[winnability] receptivity governor stopped the loop \u2014 ${reason} tripped; remaining repos left un-scored (legacy ranking). Governed egress halted to avoid prolonging the GitHub rate-limit window.`
4215
+ );
4216
+ }
4023
4217
  if (cappedOut > 0) {
4024
4218
  console.warn(
4025
4219
  `[winnability] receptivity cap hit \u2014 scored ${scored.length}/${repos.length} repos (${cappedOut} beyond maxRepos=${maxRepos} left un-scored, legacy ranking)`
@@ -4062,6 +4256,7 @@ var init_indexer = __esm({
4062
4256
  init_contributions();
4063
4257
  init_partners();
4064
4258
  init_github();
4259
+ init_gh_governor();
4065
4260
  init_winnability();
4066
4261
  }
4067
4262
  });
@@ -7657,6 +7852,7 @@ __export(src_exports, {
7657
7852
  MERGE_PROBABILITY: () => MERGE_PROBABILITY,
7658
7853
  MIN_CONTRIBUTORS: () => MIN_CONTRIBUTORS,
7659
7854
  MIN_STARS: () => MIN_STARS,
7855
+ PROBE_TIMEOUT_MS: () => PROBE_TIMEOUT_MS,
7660
7856
  RIGOR: () => RIGOR,
7661
7857
  STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
7662
7858
  SYNONYMS: () => SYNONYMS,
@@ -7728,6 +7924,9 @@ __export(src_exports, {
7728
7924
  lever: () => lever,
7729
7925
  loadPartnerRoles: () => loadPartnerRoles,
7730
7926
  looksLikeEngRole: () => looksLikeEngRole,
7927
+ makeDefaultGovernorConfig: () => makeDefaultGovernorConfig,
7928
+ makeGitHubGovernor: () => makeGitHubGovernor,
7929
+ makeScoringGovernor: () => makeScoringGovernor,
7731
7930
  match: () => match,
7732
7931
  mergeProbability: () => mergeProbability,
7733
7932
  mmrRerank: () => mmrRerank,
@@ -7740,8 +7939,12 @@ __export(src_exports, {
7740
7939
  passesMaturityGate: () => passesMaturityGate,
7741
7940
  personCardToJob: () => personCardToJob,
7742
7941
  projectCardToJob: () => projectCardToJob,
7942
+ readBuildBudgetMs: () => readBuildBudgetMs,
7943
+ readReqGapMs: () => readReqGapMs,
7944
+ realSleep: () => realSleep,
7743
7945
  recordClick: () => recordClick,
7744
7946
  rejectExtraIntroFields: () => rejectExtraIntroFields,
7947
+ relevanceScore: () => relevanceScore,
7745
7948
  revealIntroContacts: () => revealIntroContacts,
7746
7949
  safetyNumber: () => safetyNumber,
7747
7950
  sameLogin: () => sameLogin,
@@ -7768,6 +7971,7 @@ var init_src = __esm({
7768
7971
  init_winnability();
7769
7972
  init_partners();
7770
7973
  init_github();
7974
+ init_gh_governor();
7771
7975
  init_credit();
7772
7976
  init_intro();
7773
7977
  init_directoryThreshold();
@@ -7788,9 +7992,9 @@ var init_keytar = __esm({
7788
7992
  }
7789
7993
  });
7790
7994
 
7791
- // node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a4d8b1364e2f66adc/node_modules/keytar/build/Release/keytar.node
7995
+ // node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
7792
7996
  var require_keytar = __commonJS({
7793
- "node-file:/Users/ericgang/job-placement-inline/.claude/worktrees/agent-a4d8b1364e2f66adc/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7997
+ "node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7794
7998
  "use strict";
7795
7999
  init_keytar();
7796
8000
  try {