terminalhire 0.22.0 → 0.24.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 +2 -2
- package/dist/bin/jpi-bounties.js +189 -29
- package/dist/bin/jpi-chat-read.js +82 -11
- package/dist/bin/jpi-chat.js +272 -81
- package/dist/bin/jpi-claim.js +154 -5
- package/dist/bin/jpi-contribute.js +37 -3
- package/dist/bin/jpi-devs.js +205 -40
- package/dist/bin/jpi-dispatch.js +1848 -268
- package/dist/bin/jpi-hub.js +9786 -0
- package/dist/bin/jpi-inbox.js +271 -81
- package/dist/bin/jpi-init.js +152 -3
- package/dist/bin/jpi-intro.js +81 -36
- package/dist/bin/jpi-jobs.js +193 -26
- package/dist/bin/jpi-learn.js +29 -3
- package/dist/bin/jpi-login.js +154 -5
- package/dist/bin/jpi-profile.js +29 -3
- package/dist/bin/jpi-project.js +198 -9
- package/dist/bin/jpi-refresh.js +154 -5
- package/dist/bin/jpi-save.js +29 -3
- package/dist/bin/jpi-spinner.js +10 -1
- package/dist/bin/jpi-sync.js +29 -3
- package/dist/bin/jpi-trajectory.js +40 -9
- package/dist/bin/spinner.js +10 -1
- package/dist/bin/tui-core.js +440 -0
- package/dist/src/chat-client.js +12 -3
- package/dist/src/chat-keystore.js +12 -3
- package/dist/src/github-auth.js +2 -2
- package/dist/src/intro.js +81 -36
- package/dist/src/profile.js +12 -3
- package/dist/src/signal.js +10 -1
- package/dist/src/trajectory.js +40 -9
- 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
|
|
48
|
+
// node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
|
|
49
49
|
var require_keytar = __commonJS({
|
|
50
|
-
"node-file:/Users/ericgang/job-placement-inline
|
|
50
|
+
"node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
51
51
|
"use strict";
|
|
52
52
|
init_keytar();
|
|
53
53
|
try {
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -193,7 +193,7 @@ var init_graph_data = __esm({
|
|
|
193
193
|
{ id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
|
|
194
194
|
{ id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
|
|
195
195
|
{ id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
|
|
196
|
-
{ id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
|
|
196
|
+
{ id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
|
|
197
197
|
{ id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
|
|
198
198
|
{ id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
|
|
199
199
|
{ id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
|
|
@@ -459,6 +459,14 @@ var init_extract = __esm({
|
|
|
459
459
|
id: "prompt-engineering",
|
|
460
460
|
cue: /\bprompt[\s-]?engineer(?:ing|s)?\b|\b(llms?|gpt-?[0-9o]*|claude|gemini|llama|mistral|openai|anthropic|langchain|llama[\s-]?index|rag|retrieval[\s-]?augmented|embeddings?|fine[\s-]?tun(?:e|ed|ing)|vector[\s-]?(?:db|database|store)|agentic|ai agents?|chatbots?|generative ai|gen[\s-]?ai|genai|few[\s-]?shot|zero[\s-]?shot)\b/i
|
|
461
461
|
}
|
|
462
|
+
// Plan-061 note: the AI-eng generic words (orchestration/evals/evaluation/guardrails/
|
|
463
|
+
// governance) were briefly added as raw agents/llm synonyms, but `normalize()` — the
|
|
464
|
+
// context-free firewall shared by the declaration path AND the GitHub bounty/
|
|
465
|
+
// contribution feeds — resolves synonyms with NO cue, so those words false-mined
|
|
466
|
+
// agents/llm from ordinary infra/SRE prose on every normalize() caller. A cue gate
|
|
467
|
+
// here only covers extractSkillTags(), not normalize(). Fix: they are NOT graph
|
|
468
|
+
// synonyms at all (see graph.data.ts) → they fall to the 3-tier SOFT/novel bucket,
|
|
469
|
+
// which is exactly where ambiguous, uncategorizable words belong. Nothing to gate.
|
|
462
470
|
};
|
|
463
471
|
ENG_INTENT = /\b(engineer|engineering|developer|dev\b|swe|sde|programmer|architect|full[\s-]?stack|front[\s-]?end|back[\s-]?end|devops|sre|software|coding|codebase|technical staff|tech(?:nical)? lead)\b/i;
|
|
464
472
|
NON_ENG_TITLE = /\b(account executive|account manager|sales (?:rep|representative|development|manager|lead)|sdr|bdr|recruiter|recruiting|talent|marketing|administrative|business partner|billing coordinator|operations (?:administrator|coordinator)|customer success|project finance|controller|bookkeeper|graphic|brand)\b/i;
|
|
@@ -582,6 +590,69 @@ var init_idf_background = __esm({
|
|
|
582
590
|
}
|
|
583
591
|
});
|
|
584
592
|
|
|
593
|
+
// ../../packages/core/src/vocab/classify.ts
|
|
594
|
+
function editDistance(a, b, max) {
|
|
595
|
+
if (a === b) return 0;
|
|
596
|
+
if (Math.abs(a.length - b.length) > max) return max + 1;
|
|
597
|
+
const prev = new Array(b.length + 1);
|
|
598
|
+
const cur = new Array(b.length + 1);
|
|
599
|
+
for (let j = 0; j <= b.length; j++) prev[j] = j;
|
|
600
|
+
for (let i = 1; i <= a.length; i++) {
|
|
601
|
+
cur[0] = i;
|
|
602
|
+
let rowMin = cur[0];
|
|
603
|
+
for (let j = 1; j <= b.length; j++) {
|
|
604
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
605
|
+
cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
|
|
606
|
+
if (cur[j] < rowMin) rowMin = cur[j];
|
|
607
|
+
}
|
|
608
|
+
if (rowMin > max) return max + 1;
|
|
609
|
+
for (let j = 0; j <= b.length; j++) prev[j] = cur[j];
|
|
610
|
+
}
|
|
611
|
+
return prev[b.length];
|
|
612
|
+
}
|
|
613
|
+
function canonicalOf(surface, graph) {
|
|
614
|
+
if (graph.ids.has(surface)) return surface;
|
|
615
|
+
return graph.synonyms.get(surface);
|
|
616
|
+
}
|
|
617
|
+
function nearBudget(len) {
|
|
618
|
+
if (len <= 3) return 0;
|
|
619
|
+
if (len <= 6) return 1;
|
|
620
|
+
return 2;
|
|
621
|
+
}
|
|
622
|
+
function classifyToken(raw, graph = GRAPH) {
|
|
623
|
+
const token = String(raw ?? "").toLowerCase().trim();
|
|
624
|
+
const exact = canonicalOf(token, graph);
|
|
625
|
+
if (exact) return { raw: token, tier: "matched", canonical: exact };
|
|
626
|
+
const budget = nearBudget(token.length);
|
|
627
|
+
if (budget > 0) {
|
|
628
|
+
let bestSurface;
|
|
629
|
+
let bestDist = budget + 1;
|
|
630
|
+
const consider = (surface) => {
|
|
631
|
+
const d = editDistance(token, surface, budget);
|
|
632
|
+
if (d <= budget && (d < bestDist || d === bestDist && bestSurface !== void 0 && (surface.length < bestSurface.length || surface.length === bestSurface.length && surface < bestSurface))) {
|
|
633
|
+
bestDist = d;
|
|
634
|
+
bestSurface = surface;
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
for (const id of graph.ids) consider(id);
|
|
638
|
+
for (const alias of graph.synonyms.keys()) consider(alias);
|
|
639
|
+
if (bestSurface !== void 0) {
|
|
640
|
+
const suggestion = canonicalOf(bestSurface, graph);
|
|
641
|
+
if (suggestion) return { raw: token, tier: "near-miss", suggestion };
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return { raw: token, tier: "novel", soft: token };
|
|
645
|
+
}
|
|
646
|
+
function classifyTokens(raws, graph = GRAPH) {
|
|
647
|
+
return raws.map((r) => classifyToken(r, graph));
|
|
648
|
+
}
|
|
649
|
+
var init_classify = __esm({
|
|
650
|
+
"../../packages/core/src/vocab/classify.ts"() {
|
|
651
|
+
"use strict";
|
|
652
|
+
init_vocab();
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
|
|
585
656
|
// ../../packages/core/src/vocab/index.ts
|
|
586
657
|
function normalize(tokens) {
|
|
587
658
|
const result = /* @__PURE__ */ new Set();
|
|
@@ -645,6 +716,7 @@ var init_vocab = __esm({
|
|
|
645
716
|
init_graph_data();
|
|
646
717
|
init_extract();
|
|
647
718
|
init_idf_background();
|
|
719
|
+
init_classify();
|
|
648
720
|
GRAPH = buildGraph(VOCAB_NODES);
|
|
649
721
|
VOCABULARY = [...GRAPH.ids];
|
|
650
722
|
SYNONYMS = Object.fromEntries(GRAPH.synonyms);
|
|
@@ -749,6 +821,30 @@ var init_contribution_gate = __esm({
|
|
|
749
821
|
}
|
|
750
822
|
});
|
|
751
823
|
|
|
824
|
+
// ../../packages/core/src/credential/rigor.ts
|
|
825
|
+
function deriveRigorTiers(input) {
|
|
826
|
+
const tiers = {};
|
|
827
|
+
if (input.reviewerAssociations !== void 0) {
|
|
828
|
+
tiers.maintainerReviewed = input.reviewerAssociations.some(
|
|
829
|
+
(a) => MAINTAINER_SET.has(String(a).toUpperCase())
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
return tiers;
|
|
833
|
+
}
|
|
834
|
+
var RIGOR, MAINTAINER_SET;
|
|
835
|
+
var init_rigor = __esm({
|
|
836
|
+
"../../packages/core/src/credential/rigor.ts"() {
|
|
837
|
+
"use strict";
|
|
838
|
+
RIGOR = {
|
|
839
|
+
/** `authorAssociation` values that count as a maintainer review. */
|
|
840
|
+
MAINTAINER_ASSOCIATIONS: ["OWNER", "MEMBER", "COLLABORATOR"]
|
|
841
|
+
};
|
|
842
|
+
MAINTAINER_SET = new Set(
|
|
843
|
+
RIGOR.MAINTAINER_ASSOCIATIONS.map((a) => a.toUpperCase())
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
|
|
752
848
|
// ../../packages/core/src/github.ts
|
|
753
849
|
function ghHeaders(token) {
|
|
754
850
|
const headers = {
|
|
@@ -1027,6 +1123,33 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
1027
1123
|
if (mergedAt > b.lastMergedAt) b.lastMergedAt = mergedAt;
|
|
1028
1124
|
}
|
|
1029
1125
|
}
|
|
1126
|
+
if (token) {
|
|
1127
|
+
const enrichStats = { transient: 0 };
|
|
1128
|
+
const enrichCount = Math.min(qualifyingPRs.length, MAX_ENRICH_PRS);
|
|
1129
|
+
for (let i = 0; i < enrichCount; i++) {
|
|
1130
|
+
const pr = qualifyingPRs[i];
|
|
1131
|
+
const ref = parseGitHubRef(pr.url);
|
|
1132
|
+
if (!ref || ref.kind !== "pull") continue;
|
|
1133
|
+
try {
|
|
1134
|
+
const reviews = await ghFetch(
|
|
1135
|
+
`/repos/${ref.owner}/${ref.repo}/pulls/${ref.number}/reviews?per_page=100`,
|
|
1136
|
+
token
|
|
1137
|
+
);
|
|
1138
|
+
const reviewerAssociations = reviews.map((r) => r.author_association);
|
|
1139
|
+
const tiers = deriveRigorTiers({ reviewerAssociations });
|
|
1140
|
+
if (tiers.maintainerReviewed !== void 0) pr.maintainerReviewed = tiers.maintainerReviewed;
|
|
1141
|
+
} catch (err) {
|
|
1142
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1143
|
+
if (TRANSIENT_META_ERROR.test(msg)) {
|
|
1144
|
+
enrichStats.transient += 1;
|
|
1145
|
+
console.warn(
|
|
1146
|
+
`[acceptance] ${login}: per-PR rigor enrichment transient failure (${enrichStats.transient}) \u2014 leaving remaining tiers undefined rather than fabricating a false`
|
|
1147
|
+
);
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1030
1153
|
const finalDomains = {};
|
|
1031
1154
|
for (const [d, b] of Object.entries(byDomain)) {
|
|
1032
1155
|
finalDomains[d] = {
|
|
@@ -1233,6 +1356,17 @@ async function fetchPRScoringFacts(prUrl, token, signal) {
|
|
|
1233
1356
|
}
|
|
1234
1357
|
const contributors = await repoContributorCount(owner, repo, token, sig);
|
|
1235
1358
|
const { closesIssues, linkageSource } = await resolveClosingIssues(owner, repo, number, pr.body ?? "", token, sig);
|
|
1359
|
+
let reviewerAssociations;
|
|
1360
|
+
try {
|
|
1361
|
+
const reviews = await ghFetch(
|
|
1362
|
+
`/repos/${owner}/${repo}/pulls/${number}/reviews?per_page=100`,
|
|
1363
|
+
token,
|
|
1364
|
+
sig
|
|
1365
|
+
);
|
|
1366
|
+
reviewerAssociations = reviews.map((r) => r.author_association);
|
|
1367
|
+
} catch {
|
|
1368
|
+
reviewerAssociations = void 0;
|
|
1369
|
+
}
|
|
1236
1370
|
return {
|
|
1237
1371
|
repo: `${owner}/${repo}`,
|
|
1238
1372
|
prNumber: number,
|
|
@@ -1250,17 +1384,24 @@ async function fetchPRScoringFacts(prUrl, token, signal) {
|
|
|
1250
1384
|
repoArchived: !!repoMeta?.archived,
|
|
1251
1385
|
repoFork: !!repoMeta?.fork,
|
|
1252
1386
|
repoPrivate: !!repoMeta?.private,
|
|
1387
|
+
additions: pr.additions ?? null,
|
|
1388
|
+
deletions: pr.deletions ?? null,
|
|
1389
|
+
changedFiles: pr.changed_files ?? null,
|
|
1390
|
+
repoForks: repoMeta?.forks_count ?? null,
|
|
1391
|
+
reviewerAssociations,
|
|
1253
1392
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1254
1393
|
};
|
|
1255
1394
|
}
|
|
1256
|
-
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1395
|
+
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, MAX_ENRICH_PRS, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1257
1396
|
var init_github = __esm({
|
|
1258
1397
|
"../../packages/core/src/github.ts"() {
|
|
1259
1398
|
"use strict";
|
|
1260
1399
|
init_vocabulary();
|
|
1261
1400
|
init_contribution_gate();
|
|
1401
|
+
init_rigor();
|
|
1262
1402
|
TRACTION_TOP_N = 6;
|
|
1263
1403
|
CANDIDATE_PR_PAGE = 50;
|
|
1404
|
+
MAX_ENRICH_PRS = 12;
|
|
1264
1405
|
OPEN_PR_PAGE = 20;
|
|
1265
1406
|
TRANSIENT_META_ERROR = /HTTP 403|HTTP 429|rate limit|HTTP 5\d\d|timeout|network|fetch failed/i;
|
|
1266
1407
|
RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -6772,10 +6913,13 @@ function deriveLegibleProfile(credential, recency, traction, seniorityBand) {
|
|
|
6772
6913
|
if (daysAgo !== void 0) s += ` \u2014 most recent ${daysAgo}d ago`;
|
|
6773
6914
|
proofSentence = `${s}.`;
|
|
6774
6915
|
}
|
|
6916
|
+
const enrichedPRs = ok ? credential.qualifyingPRs ?? [] : [];
|
|
6917
|
+
const maintainerReviewedCount = enrichedPRs.some((p) => p.maintainerReviewed !== void 0) ? enrichedPRs.filter((p) => p.maintainerReviewed === true).length : void 0;
|
|
6775
6918
|
const auditableBadge = ok ? {
|
|
6776
6919
|
mergedTotal: credential.qualifyingTotal,
|
|
6777
6920
|
distinctOrgs: orgCount,
|
|
6778
|
-
thresholds: { stars: MIN_STARS, contributors: MIN_CONTRIBUTORS }
|
|
6921
|
+
thresholds: { stars: MIN_STARS, contributors: MIN_CONTRIBUTORS },
|
|
6922
|
+
...maintainerReviewedCount !== void 0 ? { maintainerReviewedCount } : {}
|
|
6779
6923
|
} : null;
|
|
6780
6924
|
const profile = {
|
|
6781
6925
|
headline,
|
|
@@ -6971,6 +7115,7 @@ __export(src_exports, {
|
|
|
6971
7115
|
MENTION_DELTA: () => MENTION_DELTA,
|
|
6972
7116
|
MIN_CONTRIBUTORS: () => MIN_CONTRIBUTORS,
|
|
6973
7117
|
MIN_STARS: () => MIN_STARS,
|
|
7118
|
+
RIGOR: () => RIGOR,
|
|
6974
7119
|
STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
|
|
6975
7120
|
SYNONYMS: () => SYNONYMS,
|
|
6976
7121
|
TRIVIAL_PR_TITLE: () => TRIVIAL_PR_TITLE,
|
|
@@ -6989,6 +7134,8 @@ __export(src_exports, {
|
|
|
6989
7134
|
buildIntroListItem: () => buildIntroListItem,
|
|
6990
7135
|
buildIntroPayload: () => buildIntroPayload,
|
|
6991
7136
|
buildReason: () => buildReason,
|
|
7137
|
+
classifyToken: () => classifyToken,
|
|
7138
|
+
classifyTokens: () => classifyTokens,
|
|
6992
7139
|
composeIntroAcceptedEmail: () => composeIntroAcceptedEmail,
|
|
6993
7140
|
composeIntroEmail: () => composeIntroEmail,
|
|
6994
7141
|
computeAcceptanceCredential: () => computeAcceptanceCredential,
|
|
@@ -6999,6 +7146,7 @@ __export(src_exports, {
|
|
|
6999
7146
|
decryptMessage: () => decryptMessage,
|
|
7000
7147
|
deriveLegibleProfile: () => deriveLegibleProfile,
|
|
7001
7148
|
deriveResumeTrend: () => deriveResumeTrend,
|
|
7149
|
+
deriveRigorTiers: () => deriveRigorTiers,
|
|
7002
7150
|
deriveSharedKey: () => deriveSharedKey,
|
|
7003
7151
|
deriveTrajectoryNarrative: () => deriveTrajectoryNarrative,
|
|
7004
7152
|
displayableDrift: () => displayableDrift,
|
|
@@ -7078,6 +7226,7 @@ var init_src = __esm({
|
|
|
7078
7226
|
init_job_status();
|
|
7079
7227
|
init_legible();
|
|
7080
7228
|
init_legible_trajectory();
|
|
7229
|
+
init_rigor();
|
|
7081
7230
|
init_short_token();
|
|
7082
7231
|
}
|
|
7083
7232
|
});
|
|
@@ -7090,9 +7239,9 @@ var init_keytar = __esm({
|
|
|
7090
7239
|
}
|
|
7091
7240
|
});
|
|
7092
7241
|
|
|
7093
|
-
// node-file:/Users/ericgang/job-placement-inline
|
|
7242
|
+
// node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
|
|
7094
7243
|
var require_keytar = __commonJS({
|
|
7095
|
-
"node-file:/Users/ericgang/job-placement-inline
|
|
7244
|
+
"node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
7096
7245
|
"use strict";
|
|
7097
7246
|
init_keytar();
|
|
7098
7247
|
try {
|
|
@@ -7512,36 +7661,46 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
|
7512
7661
|
console.log(` Claim: ${sanitizeText(b.claimUrl ?? job.url)}`);
|
|
7513
7662
|
console.log(` \u2192 terminalhire claim ${ref}`);
|
|
7514
7663
|
}
|
|
7664
|
+
async function getBounties({ quiet = false, offline = false } = {}) {
|
|
7665
|
+
if (!quiet) console.log(`Fetching bounty index from ${API_URL}/api/index...`);
|
|
7666
|
+
const index = offline ? readIndexCache() : await fetchIndex();
|
|
7667
|
+
if (offline && !index) return { status: "no-cache" };
|
|
7668
|
+
let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");
|
|
7669
|
+
if (PRICED_ONLY) bounties = bounties.filter((j) => j.bounty?.amountUSD != null);
|
|
7670
|
+
if (WINNABLE_ONLY) bounties = bounties.filter((j) => (j.bounty?.competingOpenPRs ?? 0) === 0);
|
|
7671
|
+
if (bounties.length === 0) {
|
|
7672
|
+
return { status: "empty" };
|
|
7673
|
+
}
|
|
7674
|
+
const ranked = /* @__PURE__ */ new Map();
|
|
7675
|
+
try {
|
|
7676
|
+
const { readProfile: readProfile2, profileToFingerprint: profileToFingerprint2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
|
|
7677
|
+
const { match: match2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
7678
|
+
const profile = await readProfile2();
|
|
7679
|
+
if (profile.skillTags.length > 0) {
|
|
7680
|
+
const fp = profileToFingerprint2(profile);
|
|
7681
|
+
for (const r of match2(fp, bounties, bounties.length)) {
|
|
7682
|
+
ranked.set(r.job.id, { score: r.score, reason: r.reason, matchedTags: r.matchedTags });
|
|
7683
|
+
}
|
|
7684
|
+
}
|
|
7685
|
+
} catch {
|
|
7686
|
+
}
|
|
7687
|
+
const score = (j) => ranked.get(j.id)?.score ?? 0;
|
|
7688
|
+
const amt = (j) => j.bounty?.amountUSD ?? -1;
|
|
7689
|
+
const contested = (j) => (j.bounty?.competingOpenPRs ?? 0) > 0 ? 1 : 0;
|
|
7690
|
+
bounties.sort((a, b) => contested(a) - contested(b) || score(b) - score(a) || amt(b) - amt(a));
|
|
7691
|
+
const matchedCount = bounties.filter((j) => score(j) > 0).length;
|
|
7692
|
+
return { status: "ok", bounties, ranked, matchedCount };
|
|
7693
|
+
}
|
|
7515
7694
|
async function run() {
|
|
7516
7695
|
try {
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");
|
|
7520
|
-
if (PRICED_ONLY) bounties = bounties.filter((j) => j.bounty?.amountUSD != null);
|
|
7521
|
-
if (WINNABLE_ONLY) bounties = bounties.filter((j) => (j.bounty?.competingOpenPRs ?? 0) === 0);
|
|
7522
|
-
if (bounties.length === 0) {
|
|
7696
|
+
const result = await getBounties();
|
|
7697
|
+
if (result.status === "empty") {
|
|
7523
7698
|
console.log("\nNo bounties available right now. Try again later \u2014 supply refreshes through the day.");
|
|
7524
7699
|
return;
|
|
7525
7700
|
}
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
const { readProfile: readProfile2, profileToFingerprint: profileToFingerprint2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
|
|
7529
|
-
const { match: match2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
7530
|
-
const profile = await readProfile2();
|
|
7531
|
-
if (profile.skillTags.length > 0) {
|
|
7532
|
-
const fp = profileToFingerprint2(profile);
|
|
7533
|
-
for (const r of match2(fp, bounties, bounties.length)) {
|
|
7534
|
-
ranked.set(r.job.id, { score: r.score, reason: r.reason, matchedTags: r.matchedTags });
|
|
7535
|
-
}
|
|
7536
|
-
}
|
|
7537
|
-
} catch {
|
|
7538
|
-
}
|
|
7539
|
-
const score = (j) => ranked.get(j.id)?.score ?? 0;
|
|
7540
|
-
const amt = (j) => j.bounty?.amountUSD ?? -1;
|
|
7541
|
-
const contested = (j) => (j.bounty?.competingOpenPRs ?? 0) > 0 ? 1 : 0;
|
|
7542
|
-
bounties.sort((a, b) => contested(a) - contested(b) || score(b) - score(a) || amt(b) - amt(a));
|
|
7701
|
+
if (result.status !== "ok") return;
|
|
7702
|
+
const { bounties, ranked, matchedCount } = result;
|
|
7543
7703
|
const shown = SHOW_ALL ? bounties : bounties.slice(0, LIMIT);
|
|
7544
|
-
const matchedCount = bounties.filter((j) => score(j) > 0).length;
|
|
7545
7704
|
console.log(
|
|
7546
7705
|
`
|
|
7547
7706
|
\u26A1 ${bounties.length} bount${bounties.length === 1 ? "y" : "ies"} you could knock out` + (matchedCount ? ` \u2014 ${matchedCount} matched to your profile` : "") + ` (local rank \u2014 no data sent)
|
|
@@ -7573,6 +7732,7 @@ Open this to claim/work the bounty (you go straight to the source \u2014 we neve
|
|
|
7573
7732
|
}
|
|
7574
7733
|
}
|
|
7575
7734
|
export {
|
|
7735
|
+
getBounties,
|
|
7576
7736
|
run
|
|
7577
7737
|
};
|
|
7578
7738
|
/*! Bundled license information:
|
|
@@ -183,7 +183,7 @@ var init_graph_data = __esm({
|
|
|
183
183
|
{ id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
|
|
184
184
|
{ id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
|
|
185
185
|
{ id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
|
|
186
|
-
{ id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
|
|
186
|
+
{ id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
|
|
187
187
|
{ id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
|
|
188
188
|
{ id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
|
|
189
189
|
{ id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
|
|
@@ -396,6 +396,14 @@ var init_idf_background = __esm({
|
|
|
396
396
|
}
|
|
397
397
|
});
|
|
398
398
|
|
|
399
|
+
// ../../packages/core/src/vocab/classify.ts
|
|
400
|
+
var init_classify = __esm({
|
|
401
|
+
"../../packages/core/src/vocab/classify.ts"() {
|
|
402
|
+
"use strict";
|
|
403
|
+
init_vocab();
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
399
407
|
// ../../packages/core/src/vocab/index.ts
|
|
400
408
|
var GRAPH, VOCABULARY, SYNONYMS;
|
|
401
409
|
var init_vocab = __esm({
|
|
@@ -408,6 +416,7 @@ var init_vocab = __esm({
|
|
|
408
416
|
init_graph_data();
|
|
409
417
|
init_extract();
|
|
410
418
|
init_idf_background();
|
|
419
|
+
init_classify();
|
|
411
420
|
GRAPH = buildGraph(VOCAB_NODES);
|
|
412
421
|
VOCABULARY = [...GRAPH.ids];
|
|
413
422
|
SYNONYMS = Object.fromEntries(GRAPH.synonyms);
|
|
@@ -462,6 +471,21 @@ var init_contribution_gate = __esm({
|
|
|
462
471
|
}
|
|
463
472
|
});
|
|
464
473
|
|
|
474
|
+
// ../../packages/core/src/credential/rigor.ts
|
|
475
|
+
var RIGOR, MAINTAINER_SET;
|
|
476
|
+
var init_rigor = __esm({
|
|
477
|
+
"../../packages/core/src/credential/rigor.ts"() {
|
|
478
|
+
"use strict";
|
|
479
|
+
RIGOR = {
|
|
480
|
+
/** `authorAssociation` values that count as a maintainer review. */
|
|
481
|
+
MAINTAINER_ASSOCIATIONS: ["OWNER", "MEMBER", "COLLABORATOR"]
|
|
482
|
+
};
|
|
483
|
+
MAINTAINER_SET = new Set(
|
|
484
|
+
RIGOR.MAINTAINER_ASSOCIATIONS.map((a) => a.toUpperCase())
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
465
489
|
// ../../packages/core/src/github.ts
|
|
466
490
|
var RESUME_DECAY_HALF_LIFE_MS;
|
|
467
491
|
var init_github = __esm({
|
|
@@ -469,6 +493,7 @@ var init_github = __esm({
|
|
|
469
493
|
"use strict";
|
|
470
494
|
init_vocabulary();
|
|
471
495
|
init_contribution_gate();
|
|
496
|
+
init_rigor();
|
|
472
497
|
RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
473
498
|
}
|
|
474
499
|
});
|
|
@@ -3963,6 +3988,7 @@ var init_src = __esm({
|
|
|
3963
3988
|
init_job_status();
|
|
3964
3989
|
init_legible();
|
|
3965
3990
|
init_legible_trajectory();
|
|
3991
|
+
init_rigor();
|
|
3966
3992
|
init_short_token();
|
|
3967
3993
|
}
|
|
3968
3994
|
});
|
|
@@ -3975,9 +4001,9 @@ var init_keytar = __esm({
|
|
|
3975
4001
|
}
|
|
3976
4002
|
});
|
|
3977
4003
|
|
|
3978
|
-
// node-file:/Users/ericgang/job-placement-inline
|
|
4004
|
+
// node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
|
|
3979
4005
|
var require_keytar = __commonJS({
|
|
3980
|
-
"node-file:/Users/ericgang/job-placement-inline
|
|
4006
|
+
"node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
3981
4007
|
"use strict";
|
|
3982
4008
|
init_keytar();
|
|
3983
4009
|
try {
|
|
@@ -4439,14 +4465,62 @@ var init_config = __esm({
|
|
|
4439
4465
|
}
|
|
4440
4466
|
});
|
|
4441
4467
|
|
|
4468
|
+
// bin/tui-core.js
|
|
4469
|
+
function sanitizeLine(text) {
|
|
4470
|
+
return String(text).replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(ANSI_OTHER, "").replace(C0_C1_DEL, "");
|
|
4471
|
+
}
|
|
4472
|
+
var ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, PALETTE, COLOR_ROLES;
|
|
4473
|
+
var init_tui_core = __esm({
|
|
4474
|
+
"bin/tui-core.js"() {
|
|
4475
|
+
"use strict";
|
|
4476
|
+
ANSI_CSI = /\x1b\[[0-?]*[ -/]*[@-~]/g;
|
|
4477
|
+
ANSI_OSC = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
4478
|
+
ANSI_OTHER = /\x1b[@-_]/g;
|
|
4479
|
+
C0_C1_DEL = /[\x00-\x1f\x7f-\x9f]/g;
|
|
4480
|
+
PALETTE = {
|
|
4481
|
+
truecolor: {
|
|
4482
|
+
bg: "\x1B[48;2;13;17;23m",
|
|
4483
|
+
panel: "\x1B[48;2;22;27;34m",
|
|
4484
|
+
rule: "\x1B[38;2;48;54;61m",
|
|
4485
|
+
text: "\x1B[38;2;201;209;217m",
|
|
4486
|
+
muted: "\x1B[38;2;125;133;144m",
|
|
4487
|
+
accent: "\x1B[38;2;88;166;255m",
|
|
4488
|
+
"accent-bright": "\x1B[38;2;121;192;255m",
|
|
4489
|
+
green: "\x1B[38;2;63;185;80m",
|
|
4490
|
+
amber: "\x1B[38;2;210;153;34m"
|
|
4491
|
+
},
|
|
4492
|
+
256: {
|
|
4493
|
+
bg: "\x1B[48;5;233m",
|
|
4494
|
+
panel: "\x1B[48;5;235m",
|
|
4495
|
+
rule: "\x1B[38;5;240m",
|
|
4496
|
+
text: "\x1B[38;5;252m",
|
|
4497
|
+
muted: "\x1B[38;5;245m",
|
|
4498
|
+
accent: "\x1B[38;5;75m",
|
|
4499
|
+
"accent-bright": "\x1B[38;5;117m",
|
|
4500
|
+
green: "\x1B[38;5;71m",
|
|
4501
|
+
amber: "\x1B[38;5;178m"
|
|
4502
|
+
},
|
|
4503
|
+
16: {
|
|
4504
|
+
bg: "\x1B[40m",
|
|
4505
|
+
panel: "\x1B[100m",
|
|
4506
|
+
rule: "\x1B[90m",
|
|
4507
|
+
text: "\x1B[37m",
|
|
4508
|
+
muted: "\x1B[90m",
|
|
4509
|
+
accent: "\x1B[94m",
|
|
4510
|
+
"accent-bright": "\x1B[96m",
|
|
4511
|
+
green: "\x1B[92m",
|
|
4512
|
+
amber: "\x1B[93m"
|
|
4513
|
+
}
|
|
4514
|
+
};
|
|
4515
|
+
COLOR_ROLES = Object.keys(PALETTE.truecolor);
|
|
4516
|
+
}
|
|
4517
|
+
});
|
|
4518
|
+
|
|
4442
4519
|
// bin/jpi-chat.js
|
|
4443
4520
|
import { createInterface } from "readline";
|
|
4444
4521
|
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
4445
4522
|
import { homedir as homedir6 } from "os";
|
|
4446
4523
|
import { join as join7 } from "path";
|
|
4447
|
-
function sanitizeLine(text) {
|
|
4448
|
-
return String(text).replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(ANSI_OTHER, "").replace(C0_C1_DEL, "");
|
|
4449
|
-
}
|
|
4450
4524
|
function defaultPromptAck({ input = process.stdin, output = process.stdout } = {}) {
|
|
4451
4525
|
if (!input || input.isTTY !== true) return Promise.resolve(false);
|
|
4452
4526
|
const rl = createInterface({ input, output });
|
|
@@ -4565,19 +4639,16 @@ function formatPresence(presence, now = /* @__PURE__ */ new Date()) {
|
|
|
4565
4639
|
}
|
|
4566
4640
|
return "\u25D0 reachable";
|
|
4567
4641
|
}
|
|
4568
|
-
var CHAT_BASE2, GH_SESSION_COOKIE2,
|
|
4642
|
+
var CHAT_BASE2, GH_SESSION_COOKIE2, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, ACTIVE_WINDOW_MS;
|
|
4569
4643
|
var init_jpi_chat = __esm({
|
|
4570
4644
|
"bin/jpi-chat.js"() {
|
|
4571
4645
|
"use strict";
|
|
4572
4646
|
init_chat_client();
|
|
4573
4647
|
init_config();
|
|
4574
4648
|
init_web_session();
|
|
4649
|
+
init_tui_core();
|
|
4575
4650
|
CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
|
|
4576
4651
|
GH_SESSION_COOKIE2 = "__jpi_gh_session";
|
|
4577
|
-
ANSI_CSI = /\x1b\[[0-?]*[ -/]*[@-~]/g;
|
|
4578
|
-
ANSI_OSC = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
4579
|
-
ANSI_OTHER = /\x1b[@-_]/g;
|
|
4580
|
-
C0_C1_DEL = /[\x00-\x1f\x7f-\x9f]/g;
|
|
4581
4652
|
CHAT_DISCLOSURE = "Messages are end-to-end encrypted using keys stored only on your device. Our server cannot read message content. Since we distribute your contact's public key, verify your connection by comparing Safety Numbers to rule out a server-side substitution. We store metadata: who messaged whom, when, and message count. Content is purged after 90 days.";
|
|
4582
4653
|
CHAT_AT_REST = "Your private key is encrypted against casual access, not full machine compromise.";
|
|
4583
4654
|
CHAT_CODE_OF_CONDUCT = "Code of conduct: keep it professional \u2014 harassment, spam, or abuse gets you blocked and removed.";
|