terminalhire 0.42.0 → 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 +20 -2
- package/dist/bin/jpi-bounties.js +76 -7
- package/dist/bin/jpi-claim.js +50 -13
- package/dist/bin/jpi-contribute.js +22 -3
- package/dist/bin/jpi-devs.js +2 -1
- package/dist/bin/jpi-dispatch.js +176 -34
- package/dist/bin/jpi-hub.js +109 -18
- package/dist/bin/jpi-jobs.js +47 -34
- package/dist/bin/jpi-mcp.js +52 -15
- package/dist/bin/jpi-refresh.js +35 -3
- package/dist/bin/jpi-repo.js +20 -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 +19 -1
- package/package.json +1 -1
|
@@ -166,8 +166,24 @@ function nextPolledState(from, observed) {
|
|
|
166
166
|
function nowISO() {
|
|
167
167
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
168
168
|
}
|
|
169
|
+
function defangText(s) {
|
|
170
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "") : s;
|
|
171
|
+
}
|
|
172
|
+
function finiteAmount(a) {
|
|
173
|
+
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
174
|
+
if (typeof a !== "string" || a.trim() === "") return null;
|
|
175
|
+
const n = Number(a);
|
|
176
|
+
return Number.isFinite(n) ? n : null;
|
|
177
|
+
}
|
|
169
178
|
function normalizeClaim(c) {
|
|
170
|
-
return {
|
|
179
|
+
return {
|
|
180
|
+
...c,
|
|
181
|
+
kind: c.kind ?? "bounty",
|
|
182
|
+
policy: c.policy ?? null,
|
|
183
|
+
title: defangText(c.title),
|
|
184
|
+
repoFullName: defangText(c.repoFullName),
|
|
185
|
+
amountUSD: finiteAmount(c.amountUSD)
|
|
186
|
+
};
|
|
171
187
|
}
|
|
172
188
|
function readClaims() {
|
|
173
189
|
try {
|
|
@@ -289,7 +305,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
289
305
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
290
306
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
291
307
|
}
|
|
292
|
-
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;
|
|
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;
|
|
293
309
|
var init_claims = __esm({
|
|
294
310
|
"src/claims.ts"() {
|
|
295
311
|
"use strict";
|
|
@@ -345,6 +361,8 @@ var init_claims = __esm({
|
|
|
345
361
|
]),
|
|
346
362
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
347
363
|
};
|
|
364
|
+
WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
365
|
+
CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
348
366
|
}
|
|
349
367
|
});
|
|
350
368
|
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -11338,8 +11338,24 @@ function nextPolledState(from, observed) {
|
|
|
11338
11338
|
function nowISO2() {
|
|
11339
11339
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
11340
11340
|
}
|
|
11341
|
+
function defangText(s) {
|
|
11342
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
11343
|
+
}
|
|
11344
|
+
function finiteAmount(a) {
|
|
11345
|
+
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
11346
|
+
if (typeof a !== "string" || a.trim() === "") return null;
|
|
11347
|
+
const n = Number(a);
|
|
11348
|
+
return Number.isFinite(n) ? n : null;
|
|
11349
|
+
}
|
|
11341
11350
|
function normalizeClaim(c) {
|
|
11342
|
-
return {
|
|
11351
|
+
return {
|
|
11352
|
+
...c,
|
|
11353
|
+
kind: c.kind ?? "bounty",
|
|
11354
|
+
policy: c.policy ?? null,
|
|
11355
|
+
title: defangText(c.title),
|
|
11356
|
+
repoFullName: defangText(c.repoFullName),
|
|
11357
|
+
amountUSD: finiteAmount(c.amountUSD)
|
|
11358
|
+
};
|
|
11343
11359
|
}
|
|
11344
11360
|
function readClaims() {
|
|
11345
11361
|
try {
|
|
@@ -11461,7 +11477,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
11461
11477
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
11462
11478
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
11463
11479
|
}
|
|
11464
|
-
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;
|
|
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;
|
|
11465
11481
|
var init_claims = __esm({
|
|
11466
11482
|
"src/claims.ts"() {
|
|
11467
11483
|
"use strict";
|
|
@@ -11517,6 +11533,8 @@ var init_claims = __esm({
|
|
|
11517
11533
|
]),
|
|
11518
11534
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
11519
11535
|
};
|
|
11536
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
11537
|
+
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11520
11538
|
}
|
|
11521
11539
|
});
|
|
11522
11540
|
|
|
@@ -11731,17 +11749,38 @@ var init_founder_paid_badge = __esm({
|
|
|
11731
11749
|
|
|
11732
11750
|
// bin/jpi-bounties.js
|
|
11733
11751
|
init_src();
|
|
11734
|
-
init_cache_store();
|
|
11735
11752
|
import { readFileSync as readFileSync7 } from "fs";
|
|
11736
11753
|
import { join as join10 } from "path";
|
|
11737
11754
|
import { homedir as homedir7 } from "os";
|
|
11738
11755
|
import { createInterface } from "readline";
|
|
11739
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
|
+
|
|
11740
11772
|
// bin/sanitize.js
|
|
11773
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
11741
11774
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
11742
11775
|
function sanitizeText(s) {
|
|
11743
11776
|
if (s == null) return "";
|
|
11744
|
-
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";
|
|
11745
11784
|
}
|
|
11746
11785
|
function safeHttpUrl(url) {
|
|
11747
11786
|
if (url == null) return null;
|
|
@@ -11814,13 +11853,33 @@ function prompt(question) {
|
|
|
11814
11853
|
});
|
|
11815
11854
|
}
|
|
11816
11855
|
function formatAmount(b) {
|
|
11817
|
-
return b.amountUSD
|
|
11856
|
+
return formatUsd(b.amountUSD);
|
|
11818
11857
|
}
|
|
11819
11858
|
var EFFORT_LABEL = {
|
|
11820
11859
|
small: "small (~\xBD day)",
|
|
11821
11860
|
medium: "medium (~1 day)",
|
|
11822
11861
|
large: "large (multi-day)"
|
|
11823
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
|
+
}
|
|
11824
11883
|
function printBounty(i, job, score, reason, matchedTags, claimedIds = /* @__PURE__ */ new Set(), continuityNote = null) {
|
|
11825
11884
|
const b = job.bounty ?? {};
|
|
11826
11885
|
const stars = b.repoStars != null ? ` \xB7 ${b.repoStars}\u2605` : "";
|
|
@@ -11963,7 +12022,9 @@ async function run() {
|
|
|
11963
12022
|
const rows = founderRows2(surface, "bounties");
|
|
11964
12023
|
console.log("\n\u26A1 Your TerminalHire postings\n");
|
|
11965
12024
|
if (!rows.length) {
|
|
11966
|
-
console.log(
|
|
12025
|
+
console.log(
|
|
12026
|
+
" No current posting data. Run `terminalhire refresh`, or lead with work:"
|
|
12027
|
+
);
|
|
11967
12028
|
console.log(" terminalhire config set lead dev\n");
|
|
11968
12029
|
} else {
|
|
11969
12030
|
rows.forEach((row, index) => {
|
|
@@ -11972,7 +12033,9 @@ async function run() {
|
|
|
11972
12033
|
);
|
|
11973
12034
|
});
|
|
11974
12035
|
console.log("\n Review and act: https://terminalhire.com/dashboard?tab=postings");
|
|
11975
|
-
console.log(
|
|
12036
|
+
console.log(
|
|
12037
|
+
" Lead with developer bounties instead: terminalhire config set lead dev\n"
|
|
12038
|
+
);
|
|
11976
12039
|
}
|
|
11977
12040
|
return;
|
|
11978
12041
|
}
|
|
@@ -12047,6 +12110,10 @@ Enter a number to open a bounty's claim page, or press Enter to exit: `
|
|
|
12047
12110
|
const idx = parseInt(pick, 10) - 1;
|
|
12048
12111
|
if (Number.isNaN(idx) || idx < 0 || idx >= shown.length) return;
|
|
12049
12112
|
const chosen = shown[idx];
|
|
12113
|
+
if (chosen.bounty?.bountySource === "founder") {
|
|
12114
|
+
console.log(founderClaimBlock(chosen));
|
|
12115
|
+
return;
|
|
12116
|
+
}
|
|
12050
12117
|
console.log(
|
|
12051
12118
|
`
|
|
12052
12119
|
Open this to claim/work the bounty (you go straight to the source \u2014 we never touch payment):
|
|
@@ -12062,6 +12129,8 @@ export {
|
|
|
12062
12129
|
classifyEmptyStatus,
|
|
12063
12130
|
continuityNoteForRow,
|
|
12064
12131
|
filterPaidVisibility,
|
|
12132
|
+
founderClaimBlock,
|
|
12133
|
+
founderClaimBlurb,
|
|
12065
12134
|
getBounties,
|
|
12066
12135
|
isPinnedFounderBounty,
|
|
12067
12136
|
printBounty,
|
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -10638,8 +10638,24 @@ function nextPolledState(from, observed) {
|
|
|
10638
10638
|
function nowISO() {
|
|
10639
10639
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
10640
10640
|
}
|
|
10641
|
+
function defangText(s) {
|
|
10642
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
10643
|
+
}
|
|
10644
|
+
function finiteAmount(a) {
|
|
10645
|
+
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
10646
|
+
if (typeof a !== "string" || a.trim() === "") return null;
|
|
10647
|
+
const n = Number(a);
|
|
10648
|
+
return Number.isFinite(n) ? n : null;
|
|
10649
|
+
}
|
|
10641
10650
|
function normalizeClaim(c) {
|
|
10642
|
-
return {
|
|
10651
|
+
return {
|
|
10652
|
+
...c,
|
|
10653
|
+
kind: c.kind ?? "bounty",
|
|
10654
|
+
policy: c.policy ?? null,
|
|
10655
|
+
title: defangText(c.title),
|
|
10656
|
+
repoFullName: defangText(c.repoFullName),
|
|
10657
|
+
amountUSD: finiteAmount(c.amountUSD)
|
|
10658
|
+
};
|
|
10643
10659
|
}
|
|
10644
10660
|
function readClaims() {
|
|
10645
10661
|
try {
|
|
@@ -10761,7 +10777,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
10761
10777
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
10762
10778
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
10763
10779
|
}
|
|
10764
|
-
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;
|
|
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;
|
|
10765
10781
|
var init_claims = __esm({
|
|
10766
10782
|
"src/claims.ts"() {
|
|
10767
10783
|
"use strict";
|
|
@@ -10817,6 +10833,8 @@ var init_claims = __esm({
|
|
|
10817
10833
|
]),
|
|
10818
10834
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
10819
10835
|
};
|
|
10836
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
10837
|
+
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
10820
10838
|
}
|
|
10821
10839
|
});
|
|
10822
10840
|
|
|
@@ -26134,10 +26152,17 @@ function openInBrowser(url) {
|
|
|
26134
26152
|
}
|
|
26135
26153
|
|
|
26136
26154
|
// bin/sanitize.js
|
|
26155
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
26137
26156
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
26138
26157
|
function sanitizeText(s) {
|
|
26139
26158
|
if (s == null) return "";
|
|
26140
|
-
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";
|
|
26141
26166
|
}
|
|
26142
26167
|
|
|
26143
26168
|
// src/policy-acks.ts
|
|
@@ -27064,7 +27089,7 @@ async function pollPR(prUrl) {
|
|
|
27064
27089
|
}
|
|
27065
27090
|
}
|
|
27066
27091
|
function fmtAmount(a) {
|
|
27067
|
-
return a
|
|
27092
|
+
return formatUsd(a);
|
|
27068
27093
|
}
|
|
27069
27094
|
function fmtClaimAmount(c) {
|
|
27070
27095
|
return c.kind === "contribution" ? "contribution" : fmtAmount(c.amountUSD);
|
|
@@ -27205,8 +27230,15 @@ async function resolveBounty(arg) {
|
|
|
27205
27230
|
return {
|
|
27206
27231
|
bountyId,
|
|
27207
27232
|
indexNativeId,
|
|
27208
|
-
|
|
27209
|
-
|
|
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),
|
|
27210
27242
|
issueUrl,
|
|
27211
27243
|
amountUSD,
|
|
27212
27244
|
source,
|
|
@@ -28402,7 +28434,7 @@ function startableRow(c) {
|
|
|
28402
28434
|
}
|
|
28403
28435
|
async function pickStartableClaim(claims, { prompt = ask, isTTY = process.stdin.isTTY } = {}) {
|
|
28404
28436
|
const active = claims.listClaims({ active: true });
|
|
28405
|
-
await syncFounderApprovals(claims, active);
|
|
28437
|
+
const { approvalsChecked, approvalsUnavailable } = await syncFounderApprovals(claims, active);
|
|
28406
28438
|
const startable = claims.listClaims({ active: true }).filter((c) => c.state === "claimed");
|
|
28407
28439
|
if (startable.length === 0) {
|
|
28408
28440
|
console.log("No claims ready to start. Claim one first: terminalhire claim <ref>");
|
|
@@ -28430,23 +28462,24 @@ Which one? (1-${startable.length}, or q to quit) `);
|
|
|
28430
28462
|
Nothing started \u2014 '${answer}' is not one of 1-${startable.length}.`);
|
|
28431
28463
|
return null;
|
|
28432
28464
|
}
|
|
28433
|
-
return startable[n - 1].id;
|
|
28465
|
+
return { id: startable[n - 1].id, approvalsChecked, approvalsUnavailable };
|
|
28434
28466
|
}
|
|
28435
28467
|
async function cmdStart(id, flags = {}) {
|
|
28436
28468
|
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
28469
|
+
let approvalsChecked = false;
|
|
28470
|
+
let approvalsUnavailable = false;
|
|
28437
28471
|
if (!id) {
|
|
28438
28472
|
const picked = await pickStartableClaim(claims);
|
|
28439
28473
|
if (!picked) return;
|
|
28440
|
-
id = picked;
|
|
28474
|
+
({ id, approvalsChecked, approvalsUnavailable } = picked);
|
|
28441
28475
|
}
|
|
28442
28476
|
let claim = claims.findClaim(id);
|
|
28443
28477
|
if (!claim) {
|
|
28444
28478
|
console.error(`terminalhire claim: no claim with id '${id}'.`);
|
|
28445
28479
|
process.exit(1);
|
|
28446
28480
|
}
|
|
28447
|
-
let approvalsChecked = false;
|
|
28448
28481
|
if (claim.approval?.state === "pending") {
|
|
28449
|
-
({ approvalsChecked } = await syncFounderApprovals(claims, [claim]));
|
|
28482
|
+
({ approvalsChecked, approvalsUnavailable } = await syncFounderApprovals(claims, [claim]));
|
|
28450
28483
|
claim = claims.findClaim(id);
|
|
28451
28484
|
}
|
|
28452
28485
|
if (claim.worktreePath) {
|
|
@@ -28473,6 +28506,10 @@ ${sanitizeText(claim.title)}`);
|
|
|
28473
28506
|
console.log(" same way.");
|
|
28474
28507
|
if (shouldStatePending(claim, approvalsChecked)) {
|
|
28475
28508
|
console.log("\n Access is pending \u2014 the founder has not approved your claim yet.");
|
|
28509
|
+
} else if (approvalsUnavailable) {
|
|
28510
|
+
console.log(
|
|
28511
|
+
"\n Terminalhire could not check approvals right now; local state was preserved.\n The next step below still works \u2014 it asks the server directly."
|
|
28512
|
+
);
|
|
28476
28513
|
}
|
|
28477
28514
|
printNextSteps([claim]);
|
|
28478
28515
|
return;
|
|
@@ -28724,10 +28761,10 @@ var CLAIM_EVENT_LABEL = {
|
|
|
28724
28761
|
rejected: "the founder rejected"
|
|
28725
28762
|
};
|
|
28726
28763
|
var LINE_BREAKS = /\r\n|[\r\n\v\f\u0085\u2028\u2029]/;
|
|
28727
|
-
var
|
|
28764
|
+
var CONTROL_CHARS3 = /[\u0000-\u001F\u007F-\u009F]/g;
|
|
28728
28765
|
function terminalSafeLines(raw) {
|
|
28729
28766
|
if (typeof raw !== "string" || raw === "") return [];
|
|
28730
|
-
return raw.split(LINE_BREAKS).map((l) => l.replace(
|
|
28767
|
+
return raw.split(LINE_BREAKS).map((l) => l.replace(CONTROL_CHARS3, ""));
|
|
28731
28768
|
}
|
|
28732
28769
|
function terminalSafeInline(raw) {
|
|
28733
28770
|
return terminalSafeLines(raw).join(" ");
|
|
@@ -3617,8 +3617,24 @@ function nextPolledState(from, observed) {
|
|
|
3617
3617
|
function nowISO2() {
|
|
3618
3618
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3619
3619
|
}
|
|
3620
|
+
function defangText(s) {
|
|
3621
|
+
return typeof s === "string" ? s.replace(WHITESPACE_CONTROLS2, " ").replace(CONTROL_CHARS2, "") : s;
|
|
3622
|
+
}
|
|
3623
|
+
function finiteAmount(a) {
|
|
3624
|
+
if (typeof a === "number") return Number.isFinite(a) ? a : null;
|
|
3625
|
+
if (typeof a !== "string" || a.trim() === "") return null;
|
|
3626
|
+
const n = Number(a);
|
|
3627
|
+
return Number.isFinite(n) ? n : null;
|
|
3628
|
+
}
|
|
3620
3629
|
function normalizeClaim(c) {
|
|
3621
|
-
return {
|
|
3630
|
+
return {
|
|
3631
|
+
...c,
|
|
3632
|
+
kind: c.kind ?? "bounty",
|
|
3633
|
+
policy: c.policy ?? null,
|
|
3634
|
+
title: defangText(c.title),
|
|
3635
|
+
repoFullName: defangText(c.repoFullName),
|
|
3636
|
+
amountUSD: finiteAmount(c.amountUSD)
|
|
3637
|
+
};
|
|
3622
3638
|
}
|
|
3623
3639
|
function readClaims() {
|
|
3624
3640
|
try {
|
|
@@ -3740,7 +3756,7 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
3740
3756
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
3741
3757
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
3742
3758
|
}
|
|
3743
|
-
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;
|
|
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;
|
|
3744
3760
|
var init_claims = __esm({
|
|
3745
3761
|
"src/claims.ts"() {
|
|
3746
3762
|
"use strict";
|
|
@@ -3796,6 +3812,8 @@ var init_claims = __esm({
|
|
|
3796
3812
|
]),
|
|
3797
3813
|
submitted: /* @__PURE__ */ new Set(["claimed", "working", "in-review", "ready"])
|
|
3798
3814
|
};
|
|
3815
|
+
WHITESPACE_CONTROLS2 = /[\t\n\v\f\r]+/g;
|
|
3816
|
+
CONTROL_CHARS2 = /[\x00-\x1f\x7f-\x9f]/g;
|
|
3799
3817
|
}
|
|
3800
3818
|
});
|
|
3801
3819
|
|
|
@@ -3879,10 +3897,11 @@ function isContributeEnabled() {
|
|
|
3879
3897
|
init_state_dir();
|
|
3880
3898
|
|
|
3881
3899
|
// bin/sanitize.js
|
|
3900
|
+
var WHITESPACE_CONTROLS = /[\t\n\v\f\r]+/g;
|
|
3882
3901
|
var CONTROL_CHARS = /[\x00-\x1f\x7f-\x9f]/g;
|
|
3883
3902
|
function sanitizeText(s) {
|
|
3884
3903
|
if (s == null) return "";
|
|
3885
|
-
return String(s).replace(CONTROL_CHARS, "");
|
|
3904
|
+
return String(s).replace(WHITESPACE_CONTROLS, " ").replace(CONTROL_CHARS, "");
|
|
3886
3905
|
}
|
|
3887
3906
|
function safeHttpUrl(url) {
|
|
3888
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;
|