terminalhire 0.42.1 → 0.42.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.
- package/dist/bin/claim-push-bg.js +3 -2
- package/dist/bin/jpi-bounties.js +59 -7
- package/dist/bin/jpi-claim.js +22 -10
- package/dist/bin/jpi-contribute.js +5 -3
- package/dist/bin/jpi-devs.js +2 -1
- package/dist/bin/jpi-dispatch.js +147 -30
- package/dist/bin/jpi-hub.js +92 -18
- package/dist/bin/jpi-jobs.js +47 -34
- package/dist/bin/jpi-mcp.js +23 -11
- package/dist/bin/jpi-refresh.js +18 -3
- package/dist/bin/jpi-repo.js +3 -2
- package/dist/bin/sanitize.js +9 -1
- package/dist/bin/spinner-render.js +9 -1
- package/dist/bin/spinner.js +9 -1
- package/dist/src/claims.js +2 -1
- package/package.json +1 -1
|
@@ -167,7 +167,7 @@ function nowISO() {
|
|
|
167
167
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
168
168
|
}
|
|
169
169
|
function defangText(s) {
|
|
170
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS, "") : s;
|
|
170
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "") : s;
|
|
171
171
|
}
|
|
172
172
|
function finiteAmount(a) {
|
|
173
173
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -305,7 +305,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
305
305
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
306
306
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
307
307
|
}
|
|
308
|
-
var TERMINALHIRE_DIR3, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS;
|
|
308
|
+
var TERMINALHIRE_DIR3, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
309
309
|
var init_claims = __esm({
|
|
310
310
|
"src/claims.ts"() {
|
|
311
311
|
"use strict";
|
|
@@ -361,6 +361,7 @@ var init_claims = __esm({
|
|
|
361
361
|
]),
|
|
362
362
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
363
363
|
};
|
|
364
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
364
365
|
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
365
366
|
}
|
|
366
367
|
});
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -11339,7 +11339,7 @@ function nowISO2() {
|
|
|
11339
11339
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
11340
11340
|
}
|
|
11341
11341
|
function defangText(s) {
|
|
11342
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS2, "") : s;
|
|
11342
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
11343
11343
|
}
|
|
11344
11344
|
function finiteAmount(a) {
|
|
11345
11345
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -11477,7 +11477,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
11477
11477
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
11478
11478
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
11479
11479
|
}
|
|
11480
|
-
var TERMINALHIRE_DIR5, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS2;
|
|
11480
|
+
var TERMINALHIRE_DIR5, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS2, CONTROL_CHARS2;
|
|
11481
11481
|
var init_claims = __esm({
|
|
11482
11482
|
"src/claims.ts"() {
|
|
11483
11483
|
"use strict";
|
|
@@ -11533,6 +11533,7 @@ var init_claims = __esm({
|
|
|
11533
11533
|
]),
|
|
11534
11534
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
11535
11535
|
};
|
|
11536
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
11536
11537
|
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11537
11538
|
}
|
|
11538
11539
|
});
|
|
@@ -11748,17 +11749,38 @@ var init_founder_paid_badge = __esm({
|
|
|
11748
11749
|
|
|
11749
11750
|
// bin/jpi-bounties.js
|
|
11750
11751
|
init_src();
|
|
11751
|
-
init_cache_store();
|
|
11752
11752
|
import { readFileSync as readFileSync7 } from "fs";
|
|
11753
11753
|
import { join as join10 } from "path";
|
|
11754
11754
|
import { homedir as homedir7 } from "os";
|
|
11755
11755
|
import { createInterface } from "readline";
|
|
11756
11756
|
|
|
11757
|
+
// ../../packages/core/src/payout-split.ts
|
|
11758
|
+
var PLATFORM_TAKE_BPS = 1e3;
|
|
11759
|
+
function platformFeeCents(totalCents) {
|
|
11760
|
+
return Math.ceil(totalCents * PLATFORM_TAKE_BPS / 1e4);
|
|
11761
|
+
}
|
|
11762
|
+
function developerShareCents(totalCents) {
|
|
11763
|
+
return totalCents - platformFeeCents(totalCents);
|
|
11764
|
+
}
|
|
11765
|
+
function formatCents(cents) {
|
|
11766
|
+
return cents % 100 === 0 ? `$${cents / 100}` : `$${(cents / 100).toFixed(2)}`;
|
|
11767
|
+
}
|
|
11768
|
+
|
|
11769
|
+
// bin/jpi-bounties.js
|
|
11770
|
+
init_cache_store();
|
|
11771
|
+
|
|
11757
11772
|
// bin/sanitize.js
|
|
11773
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
11758
11774
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11759
11775
|
function sanitizeText(s) {
|
|
11760
11776
|
if (s == null) return "";
|
|
11761
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
11777
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
11778
|
+
}
|
|
11779
|
+
function formatUsd(a) {
|
|
11780
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
11781
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
11782
|
+
const n = Number(a);
|
|
11783
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
11762
11784
|
}
|
|
11763
11785
|
function safeHttpUrl(url) {
|
|
11764
11786
|
if (url == null) return null;
|
|
@@ -11831,13 +11853,33 @@ function prompt(question) {
|
|
|
11831
11853
|
});
|
|
11832
11854
|
}
|
|
11833
11855
|
function formatAmount(b) {
|
|
11834
|
-
return b.amountUSD
|
|
11856
|
+
return formatUsd(b.amountUSD);
|
|
11835
11857
|
}
|
|
11836
11858
|
var EFFORT_LABEL = {
|
|
11837
11859
|
small: "small (~\xBD day)",
|
|
11838
11860
|
medium: "medium (~1 day)",
|
|
11839
11861
|
large: "large (multi-day)"
|
|
11840
11862
|
};
|
|
11863
|
+
function founderClaimBlurb(amountUSD, paidWork) {
|
|
11864
|
+
if (paidWork === false) {
|
|
11865
|
+
return "Claim it from here \u2014 this posting records a credential for the work, not a payment. Take it for the credential, not the money.";
|
|
11866
|
+
}
|
|
11867
|
+
if (paidWork !== true) {
|
|
11868
|
+
return "Claim it from here \u2014 this listing is missing its payment status, so it is not safe to say whether the work pays. Try `terminalhire refresh`; if it is still missing, do not count on being paid for this one.";
|
|
11869
|
+
}
|
|
11870
|
+
let share = "";
|
|
11871
|
+
if (typeof amountUSD === "number" && Number.isFinite(amountUSD) && amountUSD > 0) {
|
|
11872
|
+
share = ` You'd receive ${formatCents(developerShareCents(Math.round(amountUSD * 100)))} of the ${formatCents(Math.round(amountUSD * 100))} posted; terminalhire keeps 10%.`;
|
|
11873
|
+
}
|
|
11874
|
+
return `Claim it from here \u2014 the founder pays through terminalhire rather than off-platform, and their acceptance is what triggers your payout.${share}`;
|
|
11875
|
+
}
|
|
11876
|
+
function founderClaimBlock(job) {
|
|
11877
|
+
const ref = opportunityShortToken(job.id);
|
|
11878
|
+
return `
|
|
11879
|
+
${founderClaimBlurb(job.bounty?.amountUSD, job.bounty?.paidWork)}
|
|
11880
|
+
terminalhire claim ${ref}
|
|
11881
|
+
${sanitizeText(job.bounty?.claimUrl ?? job.url)}`;
|
|
11882
|
+
}
|
|
11841
11883
|
function printBounty(i, job, score, reason, matchedTags, claimedIds = /* @__PURE__ */ new Set(), continuityNote = null) {
|
|
11842
11884
|
const b = job.bounty ?? {};
|
|
11843
11885
|
const stars = b.repoStars != null ? ` \xB7 ${b.repoStars}\u2605` : "";
|
|
@@ -11980,7 +12022,9 @@ async function run() {
|
|
|
11980
12022
|
const rows = founderRows2(surface, "bounties");
|
|
11981
12023
|
console.log("\n\u26A1 Your TerminalHire postings\n");
|
|
11982
12024
|
if (!rows.length) {
|
|
11983
|
-
console.log(
|
|
12025
|
+
console.log(
|
|
12026
|
+
" No current posting data. Run `terminalhire refresh`, or lead with work:"
|
|
12027
|
+
);
|
|
11984
12028
|
console.log(" terminalhire config set lead dev\n");
|
|
11985
12029
|
} else {
|
|
11986
12030
|
rows.forEach((row, index) => {
|
|
@@ -11989,7 +12033,9 @@ async function run() {
|
|
|
11989
12033
|
);
|
|
11990
12034
|
});
|
|
11991
12035
|
console.log("\n Review and act: https://terminalhire.com/dashboard?tab=postings");
|
|
11992
|
-
console.log(
|
|
12036
|
+
console.log(
|
|
12037
|
+
" Lead with developer bounties instead: terminalhire config set lead dev\n"
|
|
12038
|
+
);
|
|
11993
12039
|
}
|
|
11994
12040
|
return;
|
|
11995
12041
|
}
|
|
@@ -12064,6 +12110,10 @@ Enter a number to open a bounty's claim page, or press Enter to exit: `
|
|
|
12064
12110
|
const idx = parseInt(pick, 10) - 1;
|
|
12065
12111
|
if (Number.isNaN(idx) || idx < 0 || idx >= shown.length) return;
|
|
12066
12112
|
const chosen = shown[idx];
|
|
12113
|
+
if (chosen.bounty?.bountySource === "founder") {
|
|
12114
|
+
console.log(founderClaimBlock(chosen));
|
|
12115
|
+
return;
|
|
12116
|
+
}
|
|
12067
12117
|
console.log(
|
|
12068
12118
|
`
|
|
12069
12119
|
Open this to claim/work the bounty (you go straight to the source \u2014 we never touch payment):
|
|
@@ -12079,6 +12129,8 @@ export {
|
|
|
12079
12129
|
classifyEmptyStatus,
|
|
12080
12130
|
continuityNoteForRow,
|
|
12081
12131
|
filterPaidVisibility,
|
|
12132
|
+
founderClaimBlock,
|
|
12133
|
+
founderClaimBlurb,
|
|
12082
12134
|
getBounties,
|
|
12083
12135
|
isPinnedFounderBounty,
|
|
12084
12136
|
printBounty,
|
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -10639,7 +10639,7 @@ function nowISO() {
|
|
|
10639
10639
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
10640
10640
|
}
|
|
10641
10641
|
function defangText(s) {
|
|
10642
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS2, "") : s;
|
|
10642
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
10643
10643
|
}
|
|
10644
10644
|
function finiteAmount(a) {
|
|
10645
10645
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -10777,7 +10777,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
10777
10777
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
10778
10778
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
10779
10779
|
}
|
|
10780
|
-
var TERMINALHIRE_DIR2, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS2;
|
|
10780
|
+
var TERMINALHIRE_DIR2, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS2, CONTROL_CHARS2;
|
|
10781
10781
|
var init_claims = __esm({
|
|
10782
10782
|
"src/claims.ts"() {
|
|
10783
10783
|
"use strict";
|
|
@@ -10833,6 +10833,7 @@ var init_claims = __esm({
|
|
|
10833
10833
|
]),
|
|
10834
10834
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
10835
10835
|
};
|
|
10836
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
10836
10837
|
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
10837
10838
|
}
|
|
10838
10839
|
});
|
|
@@ -26151,10 +26152,17 @@ function openInBrowser(url) {
|
|
|
26151
26152
|
}
|
|
26152
26153
|
|
|
26153
26154
|
// bin/sanitize.js
|
|
26155
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
26154
26156
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
26155
26157
|
function sanitizeText(s) {
|
|
26156
26158
|
if (s == null) return "";
|
|
26157
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
26159
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
26160
|
+
}
|
|
26161
|
+
function formatUsd(a) {
|
|
26162
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
26163
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
26164
|
+
const n = Number(a);
|
|
26165
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
26158
26166
|
}
|
|
26159
26167
|
|
|
26160
26168
|
// src/policy-acks.ts
|
|
@@ -27081,10 +27089,7 @@ async function pollPR(prUrl) {
|
|
|
27081
27089
|
}
|
|
27082
27090
|
}
|
|
27083
27091
|
function fmtAmount(a) {
|
|
27084
|
-
|
|
27085
|
-
if (typeof a === "string" && a.trim() === "") return "$\u2014";
|
|
27086
|
-
const n = typeof a === "number" ? a : Number(a);
|
|
27087
|
-
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
27092
|
+
return formatUsd(a);
|
|
27088
27093
|
}
|
|
27089
27094
|
function fmtClaimAmount(c) {
|
|
27090
27095
|
return c.kind === "contribution" ? "contribution" : fmtAmount(c.amountUSD);
|
|
@@ -27225,8 +27230,15 @@ async function resolveBounty(arg) {
|
|
|
27225
27230
|
return {
|
|
27226
27231
|
bountyId,
|
|
27227
27232
|
indexNativeId,
|
|
27228
|
-
|
|
27229
|
-
|
|
27233
|
+
// DEFANGED HERE, at the one place every tier of this resolver converges.
|
|
27234
|
+
// `claims.ts` cleans what comes OUT of the local store, which covers every later
|
|
27235
|
+
// read — but this object is printed (the preview card, the record card) and
|
|
27236
|
+
// handed to `recordClaim` BEFORE any store exists for it, so on a claim's first
|
|
27237
|
+
// use the store boundary has not run yet. `repoFullName` also goes on to be
|
|
27238
|
+
// interpolated into GitHub API URLs from here. Found by a cross-model review of
|
|
27239
|
+
// TERM-380; the store fix alone left this path open.
|
|
27240
|
+
title: sanitizeText(title),
|
|
27241
|
+
repoFullName: repoFullName == null ? repoFullName : sanitizeText(repoFullName),
|
|
27230
27242
|
issueUrl,
|
|
27231
27243
|
amountUSD,
|
|
27232
27244
|
source,
|
|
@@ -28466,7 +28478,7 @@ async function cmdStart(id, flags = {}) {
|
|
|
28466
28478
|
console.error(`terminalhire claim: no claim with id '${id}'.`);
|
|
28467
28479
|
process.exit(1);
|
|
28468
28480
|
}
|
|
28469
|
-
if (claim.approval?.state === "pending"
|
|
28481
|
+
if (claim.approval?.state === "pending") {
|
|
28470
28482
|
({ approvalsChecked, approvalsUnavailable } = await syncFounderApprovals(claims, [claim]));
|
|
28471
28483
|
claim = claims.findClaim(id);
|
|
28472
28484
|
}
|
|
@@ -3618,7 +3618,7 @@ function nowISO2() {
|
|
|
3618
3618
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3619
3619
|
}
|
|
3620
3620
|
function defangText(s) {
|
|
3621
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS2, "") : s;
|
|
3621
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
3622
3622
|
}
|
|
3623
3623
|
function finiteAmount(a) {
|
|
3624
3624
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -3756,7 +3756,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
3756
3756
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
3757
3757
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
3758
3758
|
}
|
|
3759
|
-
var TERMINALHIRE_DIR7, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS2;
|
|
3759
|
+
var TERMINALHIRE_DIR7, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS2, CONTROL_CHARS2;
|
|
3760
3760
|
var init_claims = __esm({
|
|
3761
3761
|
"src/claims.ts"() {
|
|
3762
3762
|
"use strict";
|
|
@@ -3812,6 +3812,7 @@ var init_claims = __esm({
|
|
|
3812
3812
|
]),
|
|
3813
3813
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
3814
3814
|
};
|
|
3815
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
3815
3816
|
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
3816
3817
|
}
|
|
3817
3818
|
});
|
|
@@ -3896,10 +3897,11 @@ function isContributeEnabled() {
|
|
|
3896
3897
|
init_state_dir();
|
|
3897
3898
|
|
|
3898
3899
|
// bin/sanitize.js
|
|
3900
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
3899
3901
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
3900
3902
|
function sanitizeText(s) {
|
|
3901
3903
|
if (s == null) return "";
|
|
3902
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
3904
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
3903
3905
|
}
|
|
3904
3906
|
function safeHttpUrl(url) {
|
|
3905
3907
|
if (url == null) return null;
|
package/dist/bin/jpi-devs.js
CHANGED
|
@@ -11053,10 +11053,11 @@ function excludeOwnCard(results, ownLogin) {
|
|
|
11053
11053
|
}
|
|
11054
11054
|
|
|
11055
11055
|
// bin/sanitize.js
|
|
11056
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
11056
11057
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11057
11058
|
function sanitizeText(s) {
|
|
11058
11059
|
if (s == null) return "";
|
|
11059
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
11060
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
11060
11061
|
}
|
|
11061
11062
|
function safeHttpUrl(url) {
|
|
11062
11063
|
if (url == null) return null;
|
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -12831,7 +12831,13 @@ var init_cache_store = __esm({
|
|
|
12831
12831
|
// bin/sanitize.js
|
|
12832
12832
|
function sanitizeText(s) {
|
|
12833
12833
|
if (s == null) return "";
|
|
12834
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
12834
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
12835
|
+
}
|
|
12836
|
+
function formatUsd(a) {
|
|
12837
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
12838
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
12839
|
+
const n = Number(a);
|
|
12840
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
12835
12841
|
}
|
|
12836
12842
|
function safeHttpUrl(url) {
|
|
12837
12843
|
if (url == null) return null;
|
|
@@ -12857,10 +12863,11 @@ function linkTitle(title, url) {
|
|
|
12857
12863
|
}
|
|
12858
12864
|
return href ? `${safeTitle} (${href})` : safeTitle;
|
|
12859
12865
|
}
|
|
12860
|
-
var CONTROL_CHARS;
|
|
12866
|
+
var WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
12861
12867
|
var init_sanitize = __esm({
|
|
12862
12868
|
"bin/sanitize.js"() {
|
|
12863
12869
|
"use strict";
|
|
12870
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
12864
12871
|
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
12865
12872
|
}
|
|
12866
12873
|
});
|
|
@@ -13578,7 +13585,7 @@ function buildTipsDetailed(topMatches, baseUrl, max = 8, opts = {}) {
|
|
|
13578
13585
|
const token = jobShortToken(String(m.id));
|
|
13579
13586
|
const url = `${base}/j/${token}`;
|
|
13580
13587
|
if (source === "bounty") {
|
|
13581
|
-
const money =
|
|
13588
|
+
const money = formatUsd(m.amountUSD);
|
|
13582
13589
|
const repo = m.repo || companyRaw;
|
|
13583
13590
|
out.push(`\u{1F48E} ${money} \xB7 ${title} \xB7 ${repo} \xB7 ${pct2}% \u2014 ${url}`);
|
|
13584
13591
|
} else if (source === "contribute") {
|
|
@@ -13648,6 +13655,7 @@ var init_spinner_render = __esm({
|
|
|
13648
13655
|
init_spinner_verbs();
|
|
13649
13656
|
init_spinner_seen();
|
|
13650
13657
|
init_spinner_io();
|
|
13658
|
+
init_sanitize();
|
|
13651
13659
|
init_src();
|
|
13652
13660
|
}
|
|
13653
13661
|
});
|
|
@@ -14853,6 +14861,24 @@ var init_jpi_project = __esm({
|
|
|
14853
14861
|
}
|
|
14854
14862
|
});
|
|
14855
14863
|
|
|
14864
|
+
// ../../packages/core/src/payout-split.ts
|
|
14865
|
+
function platformFeeCents(totalCents) {
|
|
14866
|
+
return Math.ceil(totalCents * PLATFORM_TAKE_BPS / 1e4);
|
|
14867
|
+
}
|
|
14868
|
+
function developerShareCents(totalCents) {
|
|
14869
|
+
return totalCents - platformFeeCents(totalCents);
|
|
14870
|
+
}
|
|
14871
|
+
function formatCents(cents) {
|
|
14872
|
+
return cents % 100 === 0 ? `$${cents / 100}` : `$${(cents / 100).toFixed(2)}`;
|
|
14873
|
+
}
|
|
14874
|
+
var PLATFORM_TAKE_BPS;
|
|
14875
|
+
var init_payout_split = __esm({
|
|
14876
|
+
"../../packages/core/src/payout-split.ts"() {
|
|
14877
|
+
"use strict";
|
|
14878
|
+
PLATFORM_TAKE_BPS = 1e3;
|
|
14879
|
+
}
|
|
14880
|
+
});
|
|
14881
|
+
|
|
14856
14882
|
// bin/founder-pin.js
|
|
14857
14883
|
function isPinnedFounderBounty(j) {
|
|
14858
14884
|
return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
|
|
@@ -15182,7 +15208,7 @@ function nowISO2() {
|
|
|
15182
15208
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
15183
15209
|
}
|
|
15184
15210
|
function defangText(s) {
|
|
15185
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS2, "") : s;
|
|
15211
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
15186
15212
|
}
|
|
15187
15213
|
function finiteAmount(a) {
|
|
15188
15214
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -15320,7 +15346,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
15320
15346
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
15321
15347
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
15322
15348
|
}
|
|
15323
|
-
var TERMINALHIRE_DIR11, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS2, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS2;
|
|
15349
|
+
var TERMINALHIRE_DIR11, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS2, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS2, CONTROL_CHARS2;
|
|
15324
15350
|
var init_claims = __esm({
|
|
15325
15351
|
"src/claims.ts"() {
|
|
15326
15352
|
"use strict";
|
|
@@ -15376,6 +15402,7 @@ var init_claims = __esm({
|
|
|
15376
15402
|
]),
|
|
15377
15403
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
15378
15404
|
};
|
|
15405
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
15379
15406
|
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
15380
15407
|
}
|
|
15381
15408
|
});
|
|
@@ -15424,6 +15451,8 @@ __export(jpi_bounties_exports, {
|
|
|
15424
15451
|
classifyEmptyStatus: () => classifyEmptyStatus,
|
|
15425
15452
|
continuityNoteForRow: () => continuityNoteForRow,
|
|
15426
15453
|
filterPaidVisibility: () => filterPaidVisibility,
|
|
15454
|
+
founderClaimBlock: () => founderClaimBlock,
|
|
15455
|
+
founderClaimBlurb: () => founderClaimBlurb,
|
|
15427
15456
|
getBounties: () => getBounties,
|
|
15428
15457
|
isPinnedFounderBounty: () => isPinnedFounderBounty,
|
|
15429
15458
|
printBounty: () => printBounty,
|
|
@@ -15465,7 +15494,27 @@ function prompt3(question) {
|
|
|
15465
15494
|
});
|
|
15466
15495
|
}
|
|
15467
15496
|
function formatAmount(b) {
|
|
15468
|
-
return b.amountUSD
|
|
15497
|
+
return formatUsd(b.amountUSD);
|
|
15498
|
+
}
|
|
15499
|
+
function founderClaimBlurb(amountUSD, paidWork) {
|
|
15500
|
+
if (paidWork === false) {
|
|
15501
|
+
return "Claim it from here \u2014 this posting records a credential for the work, not a payment. Take it for the credential, not the money.";
|
|
15502
|
+
}
|
|
15503
|
+
if (paidWork !== true) {
|
|
15504
|
+
return "Claim it from here \u2014 this listing is missing its payment status, so it is not safe to say whether the work pays. Try `terminalhire refresh`; if it is still missing, do not count on being paid for this one.";
|
|
15505
|
+
}
|
|
15506
|
+
let share = "";
|
|
15507
|
+
if (typeof amountUSD === "number" && Number.isFinite(amountUSD) && amountUSD > 0) {
|
|
15508
|
+
share = ` You'd receive ${formatCents(developerShareCents(Math.round(amountUSD * 100)))} of the ${formatCents(Math.round(amountUSD * 100))} posted; terminalhire keeps 10%.`;
|
|
15509
|
+
}
|
|
15510
|
+
return `Claim it from here \u2014 the founder pays through terminalhire rather than off-platform, and their acceptance is what triggers your payout.${share}`;
|
|
15511
|
+
}
|
|
15512
|
+
function founderClaimBlock(job) {
|
|
15513
|
+
const ref = opportunityShortToken(job.id);
|
|
15514
|
+
return `
|
|
15515
|
+
${founderClaimBlurb(job.bounty?.amountUSD, job.bounty?.paidWork)}
|
|
15516
|
+
terminalhire claim ${ref}
|
|
15517
|
+
${sanitizeText(job.bounty?.claimUrl ?? job.url)}`;
|
|
15469
15518
|
}
|
|
15470
15519
|
function printBounty(i, job, score, reason, matchedTags, claimedIds = /* @__PURE__ */ new Set(), continuityNote = null) {
|
|
15471
15520
|
const b = job.bounty ?? {};
|
|
@@ -15609,7 +15658,9 @@ async function run5() {
|
|
|
15609
15658
|
const rows = founderRows2(surface, "bounties");
|
|
15610
15659
|
console.log("\n\u26A1 Your TerminalHire postings\n");
|
|
15611
15660
|
if (!rows.length) {
|
|
15612
|
-
console.log(
|
|
15661
|
+
console.log(
|
|
15662
|
+
" No current posting data. Run `terminalhire refresh`, or lead with work:"
|
|
15663
|
+
);
|
|
15613
15664
|
console.log(" terminalhire config set lead dev\n");
|
|
15614
15665
|
} else {
|
|
15615
15666
|
rows.forEach((row, index) => {
|
|
@@ -15618,7 +15669,9 @@ async function run5() {
|
|
|
15618
15669
|
);
|
|
15619
15670
|
});
|
|
15620
15671
|
console.log("\n Review and act: https://terminalhire.com/dashboard?tab=postings");
|
|
15621
|
-
console.log(
|
|
15672
|
+
console.log(
|
|
15673
|
+
" Lead with developer bounties instead: terminalhire config set lead dev\n"
|
|
15674
|
+
);
|
|
15622
15675
|
}
|
|
15623
15676
|
return;
|
|
15624
15677
|
}
|
|
@@ -15693,6 +15746,10 @@ Enter a number to open a bounty's claim page, or press Enter to exit: `
|
|
|
15693
15746
|
const idx = parseInt(pick2, 10) - 1;
|
|
15694
15747
|
if (Number.isNaN(idx) || idx < 0 || idx >= shown.length) return;
|
|
15695
15748
|
const chosen = shown[idx];
|
|
15749
|
+
if (chosen.bounty?.bountySource === "founder") {
|
|
15750
|
+
console.log(founderClaimBlock(chosen));
|
|
15751
|
+
return;
|
|
15752
|
+
}
|
|
15696
15753
|
console.log(
|
|
15697
15754
|
`
|
|
15698
15755
|
Open this to claim/work the bounty (you go straight to the source \u2014 we never touch payment):
|
|
@@ -15708,6 +15765,7 @@ var init_jpi_bounties = __esm({
|
|
|
15708
15765
|
"bin/jpi-bounties.js"() {
|
|
15709
15766
|
"use strict";
|
|
15710
15767
|
init_src();
|
|
15768
|
+
init_payout_split();
|
|
15711
15769
|
init_cache_store();
|
|
15712
15770
|
init_sanitize();
|
|
15713
15771
|
init_founder_pin();
|
|
@@ -31679,10 +31737,7 @@ async function pollPR(prUrl) {
|
|
|
31679
31737
|
}
|
|
31680
31738
|
}
|
|
31681
31739
|
function fmtAmount(a) {
|
|
31682
|
-
|
|
31683
|
-
if (typeof a === "string" && a.trim() === "") return "$\u2014";
|
|
31684
|
-
const n = typeof a === "number" ? a : Number(a);
|
|
31685
|
-
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
31740
|
+
return formatUsd(a);
|
|
31686
31741
|
}
|
|
31687
31742
|
function fmtClaimAmount(c) {
|
|
31688
31743
|
return c.kind === "contribution" ? "contribution" : fmtAmount(c.amountUSD);
|
|
@@ -31821,8 +31876,15 @@ async function resolveBounty(arg) {
|
|
|
31821
31876
|
return {
|
|
31822
31877
|
bountyId,
|
|
31823
31878
|
indexNativeId,
|
|
31824
|
-
|
|
31825
|
-
|
|
31879
|
+
// DEFANGED HERE, at the one place every tier of this resolver converges.
|
|
31880
|
+
// `claims.ts` cleans what comes OUT of the local store, which covers every later
|
|
31881
|
+
// read — but this object is printed (the preview card, the record card) and
|
|
31882
|
+
// handed to `recordClaim` BEFORE any store exists for it, so on a claim's first
|
|
31883
|
+
// use the store boundary has not run yet. `repoFullName` also goes on to be
|
|
31884
|
+
// interpolated into GitHub API URLs from here. Found by a cross-model review of
|
|
31885
|
+
// TERM-380; the store fix alone left this path open.
|
|
31886
|
+
title: sanitizeText(title),
|
|
31887
|
+
repoFullName: repoFullName == null ? repoFullName : sanitizeText(repoFullName),
|
|
31826
31888
|
issueUrl,
|
|
31827
31889
|
amountUSD,
|
|
31828
31890
|
source,
|
|
@@ -33043,7 +33105,7 @@ async function cmdStart(id, flags = {}) {
|
|
|
33043
33105
|
console.error(`terminalhire claim: no claim with id '${id}'.`);
|
|
33044
33106
|
process.exit(1);
|
|
33045
33107
|
}
|
|
33046
|
-
if (claim.approval?.state === "pending"
|
|
33108
|
+
if (claim.approval?.state === "pending") {
|
|
33047
33109
|
({ approvalsChecked, approvalsUnavailable } = await syncFounderApprovals(claims, [claim]));
|
|
33048
33110
|
claim = claims.findClaim(id);
|
|
33049
33111
|
}
|
|
@@ -39891,7 +39953,12 @@ function substrMatch(query, candidate) {
|
|
|
39891
39953
|
if (query === "") return true;
|
|
39892
39954
|
return candidate.toLowerCase().includes(query.toLowerCase());
|
|
39893
39955
|
}
|
|
39894
|
-
function runHubTui({
|
|
39956
|
+
function runHubTui({
|
|
39957
|
+
input = process.stdin,
|
|
39958
|
+
output = process.stdout,
|
|
39959
|
+
signals,
|
|
39960
|
+
deps = {}
|
|
39961
|
+
} = {}) {
|
|
39895
39962
|
const {
|
|
39896
39963
|
listClaims: _listClaims = listClaims,
|
|
39897
39964
|
acceptedPRRate: _acceptedPRRate = acceptedPRRate,
|
|
@@ -40054,20 +40121,50 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40054
40121
|
acked = false;
|
|
40055
40122
|
}
|
|
40056
40123
|
if (!acked) {
|
|
40057
|
-
inboxState = {
|
|
40124
|
+
inboxState = {
|
|
40125
|
+
loaded: true,
|
|
40126
|
+
loading: false,
|
|
40127
|
+
status: "disclosure",
|
|
40128
|
+
items: null,
|
|
40129
|
+
message: null
|
|
40130
|
+
};
|
|
40058
40131
|
return;
|
|
40059
40132
|
}
|
|
40060
40133
|
inboxState = { ...inboxState, loading: true };
|
|
40061
40134
|
_buildInboxItems().then((built) => {
|
|
40062
40135
|
if (built.status === "ok") {
|
|
40063
|
-
inboxState = {
|
|
40136
|
+
inboxState = {
|
|
40137
|
+
loaded: true,
|
|
40138
|
+
loading: false,
|
|
40139
|
+
status: "ok",
|
|
40140
|
+
items: built.items,
|
|
40141
|
+
message: null
|
|
40142
|
+
};
|
|
40064
40143
|
} else if (built.status === "error") {
|
|
40065
|
-
inboxState = {
|
|
40144
|
+
inboxState = {
|
|
40145
|
+
loaded: true,
|
|
40146
|
+
loading: false,
|
|
40147
|
+
status: "error",
|
|
40148
|
+
items: null,
|
|
40149
|
+
message: built.message || "could not load inbox"
|
|
40150
|
+
};
|
|
40066
40151
|
} else {
|
|
40067
|
-
inboxState = {
|
|
40152
|
+
inboxState = {
|
|
40153
|
+
loaded: true,
|
|
40154
|
+
loading: false,
|
|
40155
|
+
status: built.status,
|
|
40156
|
+
items: null,
|
|
40157
|
+
message: null
|
|
40158
|
+
};
|
|
40068
40159
|
}
|
|
40069
40160
|
}).catch((e) => {
|
|
40070
|
-
inboxState = {
|
|
40161
|
+
inboxState = {
|
|
40162
|
+
loaded: true,
|
|
40163
|
+
loading: false,
|
|
40164
|
+
status: "error",
|
|
40165
|
+
items: null,
|
|
40166
|
+
message: errMsg(e)
|
|
40167
|
+
};
|
|
40071
40168
|
}).finally(() => repaint());
|
|
40072
40169
|
return;
|
|
40073
40170
|
}
|
|
@@ -40101,7 +40198,9 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40101
40198
|
function inboxRows(st) {
|
|
40102
40199
|
switch (st.status) {
|
|
40103
40200
|
case "disclosure":
|
|
40104
|
-
return [
|
|
40201
|
+
return [
|
|
40202
|
+
"Messaging disclosure not yet acknowledged \u2014 run `terminalhire inbox` once to review it and enable messages."
|
|
40203
|
+
];
|
|
40105
40204
|
case "not-linked":
|
|
40106
40205
|
return ["Not linked \u2014 run `terminalhire link` to connect your web session."];
|
|
40107
40206
|
case "expired":
|
|
@@ -40144,11 +40243,13 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40144
40243
|
case "empty":
|
|
40145
40244
|
return ["No bounties available right now. Check back through the day."];
|
|
40146
40245
|
case "demoted":
|
|
40147
|
-
return [
|
|
40246
|
+
return [
|
|
40247
|
+
"Paid bounties paused \u2014 run `bounties --priced` to view them. Try Contribute or Jobs."
|
|
40248
|
+
];
|
|
40148
40249
|
case "ok":
|
|
40149
40250
|
return result.bounties.map((job) => {
|
|
40150
40251
|
const b = job.bounty || {};
|
|
40151
|
-
const amt = b.amountUSD
|
|
40252
|
+
const amt = formatUsd(b.amountUSD);
|
|
40152
40253
|
const repo = sanitizeLine(b.repoFullName || job.company);
|
|
40153
40254
|
const prs = b.competingOpenPRs;
|
|
40154
40255
|
const contend = prs != null && prs > 0 ? ` \xB7 \u26A0 ${prs} in flight` : "";
|
|
@@ -40203,7 +40304,9 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40203
40304
|
if (it.note) rows.push(` note: ${sanitizeLine(it.note)}`);
|
|
40204
40305
|
if (it.contact) rows.push(` contact: ${sanitizeLine(it.contact)}`);
|
|
40205
40306
|
else if (it.role === "incoming" && it.status === "pending") {
|
|
40206
|
-
rows.push(
|
|
40307
|
+
rows.push(
|
|
40308
|
+
` \u2192 accept: terminalhire intro --accept @${sanitizeLine(it.counterpartyLogin)}`
|
|
40309
|
+
);
|
|
40207
40310
|
}
|
|
40208
40311
|
}
|
|
40209
40312
|
return rows;
|
|
@@ -40290,7 +40393,8 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40290
40393
|
if (name === "Claims") {
|
|
40291
40394
|
if (!claimsState.loaded) return ["Loading\u2026"];
|
|
40292
40395
|
if (claimsState.error) return ["Could not read claims \u2014 " + claimsState.error];
|
|
40293
|
-
if (!claimsState.rows.length)
|
|
40396
|
+
if (!claimsState.rows.length)
|
|
40397
|
+
return ["No claims yet \u2014 run `terminalhire claim <url>` to start one."];
|
|
40294
40398
|
return claimsState.rows.map(formatClaimRow);
|
|
40295
40399
|
}
|
|
40296
40400
|
if (name === "Profile") {
|
|
@@ -40320,8 +40424,10 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40320
40424
|
const st = listState[name];
|
|
40321
40425
|
if (st.loaded && !st.error && st.result && st.result.status === "ok") {
|
|
40322
40426
|
if (name === "Jobs") return `${st.result.ranked.length} roles matching your profile`;
|
|
40323
|
-
if (name === "Bounties")
|
|
40324
|
-
|
|
40427
|
+
if (name === "Bounties")
|
|
40428
|
+
return `${st.result.bounties.length} bounties you could knock out`;
|
|
40429
|
+
if (name === "Devs")
|
|
40430
|
+
return `${st.result.results.length} matches in the builder directory`;
|
|
40325
40431
|
}
|
|
40326
40432
|
return name;
|
|
40327
40433
|
}
|
|
@@ -40351,7 +40457,9 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
40351
40457
|
const row = startRow + i;
|
|
40352
40458
|
if (row < 0 || row >= rows) continue;
|
|
40353
40459
|
const t = TH_GLYPH.length <= 1 ? 0 : i / (TH_GLYPH.length - 1);
|
|
40354
|
-
drawText(buf, cols, row, startCol, TH_GLYPH[i], {
|
|
40460
|
+
drawText(buf, cols, row, startCol, TH_GLYPH[i], {
|
|
40461
|
+
fg: gradientFg(BRAND_GRADIENT, t, level)
|
|
40462
|
+
});
|
|
40355
40463
|
}
|
|
40356
40464
|
const hint = "press any key to continue";
|
|
40357
40465
|
const hintRow = Math.min(rows - 1, startRow + TH_GLYPH.length + 1);
|
|
@@ -40805,6 +40913,7 @@ var init_jpi_hub = __esm({
|
|
|
40805
40913
|
"bin/jpi-hub.js"() {
|
|
40806
40914
|
"use strict";
|
|
40807
40915
|
init_tui_core();
|
|
40916
|
+
init_sanitize();
|
|
40808
40917
|
init_claims();
|
|
40809
40918
|
init_profile();
|
|
40810
40919
|
init_config();
|
|
@@ -40842,7 +40951,15 @@ var init_jpi_hub = __esm({
|
|
|
40842
40951
|
];
|
|
40843
40952
|
BRAND_GRADIENT = ["#9d8fff", "#7c6af7", "#5b4fcf"];
|
|
40844
40953
|
DEFAULT_SPLASH_MS = 900;
|
|
40845
|
-
STATE_LEVEL = {
|
|
40954
|
+
STATE_LEVEL = {
|
|
40955
|
+
abandoned: 0,
|
|
40956
|
+
claimed: 2,
|
|
40957
|
+
working: 3,
|
|
40958
|
+
"in-review": 4,
|
|
40959
|
+
ready: 5,
|
|
40960
|
+
submitted: 6,
|
|
40961
|
+
merged: 7
|
|
40962
|
+
};
|
|
40846
40963
|
SPARK_LEVELS = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
|
|
40847
40964
|
}
|
|
40848
40965
|
});
|
package/dist/bin/jpi-hub.js
CHANGED
|
@@ -380,6 +380,19 @@ var init_tui_core = __esm({
|
|
|
380
380
|
}
|
|
381
381
|
});
|
|
382
382
|
|
|
383
|
+
// bin/sanitize.js
|
|
384
|
+
function formatUsd(a) {
|
|
385
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
386
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
387
|
+
const n = Number(a);
|
|
388
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
389
|
+
}
|
|
390
|
+
var init_sanitize = __esm({
|
|
391
|
+
"bin/sanitize.js"() {
|
|
392
|
+
"use strict";
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
383
396
|
// src/state-dir.ts
|
|
384
397
|
import { closeSync, constants, fchmodSync, fstatSync, mkdirSync, openSync } from "fs";
|
|
385
398
|
function warnStateDirOnce(dir, message) {
|
|
@@ -539,7 +552,7 @@ function nowISO() {
|
|
|
539
552
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
540
553
|
}
|
|
541
554
|
function defangText(s) {
|
|
542
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS, "") : s;
|
|
555
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "") : s;
|
|
543
556
|
}
|
|
544
557
|
function finiteAmount(a) {
|
|
545
558
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -677,7 +690,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
677
690
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
678
691
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
679
692
|
}
|
|
680
|
-
var TERMINALHIRE_DIR, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS;
|
|
693
|
+
var TERMINALHIRE_DIR, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
681
694
|
var init_claims = __esm({
|
|
682
695
|
"src/claims.ts"() {
|
|
683
696
|
"use strict";
|
|
@@ -733,6 +746,7 @@ var init_claims = __esm({
|
|
|
733
746
|
]),
|
|
734
747
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
735
748
|
};
|
|
749
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
736
750
|
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
737
751
|
}
|
|
738
752
|
});
|
|
@@ -12649,6 +12663,7 @@ var init_intro2 = __esm({
|
|
|
12649
12663
|
|
|
12650
12664
|
// bin/jpi-hub.js
|
|
12651
12665
|
init_tui_core();
|
|
12666
|
+
init_sanitize();
|
|
12652
12667
|
init_claims();
|
|
12653
12668
|
init_profile();
|
|
12654
12669
|
init_config();
|
|
@@ -12685,6 +12700,7 @@ var BAK_FILE = `${STATUS_FILE}.bak`;
|
|
|
12685
12700
|
|
|
12686
12701
|
// bin/jpi-jobs.js
|
|
12687
12702
|
init_cache_store();
|
|
12703
|
+
init_sanitize();
|
|
12688
12704
|
var __dirname = fileURLToPath2(new URL(".", import.meta.url));
|
|
12689
12705
|
var TERMINALHIRE_DIR11 = process.env.TERMINALHIRE_DIR || join16(homedir13(), ".terminalhire");
|
|
12690
12706
|
var INDEX_CACHE_FILE3 = join16(TERMINALHIRE_DIR11, "index-cache.json");
|
|
@@ -12771,11 +12787,12 @@ async function getJobMatches({ quiet = false, offline = false } = {}) {
|
|
|
12771
12787
|
|
|
12772
12788
|
// bin/jpi-bounties.js
|
|
12773
12789
|
init_src();
|
|
12774
|
-
init_cache_store();
|
|
12775
12790
|
import { readFileSync as readFileSync15 } from "fs";
|
|
12776
12791
|
import { join as join18 } from "path";
|
|
12777
12792
|
import { homedir as homedir15 } from "os";
|
|
12778
12793
|
import { createInterface as createInterface3 } from "readline";
|
|
12794
|
+
init_cache_store();
|
|
12795
|
+
init_sanitize();
|
|
12779
12796
|
init_founder_pin();
|
|
12780
12797
|
var TERMINALHIRE_DIR13 = process.env.TERMINALHIRE_DIR || join18(homedir15(), ".terminalhire");
|
|
12781
12798
|
var INDEX_CACHE_FILE4 = join18(TERMINALHIRE_DIR13, "index-cache.json");
|
|
@@ -12970,6 +12987,9 @@ function excludeOwnCard(results, ownLogin) {
|
|
|
12970
12987
|
});
|
|
12971
12988
|
}
|
|
12972
12989
|
|
|
12990
|
+
// bin/jpi-devs.js
|
|
12991
|
+
init_sanitize();
|
|
12992
|
+
|
|
12973
12993
|
// bin/match-slots.js
|
|
12974
12994
|
var ROTATE_WINDOW_MS = 5 * 60 * 1e3;
|
|
12975
12995
|
var ROLE_HEAD_ROTATE_MS = 60 * 60 * 1e3;
|
|
@@ -13081,7 +13101,15 @@ var TH_GLYPH = [
|
|
|
13081
13101
|
];
|
|
13082
13102
|
var BRAND_GRADIENT = ["#9d8fff", "#7c6af7", "#5b4fcf"];
|
|
13083
13103
|
var DEFAULT_SPLASH_MS = 900;
|
|
13084
|
-
var STATE_LEVEL = {
|
|
13104
|
+
var STATE_LEVEL = {
|
|
13105
|
+
abandoned: 0,
|
|
13106
|
+
claimed: 2,
|
|
13107
|
+
working: 3,
|
|
13108
|
+
"in-review": 4,
|
|
13109
|
+
ready: 5,
|
|
13110
|
+
submitted: 6,
|
|
13111
|
+
merged: 7
|
|
13112
|
+
};
|
|
13085
13113
|
var SPARK_LEVELS = ["\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"];
|
|
13086
13114
|
function sparkline(rows) {
|
|
13087
13115
|
if (!rows || !rows.length) return "";
|
|
@@ -13103,7 +13131,12 @@ function substrMatch(query, candidate) {
|
|
|
13103
13131
|
if (query === "") return true;
|
|
13104
13132
|
return candidate.toLowerCase().includes(query.toLowerCase());
|
|
13105
13133
|
}
|
|
13106
|
-
function runHubTui({
|
|
13134
|
+
function runHubTui({
|
|
13135
|
+
input = process.stdin,
|
|
13136
|
+
output = process.stdout,
|
|
13137
|
+
signals,
|
|
13138
|
+
deps = {}
|
|
13139
|
+
} = {}) {
|
|
13107
13140
|
const {
|
|
13108
13141
|
listClaims: _listClaims = listClaims,
|
|
13109
13142
|
acceptedPRRate: _acceptedPRRate = acceptedPRRate,
|
|
@@ -13266,20 +13299,50 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13266
13299
|
acked = false;
|
|
13267
13300
|
}
|
|
13268
13301
|
if (!acked) {
|
|
13269
|
-
inboxState = {
|
|
13302
|
+
inboxState = {
|
|
13303
|
+
loaded: true,
|
|
13304
|
+
loading: false,
|
|
13305
|
+
status: "disclosure",
|
|
13306
|
+
items: null,
|
|
13307
|
+
message: null
|
|
13308
|
+
};
|
|
13270
13309
|
return;
|
|
13271
13310
|
}
|
|
13272
13311
|
inboxState = { ...inboxState, loading: true };
|
|
13273
13312
|
_buildInboxItems().then((built) => {
|
|
13274
13313
|
if (built.status === "ok") {
|
|
13275
|
-
inboxState = {
|
|
13314
|
+
inboxState = {
|
|
13315
|
+
loaded: true,
|
|
13316
|
+
loading: false,
|
|
13317
|
+
status: "ok",
|
|
13318
|
+
items: built.items,
|
|
13319
|
+
message: null
|
|
13320
|
+
};
|
|
13276
13321
|
} else if (built.status === "error") {
|
|
13277
|
-
inboxState = {
|
|
13322
|
+
inboxState = {
|
|
13323
|
+
loaded: true,
|
|
13324
|
+
loading: false,
|
|
13325
|
+
status: "error",
|
|
13326
|
+
items: null,
|
|
13327
|
+
message: built.message || "could not load inbox"
|
|
13328
|
+
};
|
|
13278
13329
|
} else {
|
|
13279
|
-
inboxState = {
|
|
13330
|
+
inboxState = {
|
|
13331
|
+
loaded: true,
|
|
13332
|
+
loading: false,
|
|
13333
|
+
status: built.status,
|
|
13334
|
+
items: null,
|
|
13335
|
+
message: null
|
|
13336
|
+
};
|
|
13280
13337
|
}
|
|
13281
13338
|
}).catch((e) => {
|
|
13282
|
-
inboxState = {
|
|
13339
|
+
inboxState = {
|
|
13340
|
+
loaded: true,
|
|
13341
|
+
loading: false,
|
|
13342
|
+
status: "error",
|
|
13343
|
+
items: null,
|
|
13344
|
+
message: errMsg(e)
|
|
13345
|
+
};
|
|
13283
13346
|
}).finally(() => repaint());
|
|
13284
13347
|
return;
|
|
13285
13348
|
}
|
|
@@ -13313,7 +13376,9 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13313
13376
|
function inboxRows(st) {
|
|
13314
13377
|
switch (st.status) {
|
|
13315
13378
|
case "disclosure":
|
|
13316
|
-
return [
|
|
13379
|
+
return [
|
|
13380
|
+
"Messaging disclosure not yet acknowledged \u2014 run `terminalhire inbox` once to review it and enable messages."
|
|
13381
|
+
];
|
|
13317
13382
|
case "not-linked":
|
|
13318
13383
|
return ["Not linked \u2014 run `terminalhire link` to connect your web session."];
|
|
13319
13384
|
case "expired":
|
|
@@ -13356,11 +13421,13 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13356
13421
|
case "empty":
|
|
13357
13422
|
return ["No bounties available right now. Check back through the day."];
|
|
13358
13423
|
case "demoted":
|
|
13359
|
-
return [
|
|
13424
|
+
return [
|
|
13425
|
+
"Paid bounties paused \u2014 run `bounties --priced` to view them. Try Contribute or Jobs."
|
|
13426
|
+
];
|
|
13360
13427
|
case "ok":
|
|
13361
13428
|
return result.bounties.map((job) => {
|
|
13362
13429
|
const b = job.bounty || {};
|
|
13363
|
-
const amt = b.amountUSD
|
|
13430
|
+
const amt = formatUsd(b.amountUSD);
|
|
13364
13431
|
const repo = sanitizeLine(b.repoFullName || job.company);
|
|
13365
13432
|
const prs = b.competingOpenPRs;
|
|
13366
13433
|
const contend = prs != null && prs > 0 ? ` \xB7 \u26A0 ${prs} in flight` : "";
|
|
@@ -13415,7 +13482,9 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13415
13482
|
if (it.note) rows.push(` note: ${sanitizeLine(it.note)}`);
|
|
13416
13483
|
if (it.contact) rows.push(` contact: ${sanitizeLine(it.contact)}`);
|
|
13417
13484
|
else if (it.role === "incoming" && it.status === "pending") {
|
|
13418
|
-
rows.push(
|
|
13485
|
+
rows.push(
|
|
13486
|
+
` \u2192 accept: terminalhire intro --accept @${sanitizeLine(it.counterpartyLogin)}`
|
|
13487
|
+
);
|
|
13419
13488
|
}
|
|
13420
13489
|
}
|
|
13421
13490
|
return rows;
|
|
@@ -13502,7 +13571,8 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13502
13571
|
if (name === "Claims") {
|
|
13503
13572
|
if (!claimsState.loaded) return ["Loading\u2026"];
|
|
13504
13573
|
if (claimsState.error) return ["Could not read claims \u2014 " + claimsState.error];
|
|
13505
|
-
if (!claimsState.rows.length)
|
|
13574
|
+
if (!claimsState.rows.length)
|
|
13575
|
+
return ["No claims yet \u2014 run `terminalhire claim <url>` to start one."];
|
|
13506
13576
|
return claimsState.rows.map(formatClaimRow);
|
|
13507
13577
|
}
|
|
13508
13578
|
if (name === "Profile") {
|
|
@@ -13532,8 +13602,10 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13532
13602
|
const st = listState[name];
|
|
13533
13603
|
if (st.loaded && !st.error && st.result && st.result.status === "ok") {
|
|
13534
13604
|
if (name === "Jobs") return `${st.result.ranked.length} roles matching your profile`;
|
|
13535
|
-
if (name === "Bounties")
|
|
13536
|
-
|
|
13605
|
+
if (name === "Bounties")
|
|
13606
|
+
return `${st.result.bounties.length} bounties you could knock out`;
|
|
13607
|
+
if (name === "Devs")
|
|
13608
|
+
return `${st.result.results.length} matches in the builder directory`;
|
|
13537
13609
|
}
|
|
13538
13610
|
return name;
|
|
13539
13611
|
}
|
|
@@ -13563,7 +13635,9 @@ function runHubTui({ input = process.stdin, output = process.stdout, signals, de
|
|
|
13563
13635
|
const row = startRow + i;
|
|
13564
13636
|
if (row < 0 || row >= rows) continue;
|
|
13565
13637
|
const t = TH_GLYPH.length <= 1 ? 0 : i / (TH_GLYPH.length - 1);
|
|
13566
|
-
drawText(buf, cols, row, startCol, TH_GLYPH[i], {
|
|
13638
|
+
drawText(buf, cols, row, startCol, TH_GLYPH[i], {
|
|
13639
|
+
fg: gradientFg(BRAND_GRADIENT, t, level)
|
|
13640
|
+
});
|
|
13567
13641
|
}
|
|
13568
13642
|
const hint = "press any key to continue";
|
|
13569
13643
|
const hintRow = Math.min(rows - 1, startRow + TH_GLYPH.length + 1);
|
package/dist/bin/jpi-jobs.js
CHANGED
|
@@ -10578,6 +10578,50 @@ var init_cache_store = __esm({
|
|
|
10578
10578
|
}
|
|
10579
10579
|
});
|
|
10580
10580
|
|
|
10581
|
+
// bin/sanitize.js
|
|
10582
|
+
function sanitizeText(s) {
|
|
10583
|
+
if (s == null) return "";
|
|
10584
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
10585
|
+
}
|
|
10586
|
+
function formatUsd(a) {
|
|
10587
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
10588
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
10589
|
+
const n = Number(a);
|
|
10590
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
10591
|
+
}
|
|
10592
|
+
function safeHttpUrl(url) {
|
|
10593
|
+
if (url == null) return null;
|
|
10594
|
+
const raw = String(url);
|
|
10595
|
+
CONTROL_CHARS.lastIndex = 0;
|
|
10596
|
+
if (CONTROL_CHARS.test(raw)) return null;
|
|
10597
|
+
let parsed;
|
|
10598
|
+
try {
|
|
10599
|
+
parsed = new URL(raw);
|
|
10600
|
+
} catch {
|
|
10601
|
+
return null;
|
|
10602
|
+
}
|
|
10603
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
|
|
10604
|
+
return parsed.href;
|
|
10605
|
+
}
|
|
10606
|
+
function linkTitle(title, url) {
|
|
10607
|
+
const safeTitle = sanitizeText(title);
|
|
10608
|
+
const href = safeHttpUrl(url);
|
|
10609
|
+
const isTTY = process.stdout.isTTY;
|
|
10610
|
+
const noColor = process.env["NO_COLOR"] !== void 0;
|
|
10611
|
+
if (isTTY && !noColor && href) {
|
|
10612
|
+
return `\x1B]8;;${href}\x1B\\${safeTitle}\x1B]8;;\x1B\\`;
|
|
10613
|
+
}
|
|
10614
|
+
return href ? `${safeTitle} (${href})` : safeTitle;
|
|
10615
|
+
}
|
|
10616
|
+
var WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
10617
|
+
var init_sanitize = __esm({
|
|
10618
|
+
"bin/sanitize.js"() {
|
|
10619
|
+
"use strict";
|
|
10620
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
10621
|
+
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
10622
|
+
}
|
|
10623
|
+
});
|
|
10624
|
+
|
|
10581
10625
|
// bin/spinner-io.js
|
|
10582
10626
|
import {
|
|
10583
10627
|
readFileSync as readFileSync4,
|
|
@@ -11291,7 +11335,7 @@ function buildTipsDetailed(topMatches, baseUrl, max = 8, opts = {}) {
|
|
|
11291
11335
|
const token = jobShortToken(String(m.id));
|
|
11292
11336
|
const url = `${base}/j/${token}`;
|
|
11293
11337
|
if (source === "bounty") {
|
|
11294
|
-
const money =
|
|
11338
|
+
const money = formatUsd(m.amountUSD);
|
|
11295
11339
|
const repo = m.repo || companyRaw;
|
|
11296
11340
|
out.push(`\u{1F48E} ${money} \xB7 ${title} \xB7 ${repo} \xB7 ${pct}% \u2014 ${url}`);
|
|
11297
11341
|
} else if (source === "contribute") {
|
|
@@ -11361,6 +11405,7 @@ var init_spinner_render = __esm({
|
|
|
11361
11405
|
init_spinner_verbs();
|
|
11362
11406
|
init_spinner_seen();
|
|
11363
11407
|
init_spinner_io();
|
|
11408
|
+
init_sanitize();
|
|
11364
11409
|
init_src();
|
|
11365
11410
|
}
|
|
11366
11411
|
});
|
|
@@ -12297,39 +12342,7 @@ function markClicked(id) {
|
|
|
12297
12342
|
|
|
12298
12343
|
// bin/jpi-jobs.js
|
|
12299
12344
|
init_cache_store();
|
|
12300
|
-
|
|
12301
|
-
// bin/sanitize.js
|
|
12302
|
-
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
12303
|
-
function sanitizeText(s) {
|
|
12304
|
-
if (s == null) return "";
|
|
12305
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
12306
|
-
}
|
|
12307
|
-
function safeHttpUrl(url) {
|
|
12308
|
-
if (url == null) return null;
|
|
12309
|
-
const raw = String(url);
|
|
12310
|
-
CONTROL_CHARS.lastIndex = 0;
|
|
12311
|
-
if (CONTROL_CHARS.test(raw)) return null;
|
|
12312
|
-
let parsed;
|
|
12313
|
-
try {
|
|
12314
|
-
parsed = new URL(raw);
|
|
12315
|
-
} catch {
|
|
12316
|
-
return null;
|
|
12317
|
-
}
|
|
12318
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
|
|
12319
|
-
return parsed.href;
|
|
12320
|
-
}
|
|
12321
|
-
function linkTitle(title, url) {
|
|
12322
|
-
const safeTitle = sanitizeText(title);
|
|
12323
|
-
const href = safeHttpUrl(url);
|
|
12324
|
-
const isTTY = process.stdout.isTTY;
|
|
12325
|
-
const noColor = process.env["NO_COLOR"] !== void 0;
|
|
12326
|
-
if (isTTY && !noColor && href) {
|
|
12327
|
-
return `\x1B]8;;${href}\x1B\\${safeTitle}\x1B]8;;\x1B\\`;
|
|
12328
|
-
}
|
|
12329
|
-
return href ? `${safeTitle} (${href})` : safeTitle;
|
|
12330
|
-
}
|
|
12331
|
-
|
|
12332
|
-
// bin/jpi-jobs.js
|
|
12345
|
+
init_sanitize();
|
|
12333
12346
|
var __dirname2 = fileURLToPath3(new URL(".", import.meta.url));
|
|
12334
12347
|
var TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join14(homedir9(), ".terminalhire");
|
|
12335
12348
|
var INDEX_CACHE_FILE2 = join14(TERMINALHIRE_DIR6, "index-cache.json");
|
package/dist/bin/jpi-mcp.js
CHANGED
|
@@ -10980,12 +10980,19 @@ var init_open_url = __esm({
|
|
|
10980
10980
|
// bin/sanitize.js
|
|
10981
10981
|
function sanitizeText(s) {
|
|
10982
10982
|
if (s == null) return "";
|
|
10983
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
10983
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
10984
10984
|
}
|
|
10985
|
-
|
|
10985
|
+
function formatUsd(a) {
|
|
10986
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
10987
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
10988
|
+
const n = Number(a);
|
|
10989
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
10990
|
+
}
|
|
10991
|
+
var WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
10986
10992
|
var init_sanitize = __esm({
|
|
10987
10993
|
"bin/sanitize.js"() {
|
|
10988
10994
|
"use strict";
|
|
10995
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
10989
10996
|
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
10990
10997
|
}
|
|
10991
10998
|
});
|
|
@@ -11141,7 +11148,7 @@ function nowISO() {
|
|
|
11141
11148
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
11142
11149
|
}
|
|
11143
11150
|
function defangText(s) {
|
|
11144
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS2, "") : s;
|
|
11151
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
11145
11152
|
}
|
|
11146
11153
|
function finiteAmount(a) {
|
|
11147
11154
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -11279,7 +11286,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
11279
11286
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
11280
11287
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
11281
11288
|
}
|
|
11282
|
-
var TERMINALHIRE_DIR5, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS2;
|
|
11289
|
+
var TERMINALHIRE_DIR5, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS2, CONTROL_CHARS2;
|
|
11283
11290
|
var init_claims = __esm({
|
|
11284
11291
|
"src/claims.ts"() {
|
|
11285
11292
|
"use strict";
|
|
@@ -11335,6 +11342,7 @@ var init_claims = __esm({
|
|
|
11335
11342
|
]),
|
|
11336
11343
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
11337
11344
|
};
|
|
11345
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
11338
11346
|
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11339
11347
|
}
|
|
11340
11348
|
});
|
|
@@ -27157,10 +27165,7 @@ async function pollPR(prUrl) {
|
|
|
27157
27165
|
}
|
|
27158
27166
|
}
|
|
27159
27167
|
function fmtAmount(a) {
|
|
27160
|
-
|
|
27161
|
-
if (typeof a === "string" && a.trim() === "") return "$\u2014";
|
|
27162
|
-
const n = typeof a === "number" ? a : Number(a);
|
|
27163
|
-
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
27168
|
+
return formatUsd(a);
|
|
27164
27169
|
}
|
|
27165
27170
|
function fmtClaimAmount(c) {
|
|
27166
27171
|
return c.kind === "contribution" ? "contribution" : fmtAmount(c.amountUSD);
|
|
@@ -27299,8 +27304,15 @@ async function resolveBounty(arg) {
|
|
|
27299
27304
|
return {
|
|
27300
27305
|
bountyId,
|
|
27301
27306
|
indexNativeId,
|
|
27302
|
-
|
|
27303
|
-
|
|
27307
|
+
// DEFANGED HERE, at the one place every tier of this resolver converges.
|
|
27308
|
+
// `claims.ts` cleans what comes OUT of the local store, which covers every later
|
|
27309
|
+
// read — but this object is printed (the preview card, the record card) and
|
|
27310
|
+
// handed to `recordClaim` BEFORE any store exists for it, so on a claim's first
|
|
27311
|
+
// use the store boundary has not run yet. `repoFullName` also goes on to be
|
|
27312
|
+
// interpolated into GitHub API URLs from here. Found by a cross-model review of
|
|
27313
|
+
// TERM-380; the store fix alone left this path open.
|
|
27314
|
+
title: sanitizeText(title),
|
|
27315
|
+
repoFullName: repoFullName == null ? repoFullName : sanitizeText(repoFullName),
|
|
27304
27316
|
issueUrl,
|
|
27305
27317
|
amountUSD,
|
|
27306
27318
|
source,
|
|
@@ -28521,7 +28533,7 @@ async function cmdStart(id, flags = {}) {
|
|
|
28521
28533
|
console.error(`terminalhire claim: no claim with id '${id}'.`);
|
|
28522
28534
|
process.exit(1);
|
|
28523
28535
|
}
|
|
28524
|
-
if (claim.approval?.state === "pending"
|
|
28536
|
+
if (claim.approval?.state === "pending") {
|
|
28525
28537
|
({ approvalsChecked, approvalsUnavailable } = await syncFounderApprovals(claims, [claim]));
|
|
28526
28538
|
claim = claims.findClaim(id);
|
|
28527
28539
|
}
|
package/dist/bin/jpi-refresh.js
CHANGED
|
@@ -12236,6 +12236,19 @@ var init_spinner_verbs = __esm({
|
|
|
12236
12236
|
}
|
|
12237
12237
|
});
|
|
12238
12238
|
|
|
12239
|
+
// bin/sanitize.js
|
|
12240
|
+
function formatUsd(a) {
|
|
12241
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
12242
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
12243
|
+
const n = Number(a);
|
|
12244
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
12245
|
+
}
|
|
12246
|
+
var init_sanitize = __esm({
|
|
12247
|
+
"bin/sanitize.js"() {
|
|
12248
|
+
"use strict";
|
|
12249
|
+
}
|
|
12250
|
+
});
|
|
12251
|
+
|
|
12239
12252
|
// bin/spinner-render.js
|
|
12240
12253
|
function interleaveBySource(topMatches) {
|
|
12241
12254
|
if (!Array.isArray(topMatches) || topMatches.length === 0) return topMatches;
|
|
@@ -12317,7 +12330,7 @@ function buildTipsDetailed(topMatches, baseUrl, max = 8, opts = {}) {
|
|
|
12317
12330
|
const token = jobShortToken(String(m.id));
|
|
12318
12331
|
const url = `${base}/j/${token}`;
|
|
12319
12332
|
if (source === "bounty") {
|
|
12320
|
-
const money =
|
|
12333
|
+
const money = formatUsd(m.amountUSD);
|
|
12321
12334
|
const repo = m.repo || companyRaw;
|
|
12322
12335
|
out.push(`\u{1F48E} ${money} \xB7 ${title} \xB7 ${repo} \xB7 ${pct}% \u2014 ${url}`);
|
|
12323
12336
|
} else if (source === "contribute") {
|
|
@@ -12387,6 +12400,7 @@ var init_spinner_render = __esm({
|
|
|
12387
12400
|
init_spinner_verbs();
|
|
12388
12401
|
init_spinner_seen();
|
|
12389
12402
|
init_spinner_io();
|
|
12403
|
+
init_sanitize();
|
|
12390
12404
|
init_src();
|
|
12391
12405
|
}
|
|
12392
12406
|
});
|
|
@@ -12563,7 +12577,7 @@ function nowISO() {
|
|
|
12563
12577
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
12564
12578
|
}
|
|
12565
12579
|
function defangText(s) {
|
|
12566
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS, "") : s;
|
|
12580
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "") : s;
|
|
12567
12581
|
}
|
|
12568
12582
|
function finiteAmount(a) {
|
|
12569
12583
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -12701,7 +12715,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
12701
12715
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
12702
12716
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
12703
12717
|
}
|
|
12704
|
-
var TERMINALHIRE_DIR8, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS2, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS;
|
|
12718
|
+
var TERMINALHIRE_DIR8, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS2, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
12705
12719
|
var init_claims = __esm({
|
|
12706
12720
|
"src/claims.ts"() {
|
|
12707
12721
|
"use strict";
|
|
@@ -12757,6 +12771,7 @@ var init_claims = __esm({
|
|
|
12757
12771
|
]),
|
|
12758
12772
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
12759
12773
|
};
|
|
12774
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
12760
12775
|
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
12761
12776
|
}
|
|
12762
12777
|
});
|
package/dist/bin/jpi-repo.js
CHANGED
|
@@ -1910,7 +1910,7 @@ function nowISO2() {
|
|
|
1910
1910
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1911
1911
|
}
|
|
1912
1912
|
function defangText(s) {
|
|
1913
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS, "") : s;
|
|
1913
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "") : s;
|
|
1914
1914
|
}
|
|
1915
1915
|
function finiteAmount(a) {
|
|
1916
1916
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
@@ -2048,7 +2048,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
2048
2048
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
2049
2049
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
2050
2050
|
}
|
|
2051
|
-
var TERMINALHIRE_DIR4, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, CONTROL_CHARS;
|
|
2051
|
+
var TERMINALHIRE_DIR4, CLAIMS_FILE, LOCK_DIR, LOCK_STALE_MS, LOCK_RETRY_MS, LOCK_TIMEOUT_MS, CLAIM_STATES, PUSHED_CLAIM_FIELDS, TERMINAL_STATES, POLL_TRANSITIONS, WHITESPACE_CONTROLS, CONTROL_CHARS;
|
|
2052
2052
|
var init_claims = __esm({
|
|
2053
2053
|
"src/claims.ts"() {
|
|
2054
2054
|
"use strict";
|
|
@@ -2104,6 +2104,7 @@ var init_claims = __esm({
|
|
|
2104
2104
|
]),
|
|
2105
2105
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
2106
2106
|
};
|
|
2107
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
2107
2108
|
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
2108
2109
|
}
|
|
2109
2110
|
});
|
package/dist/bin/sanitize.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
// bin/sanitize.js
|
|
2
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
2
3
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
3
4
|
function sanitizeText(s) {
|
|
4
5
|
if (s == null) return "";
|
|
5
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
6
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
7
|
+
}
|
|
8
|
+
function formatUsd(a) {
|
|
9
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
10
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
11
|
+
const n = Number(a);
|
|
12
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
6
13
|
}
|
|
7
14
|
function safeHttpUrl(url) {
|
|
8
15
|
if (url == null) return null;
|
|
@@ -29,6 +36,7 @@ function linkTitle(title, url) {
|
|
|
29
36
|
return href ? `${safeTitle} (${href})` : safeTitle;
|
|
30
37
|
}
|
|
31
38
|
export {
|
|
39
|
+
formatUsd,
|
|
32
40
|
linkTitle,
|
|
33
41
|
safeHttpUrl,
|
|
34
42
|
sanitizeText
|
|
@@ -607,6 +607,14 @@ function clearSpinnerTips() {
|
|
|
607
607
|
return { cleared: true };
|
|
608
608
|
}
|
|
609
609
|
|
|
610
|
+
// bin/sanitize.js
|
|
611
|
+
function formatUsd(a) {
|
|
612
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
613
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
614
|
+
const n = Number(a);
|
|
615
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
616
|
+
}
|
|
617
|
+
|
|
610
618
|
// ../../packages/core/src/vocab/graph.data.ts
|
|
611
619
|
var VOCAB_NODES = [
|
|
612
620
|
// ── Languages ─────────────────────────────────────────────────────────────
|
|
@@ -1404,7 +1412,7 @@ function buildTipsDetailed(topMatches, baseUrl, max = 8, opts = {}) {
|
|
|
1404
1412
|
const token = jobShortToken(String(m.id));
|
|
1405
1413
|
const url = `${base}/j/${token}`;
|
|
1406
1414
|
if (source === "bounty") {
|
|
1407
|
-
const money =
|
|
1415
|
+
const money = formatUsd(m.amountUSD);
|
|
1408
1416
|
const repo = m.repo || companyRaw;
|
|
1409
1417
|
out.push(`\u{1F48E} ${money} \xB7 ${title} \xB7 ${repo} \xB7 ${pct}% \u2014 ${url}`);
|
|
1410
1418
|
} else if (source === "contribute") {
|
package/dist/bin/spinner.js
CHANGED
|
@@ -635,6 +635,14 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
635
635
|
return withStale(pool);
|
|
636
636
|
}
|
|
637
637
|
|
|
638
|
+
// bin/sanitize.js
|
|
639
|
+
function formatUsd(a) {
|
|
640
|
+
if (typeof a === "number") return Number.isFinite(a) ? "$" + a.toLocaleString() : "$\u2014";
|
|
641
|
+
if (typeof a !== "string" || a.trim() === "") return "$\u2014";
|
|
642
|
+
const n = Number(a);
|
|
643
|
+
return Number.isFinite(n) ? "$" + n.toLocaleString() : "$\u2014";
|
|
644
|
+
}
|
|
645
|
+
|
|
638
646
|
// ../../packages/core/src/vocab/graph.data.ts
|
|
639
647
|
var VOCAB_NODES = [
|
|
640
648
|
// ── Languages ─────────────────────────────────────────────────────────────
|
|
@@ -1432,7 +1440,7 @@ function buildTipsDetailed(topMatches, baseUrl, max = 8, opts = {}) {
|
|
|
1432
1440
|
const token = jobShortToken(String(m.id));
|
|
1433
1441
|
const url = `${base}/j/${token}`;
|
|
1434
1442
|
if (source === "bounty") {
|
|
1435
|
-
const money =
|
|
1443
|
+
const money = formatUsd(m.amountUSD);
|
|
1436
1444
|
const repo = m.repo || companyRaw;
|
|
1437
1445
|
out.push(`\u{1F48E} ${money} \xB7 ${title} \xB7 ${repo} \xB7 ${pct}% \u2014 ${url}`);
|
|
1438
1446
|
} else if (source === "contribute") {
|
package/dist/src/claims.js
CHANGED
|
@@ -161,9 +161,10 @@ function nextPolledState(from, observed) {
|
|
|
161
161
|
function nowISO() {
|
|
162
162
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
163
163
|
}
|
|
164
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
164
165
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
165
166
|
function defangText(s) {
|
|
166
|
-
return typeof s === "string" ? s.replace(CONTROL_CHARS, "") : s;
|
|
167
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "") : s;
|
|
167
168
|
}
|
|
168
169
|
function finiteAmount(a) {
|
|
169
170
|
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
package/package.json
CHANGED