terminalhire 0.28.0 → 0.29.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 +41 -0
- package/dist/bin/jpi-claim.js +51 -1
- package/dist/bin/jpi-dispatch.js +73 -2
- package/dist/bin/jpi-refresh.js +227 -168
- package/dist/bin/jpi-spinner.js +7 -0
- package/dist/bin/spinner.js +9 -0
- package/package.json +1 -1
|
@@ -285,6 +285,7 @@ function decrypt(blob, key) {
|
|
|
285
285
|
var TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR || join3(homedir3(), ".terminalhire");
|
|
286
286
|
var CLAIM_PUSH_AUTO_MARKER = join3(TERMINALHIRE_DIR3, "claim-push-auto.json");
|
|
287
287
|
var CLAIM_PUSH_TOKEN_FILE = join3(TERMINALHIRE_DIR3, "claim-push-token.enc");
|
|
288
|
+
var CLAIM_PUSH_MANUAL_MARKER = join3(TERMINALHIRE_DIR3, "claim-push.json");
|
|
288
289
|
var CLAIM_SYNC_BASE = "https://terminalhire.com";
|
|
289
290
|
var AUTO_CONSENT_VERSION = 2;
|
|
290
291
|
var AUTO_PUSH_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -352,6 +353,43 @@ function backgroundPushGate(params) {
|
|
|
352
353
|
}
|
|
353
354
|
return { push: true, reason: "ok" };
|
|
354
355
|
}
|
|
356
|
+
function unpushedNudgeGate(params) {
|
|
357
|
+
const {
|
|
358
|
+
autoMarkerExists,
|
|
359
|
+
tokenFileExists,
|
|
360
|
+
manualMarkerExists,
|
|
361
|
+
lastSnapshotHash,
|
|
362
|
+
currentHash,
|
|
363
|
+
claimCount
|
|
364
|
+
} = params;
|
|
365
|
+
if (autoMarkerExists && tokenFileExists) return false;
|
|
366
|
+
if (!manualMarkerExists) return false;
|
|
367
|
+
if (!(claimCount > 0)) return false;
|
|
368
|
+
return lastSnapshotHash !== currentHash;
|
|
369
|
+
}
|
|
370
|
+
async function shouldNudgeUnpushed() {
|
|
371
|
+
try {
|
|
372
|
+
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
373
|
+
const pushed = listClaims2().map((c) => toPushedClaim2(c));
|
|
374
|
+
const currentHash = computeSnapshotHash(pushed);
|
|
375
|
+
let manual = null;
|
|
376
|
+
try {
|
|
377
|
+
manual = existsSync3(CLAIM_PUSH_MANUAL_MARKER) ? JSON.parse(readFileSync3(CLAIM_PUSH_MANUAL_MARKER, "utf8")) : null;
|
|
378
|
+
} catch {
|
|
379
|
+
manual = null;
|
|
380
|
+
}
|
|
381
|
+
return unpushedNudgeGate({
|
|
382
|
+
autoMarkerExists: existsSync3(CLAIM_PUSH_AUTO_MARKER),
|
|
383
|
+
tokenFileExists: existsSync3(CLAIM_PUSH_TOKEN_FILE),
|
|
384
|
+
manualMarkerExists: !!manual,
|
|
385
|
+
lastSnapshotHash: manual?.lastSnapshotHash ?? null,
|
|
386
|
+
currentHash,
|
|
387
|
+
claimCount: pushed.length
|
|
388
|
+
});
|
|
389
|
+
} catch {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
355
393
|
async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
356
394
|
try {
|
|
357
395
|
if (!existsSync3(CLAIM_PUSH_AUTO_MARKER) || !existsSync3(CLAIM_PUSH_TOKEN_FILE)) return;
|
|
@@ -396,6 +434,7 @@ export {
|
|
|
396
434
|
AUTO_CONSENT_VERSION,
|
|
397
435
|
AUTO_PUSH_THROTTLE_MS,
|
|
398
436
|
CLAIM_PUSH_AUTO_MARKER,
|
|
437
|
+
CLAIM_PUSH_MANUAL_MARKER,
|
|
399
438
|
CLAIM_PUSH_TOKEN_FILE,
|
|
400
439
|
backgroundPushGate,
|
|
401
440
|
clearAutoMarker,
|
|
@@ -404,6 +443,8 @@ export {
|
|
|
404
443
|
readAutoMarker,
|
|
405
444
|
readPushTokenEnc,
|
|
406
445
|
runBackgroundClaimPush,
|
|
446
|
+
shouldNudgeUnpushed,
|
|
447
|
+
unpushedNudgeGate,
|
|
407
448
|
writeAutoMarker,
|
|
408
449
|
writePushTokenEnc
|
|
409
450
|
};
|
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -8616,6 +8616,7 @@ function encrypt(plaintext, key) {
|
|
|
8616
8616
|
var TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR || join4(homedir3(), ".terminalhire");
|
|
8617
8617
|
var CLAIM_PUSH_AUTO_MARKER = join4(TERMINALHIRE_DIR3, "claim-push-auto.json");
|
|
8618
8618
|
var CLAIM_PUSH_TOKEN_FILE = join4(TERMINALHIRE_DIR3, "claim-push-token.enc");
|
|
8619
|
+
var CLAIM_PUSH_MANUAL_MARKER = join4(TERMINALHIRE_DIR3, "claim-push.json");
|
|
8619
8620
|
var AUTO_CONSENT_VERSION = 2;
|
|
8620
8621
|
var AUTO_PUSH_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
8621
8622
|
async function writePushTokenEnc(rawToken) {
|
|
@@ -8643,6 +8644,43 @@ function clearAutoMarker() {
|
|
|
8643
8644
|
function computeSnapshotHash(pushed) {
|
|
8644
8645
|
return createHash3("sha256").update(JSON.stringify(pushed)).digest("hex");
|
|
8645
8646
|
}
|
|
8647
|
+
function unpushedNudgeGate(params) {
|
|
8648
|
+
const {
|
|
8649
|
+
autoMarkerExists,
|
|
8650
|
+
tokenFileExists,
|
|
8651
|
+
manualMarkerExists,
|
|
8652
|
+
lastSnapshotHash,
|
|
8653
|
+
currentHash,
|
|
8654
|
+
claimCount
|
|
8655
|
+
} = params;
|
|
8656
|
+
if (autoMarkerExists && tokenFileExists) return false;
|
|
8657
|
+
if (!manualMarkerExists) return false;
|
|
8658
|
+
if (!(claimCount > 0)) return false;
|
|
8659
|
+
return lastSnapshotHash !== currentHash;
|
|
8660
|
+
}
|
|
8661
|
+
async function shouldNudgeUnpushed() {
|
|
8662
|
+
try {
|
|
8663
|
+
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
8664
|
+
const pushed = listClaims2().map((c) => toPushedClaim2(c));
|
|
8665
|
+
const currentHash = computeSnapshotHash(pushed);
|
|
8666
|
+
let manual = null;
|
|
8667
|
+
try {
|
|
8668
|
+
manual = existsSync3(CLAIM_PUSH_MANUAL_MARKER) ? JSON.parse(readFileSync4(CLAIM_PUSH_MANUAL_MARKER, "utf8")) : null;
|
|
8669
|
+
} catch {
|
|
8670
|
+
manual = null;
|
|
8671
|
+
}
|
|
8672
|
+
return unpushedNudgeGate({
|
|
8673
|
+
autoMarkerExists: existsSync3(CLAIM_PUSH_AUTO_MARKER),
|
|
8674
|
+
tokenFileExists: existsSync3(CLAIM_PUSH_TOKEN_FILE),
|
|
8675
|
+
manualMarkerExists: !!manual,
|
|
8676
|
+
lastSnapshotHash: manual?.lastSnapshotHash ?? null,
|
|
8677
|
+
currentHash,
|
|
8678
|
+
claimCount: pushed.length
|
|
8679
|
+
});
|
|
8680
|
+
} catch {
|
|
8681
|
+
return false;
|
|
8682
|
+
}
|
|
8683
|
+
}
|
|
8646
8684
|
|
|
8647
8685
|
// bin/jpi-claim.js
|
|
8648
8686
|
var TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join7(homedir6(), ".terminalhire");
|
|
@@ -9302,6 +9340,12 @@ ${list.length} ${active ? "active " : ""}claim${list.length === 1 ? "" : "s"}:
|
|
|
9302
9340
|
console.log(` id: ${c.id}${pr}`);
|
|
9303
9341
|
}
|
|
9304
9342
|
printMetric(claims.acceptedPRRate());
|
|
9343
|
+
try {
|
|
9344
|
+
if (await shouldNudgeUnpushed()) {
|
|
9345
|
+
console.log("\n \u26A0 new claims not yet on your dashboard \u2014 run: terminalhire claim --push --keep-updated");
|
|
9346
|
+
}
|
|
9347
|
+
} catch {
|
|
9348
|
+
}
|
|
9305
9349
|
}
|
|
9306
9350
|
async function cmdStatus(id) {
|
|
9307
9351
|
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
@@ -10118,7 +10162,13 @@ async function cmdPush({ keepUpdated = false } = {}) {
|
|
|
10118
10162
|
pushToken = body?.pushToken || null;
|
|
10119
10163
|
} catch {
|
|
10120
10164
|
}
|
|
10121
|
-
writeClaimPushMarker({
|
|
10165
|
+
writeClaimPushMarker({
|
|
10166
|
+
consentedAt,
|
|
10167
|
+
login,
|
|
10168
|
+
deleteToken,
|
|
10169
|
+
lastPushedAt: consentedAt,
|
|
10170
|
+
lastSnapshotHash: computeSnapshotHash(pushed)
|
|
10171
|
+
});
|
|
10122
10172
|
if (autoConsent && pushToken) {
|
|
10123
10173
|
try {
|
|
10124
10174
|
await writePushTokenEnc(pushToken);
|
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -10811,6 +10811,7 @@ __export(claim_push_bg_exports, {
|
|
|
10811
10811
|
AUTO_CONSENT_VERSION: () => AUTO_CONSENT_VERSION,
|
|
10812
10812
|
AUTO_PUSH_THROTTLE_MS: () => AUTO_PUSH_THROTTLE_MS,
|
|
10813
10813
|
CLAIM_PUSH_AUTO_MARKER: () => CLAIM_PUSH_AUTO_MARKER,
|
|
10814
|
+
CLAIM_PUSH_MANUAL_MARKER: () => CLAIM_PUSH_MANUAL_MARKER,
|
|
10814
10815
|
CLAIM_PUSH_TOKEN_FILE: () => CLAIM_PUSH_TOKEN_FILE,
|
|
10815
10816
|
backgroundPushGate: () => backgroundPushGate,
|
|
10816
10817
|
clearAutoMarker: () => clearAutoMarker,
|
|
@@ -10819,6 +10820,8 @@ __export(claim_push_bg_exports, {
|
|
|
10819
10820
|
readAutoMarker: () => readAutoMarker,
|
|
10820
10821
|
readPushTokenEnc: () => readPushTokenEnc,
|
|
10821
10822
|
runBackgroundClaimPush: () => runBackgroundClaimPush,
|
|
10823
|
+
shouldNudgeUnpushed: () => shouldNudgeUnpushed,
|
|
10824
|
+
unpushedNudgeGate: () => unpushedNudgeGate,
|
|
10822
10825
|
writeAutoMarker: () => writeAutoMarker,
|
|
10823
10826
|
writePushTokenEnc: () => writePushTokenEnc
|
|
10824
10827
|
});
|
|
@@ -10890,6 +10893,43 @@ function backgroundPushGate(params) {
|
|
|
10890
10893
|
}
|
|
10891
10894
|
return { push: true, reason: "ok" };
|
|
10892
10895
|
}
|
|
10896
|
+
function unpushedNudgeGate(params) {
|
|
10897
|
+
const {
|
|
10898
|
+
autoMarkerExists,
|
|
10899
|
+
tokenFileExists,
|
|
10900
|
+
manualMarkerExists,
|
|
10901
|
+
lastSnapshotHash,
|
|
10902
|
+
currentHash,
|
|
10903
|
+
claimCount
|
|
10904
|
+
} = params;
|
|
10905
|
+
if (autoMarkerExists && tokenFileExists) return false;
|
|
10906
|
+
if (!manualMarkerExists) return false;
|
|
10907
|
+
if (!(claimCount > 0)) return false;
|
|
10908
|
+
return lastSnapshotHash !== currentHash;
|
|
10909
|
+
}
|
|
10910
|
+
async function shouldNudgeUnpushed() {
|
|
10911
|
+
try {
|
|
10912
|
+
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
10913
|
+
const pushed = listClaims2().map((c) => toPushedClaim2(c));
|
|
10914
|
+
const currentHash = computeSnapshotHash(pushed);
|
|
10915
|
+
let manual = null;
|
|
10916
|
+
try {
|
|
10917
|
+
manual = existsSync9(CLAIM_PUSH_MANUAL_MARKER) ? JSON.parse(readFileSync16(CLAIM_PUSH_MANUAL_MARKER, "utf8")) : null;
|
|
10918
|
+
} catch {
|
|
10919
|
+
manual = null;
|
|
10920
|
+
}
|
|
10921
|
+
return unpushedNudgeGate({
|
|
10922
|
+
autoMarkerExists: existsSync9(CLAIM_PUSH_AUTO_MARKER),
|
|
10923
|
+
tokenFileExists: existsSync9(CLAIM_PUSH_TOKEN_FILE),
|
|
10924
|
+
manualMarkerExists: !!manual,
|
|
10925
|
+
lastSnapshotHash: manual?.lastSnapshotHash ?? null,
|
|
10926
|
+
currentHash,
|
|
10927
|
+
claimCount: pushed.length
|
|
10928
|
+
});
|
|
10929
|
+
} catch {
|
|
10930
|
+
return false;
|
|
10931
|
+
}
|
|
10932
|
+
}
|
|
10893
10933
|
async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
10894
10934
|
try {
|
|
10895
10935
|
if (!existsSync9(CLAIM_PUSH_AUTO_MARKER) || !existsSync9(CLAIM_PUSH_TOKEN_FILE)) return;
|
|
@@ -10930,7 +10970,7 @@ async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
|
10930
10970
|
} catch {
|
|
10931
10971
|
}
|
|
10932
10972
|
}
|
|
10933
|
-
var TERMINALHIRE_DIR12, CLAIM_PUSH_AUTO_MARKER, CLAIM_PUSH_TOKEN_FILE, CLAIM_SYNC_BASE, AUTO_CONSENT_VERSION, AUTO_PUSH_THROTTLE_MS;
|
|
10973
|
+
var TERMINALHIRE_DIR12, CLAIM_PUSH_AUTO_MARKER, CLAIM_PUSH_TOKEN_FILE, CLAIM_PUSH_MANUAL_MARKER, CLAIM_SYNC_BASE, AUTO_CONSENT_VERSION, AUTO_PUSH_THROTTLE_MS;
|
|
10934
10974
|
var init_claim_push_bg = __esm({
|
|
10935
10975
|
"bin/claim-push-bg.js"() {
|
|
10936
10976
|
"use strict";
|
|
@@ -10938,6 +10978,7 @@ var init_claim_push_bg = __esm({
|
|
|
10938
10978
|
TERMINALHIRE_DIR12 = process.env.TERMINALHIRE_DIR || join16(homedir14(), ".terminalhire");
|
|
10939
10979
|
CLAIM_PUSH_AUTO_MARKER = join16(TERMINALHIRE_DIR12, "claim-push-auto.json");
|
|
10940
10980
|
CLAIM_PUSH_TOKEN_FILE = join16(TERMINALHIRE_DIR12, "claim-push-token.enc");
|
|
10981
|
+
CLAIM_PUSH_MANUAL_MARKER = join16(TERMINALHIRE_DIR12, "claim-push.json");
|
|
10941
10982
|
CLAIM_SYNC_BASE = "https://terminalhire.com";
|
|
10942
10983
|
AUTO_CONSENT_VERSION = 2;
|
|
10943
10984
|
AUTO_PUSH_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -11708,6 +11749,12 @@ ${list.length} ${active ? "active " : ""}claim${list.length === 1 ? "" : "s"}:
|
|
|
11708
11749
|
console.log(` id: ${c.id}${pr}`);
|
|
11709
11750
|
}
|
|
11710
11751
|
printMetric(claims.acceptedPRRate());
|
|
11752
|
+
try {
|
|
11753
|
+
if (await shouldNudgeUnpushed()) {
|
|
11754
|
+
console.log("\n \u26A0 new claims not yet on your dashboard \u2014 run: terminalhire claim --push --keep-updated");
|
|
11755
|
+
}
|
|
11756
|
+
} catch {
|
|
11757
|
+
}
|
|
11711
11758
|
}
|
|
11712
11759
|
async function cmdStatus(id) {
|
|
11713
11760
|
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
@@ -12524,7 +12571,13 @@ async function cmdPush({ keepUpdated = false } = {}) {
|
|
|
12524
12571
|
pushToken = body?.pushToken || null;
|
|
12525
12572
|
} catch {
|
|
12526
12573
|
}
|
|
12527
|
-
writeClaimPushMarker({
|
|
12574
|
+
writeClaimPushMarker({
|
|
12575
|
+
consentedAt,
|
|
12576
|
+
login,
|
|
12577
|
+
deleteToken,
|
|
12578
|
+
lastPushedAt: consentedAt,
|
|
12579
|
+
lastSnapshotHash: computeSnapshotHash(pushed)
|
|
12580
|
+
});
|
|
12528
12581
|
if (autoConsent && pushToken) {
|
|
12529
12582
|
try {
|
|
12530
12583
|
await writePushTokenEnc(pushToken);
|
|
@@ -41191,6 +41244,9 @@ function buildContributeNudgeLine(contributeNudge) {
|
|
|
41191
41244
|
function buildSessionStaleLine(sessionStale) {
|
|
41192
41245
|
return sessionStale === true ? "\u26A0 terminalhire: linked session expired \u2014 run: terminalhire login" : null;
|
|
41193
41246
|
}
|
|
41247
|
+
function buildUnpushedClaimsLine(unpushedClaims) {
|
|
41248
|
+
return unpushedClaims === true ? "\u26A0 new claims not yet on your dashboard \u2014 run: terminalhire claim --push --keep-updated" : null;
|
|
41249
|
+
}
|
|
41194
41250
|
function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
41195
41251
|
const {
|
|
41196
41252
|
sessionTags,
|
|
@@ -41199,16 +41255,19 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
41199
41255
|
incomingPending,
|
|
41200
41256
|
sessionStale,
|
|
41201
41257
|
contributeNudge,
|
|
41258
|
+
unpushedClaims,
|
|
41202
41259
|
seenHistory
|
|
41203
41260
|
} = opts;
|
|
41204
41261
|
const staleLine = buildSessionStaleLine(sessionStale);
|
|
41205
41262
|
const withStale = (pool2) => staleLine ? [staleLine, ...pool2] : pool2;
|
|
41206
41263
|
const introLine = buildIncomingIntroLine(incomingPending);
|
|
41207
41264
|
const contributeLine = buildContributeNudgeLine(contributeNudge);
|
|
41265
|
+
const unpushedLine = buildUnpushedClaimsLine(unpushedClaims);
|
|
41208
41266
|
const ranked = filterFreshMatches(rankBySessionTags(topMatches, sessionTags), seenHistory);
|
|
41209
41267
|
if (!Array.isArray(ranked) || ranked.length === 0) {
|
|
41210
41268
|
if (introLine) return withStale([introLine]);
|
|
41211
41269
|
if (contributeLine) return withStale([contributeLine]);
|
|
41270
|
+
if (unpushedLine) return withStale([unpushedLine]);
|
|
41212
41271
|
const peerLine = buildPeerLine(topPeers);
|
|
41213
41272
|
return withStale(peerLine ? [peerLine] : []);
|
|
41214
41273
|
}
|
|
@@ -41218,6 +41277,7 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
41218
41277
|
const pool = [...headers.slice(0, cap), ctaVerb()];
|
|
41219
41278
|
if (introLine) pool.push(introLine);
|
|
41220
41279
|
if (contributeLine) pool.push(contributeLine);
|
|
41280
|
+
if (unpushedLine) pool.push(unpushedLine);
|
|
41221
41281
|
return withStale(pool);
|
|
41222
41282
|
}
|
|
41223
41283
|
var init_spinner_verbs = __esm({
|
|
@@ -41357,6 +41417,7 @@ function renderRefreshSurface(topMatches, sc, opts = {}) {
|
|
|
41357
41417
|
incomingPending: opts.incomingPending,
|
|
41358
41418
|
sessionStale: opts.sessionStale,
|
|
41359
41419
|
contributeNudge: opts.contributeNudge,
|
|
41420
|
+
unpushedClaims: opts.unpushedClaims,
|
|
41360
41421
|
seenHistory
|
|
41361
41422
|
});
|
|
41362
41423
|
if (verbs.length > 0) applySpinnerVerbs(verbs, sc.mode);
|
|
@@ -41396,6 +41457,7 @@ __export(spinner_exports, {
|
|
|
41396
41457
|
buildSpinnerPool: () => buildSpinnerPool,
|
|
41397
41458
|
buildTips: () => buildTips,
|
|
41398
41459
|
buildTipsDetailed: () => buildTipsDetailed,
|
|
41460
|
+
buildUnpushedClaimsLine: () => buildUnpushedClaimsLine,
|
|
41399
41461
|
clearSpinnerTips: () => clearSpinnerTips,
|
|
41400
41462
|
clearSpinnerVerbs: () => clearSpinnerVerbs,
|
|
41401
41463
|
ctaVerb: () => ctaVerb,
|
|
@@ -41420,6 +41482,7 @@ var init_spinner = __esm({
|
|
|
41420
41482
|
init_spinner_verbs();
|
|
41421
41483
|
init_spinner_verbs();
|
|
41422
41484
|
init_spinner_verbs();
|
|
41485
|
+
init_spinner_verbs();
|
|
41423
41486
|
init_spinner_select();
|
|
41424
41487
|
init_spinner_select();
|
|
41425
41488
|
init_spinner_select();
|
|
@@ -42582,6 +42645,12 @@ async function run22() {
|
|
|
42582
42645
|
topMatches = filterFreshMatches2(topMatches, seenHistory);
|
|
42583
42646
|
} catch {
|
|
42584
42647
|
}
|
|
42648
|
+
let unpushedClaims = false;
|
|
42649
|
+
try {
|
|
42650
|
+
const { shouldNudgeUnpushed: shouldNudgeUnpushed2 } = await Promise.resolve().then(() => (init_claim_push_bg(), claim_push_bg_exports));
|
|
42651
|
+
unpushedClaims = await shouldNudgeUnpushed2();
|
|
42652
|
+
} catch {
|
|
42653
|
+
}
|
|
42585
42654
|
const cacheEntry = {
|
|
42586
42655
|
index,
|
|
42587
42656
|
matchCount,
|
|
@@ -42590,6 +42659,7 @@ async function run22() {
|
|
|
42590
42659
|
incomingPending,
|
|
42591
42660
|
unreadChat,
|
|
42592
42661
|
sessionStale,
|
|
42662
|
+
unpushedClaims,
|
|
42593
42663
|
// In-process-only despite being persisted: the render pass receives it as
|
|
42594
42664
|
// a function argument below. A future cache READER must not gate on this
|
|
42595
42665
|
// field without re-checking isContributeEnabled/isContributePrompted at
|
|
@@ -42628,6 +42698,7 @@ async function run22() {
|
|
|
42628
42698
|
incomingPending,
|
|
42629
42699
|
sessionStale,
|
|
42630
42700
|
contributeNudge,
|
|
42701
|
+
unpushedClaims,
|
|
42631
42702
|
baseUrl: API_URL8,
|
|
42632
42703
|
seenHistory,
|
|
42633
42704
|
widen,
|
package/dist/bin/jpi-refresh.js
CHANGED
|
@@ -9045,6 +9045,9 @@ function buildContributeNudgeLine(contributeNudge) {
|
|
|
9045
9045
|
function buildSessionStaleLine(sessionStale) {
|
|
9046
9046
|
return sessionStale === true ? "\u26A0 terminalhire: linked session expired \u2014 run: terminalhire login" : null;
|
|
9047
9047
|
}
|
|
9048
|
+
function buildUnpushedClaimsLine(unpushedClaims) {
|
|
9049
|
+
return unpushedClaims === true ? "\u26A0 new claims not yet on your dashboard \u2014 run: terminalhire claim --push --keep-updated" : null;
|
|
9050
|
+
}
|
|
9048
9051
|
function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
9049
9052
|
const {
|
|
9050
9053
|
sessionTags,
|
|
@@ -9053,16 +9056,19 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
9053
9056
|
incomingPending,
|
|
9054
9057
|
sessionStale,
|
|
9055
9058
|
contributeNudge,
|
|
9059
|
+
unpushedClaims,
|
|
9056
9060
|
seenHistory
|
|
9057
9061
|
} = opts;
|
|
9058
9062
|
const staleLine = buildSessionStaleLine(sessionStale);
|
|
9059
9063
|
const withStale = (pool2) => staleLine ? [staleLine, ...pool2] : pool2;
|
|
9060
9064
|
const introLine = buildIncomingIntroLine(incomingPending);
|
|
9061
9065
|
const contributeLine = buildContributeNudgeLine(contributeNudge);
|
|
9066
|
+
const unpushedLine = buildUnpushedClaimsLine(unpushedClaims);
|
|
9062
9067
|
const ranked = filterFreshMatches(rankBySessionTags(topMatches, sessionTags), seenHistory);
|
|
9063
9068
|
if (!Array.isArray(ranked) || ranked.length === 0) {
|
|
9064
9069
|
if (introLine) return withStale([introLine]);
|
|
9065
9070
|
if (contributeLine) return withStale([contributeLine]);
|
|
9071
|
+
if (unpushedLine) return withStale([unpushedLine]);
|
|
9066
9072
|
const peerLine = buildPeerLine(topPeers);
|
|
9067
9073
|
return withStale(peerLine ? [peerLine] : []);
|
|
9068
9074
|
}
|
|
@@ -9072,6 +9078,7 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
9072
9078
|
const pool = [...headers.slice(0, cap), ctaVerb()];
|
|
9073
9079
|
if (introLine) pool.push(introLine);
|
|
9074
9080
|
if (contributeLine) pool.push(contributeLine);
|
|
9081
|
+
if (unpushedLine) pool.push(unpushedLine);
|
|
9075
9082
|
return withStale(pool);
|
|
9076
9083
|
}
|
|
9077
9084
|
var init_spinner_verbs = __esm({
|
|
@@ -9211,6 +9218,7 @@ function renderRefreshSurface(topMatches, sc, opts = {}) {
|
|
|
9211
9218
|
incomingPending: opts.incomingPending,
|
|
9212
9219
|
sessionStale: opts.sessionStale,
|
|
9213
9220
|
contributeNudge: opts.contributeNudge,
|
|
9221
|
+
unpushedClaims: opts.unpushedClaims,
|
|
9214
9222
|
seenHistory
|
|
9215
9223
|
});
|
|
9216
9224
|
if (verbs.length > 0) applySpinnerVerbs(verbs, sc.mode);
|
|
@@ -9250,6 +9258,7 @@ __export(spinner_exports, {
|
|
|
9250
9258
|
buildSpinnerPool: () => buildSpinnerPool,
|
|
9251
9259
|
buildTips: () => buildTips,
|
|
9252
9260
|
buildTipsDetailed: () => buildTipsDetailed,
|
|
9261
|
+
buildUnpushedClaimsLine: () => buildUnpushedClaimsLine,
|
|
9253
9262
|
clearSpinnerTips: () => clearSpinnerTips,
|
|
9254
9263
|
clearSpinnerVerbs: () => clearSpinnerVerbs,
|
|
9255
9264
|
ctaVerb: () => ctaVerb,
|
|
@@ -9274,6 +9283,7 @@ var init_spinner = __esm({
|
|
|
9274
9283
|
init_spinner_verbs();
|
|
9275
9284
|
init_spinner_verbs();
|
|
9276
9285
|
init_spinner_verbs();
|
|
9286
|
+
init_spinner_verbs();
|
|
9277
9287
|
init_spinner_select();
|
|
9278
9288
|
init_spinner_select();
|
|
9279
9289
|
init_spinner_select();
|
|
@@ -9288,137 +9298,6 @@ var init_spinner = __esm({
|
|
|
9288
9298
|
}
|
|
9289
9299
|
});
|
|
9290
9300
|
|
|
9291
|
-
// bin/version-nudge.js
|
|
9292
|
-
var version_nudge_exports = {};
|
|
9293
|
-
__export(version_nudge_exports, {
|
|
9294
|
-
buildStaleNudge: () => buildStaleNudge,
|
|
9295
|
-
cachedStaleNudge: () => cachedStaleNudge,
|
|
9296
|
-
compareVersions: () => compareVersions,
|
|
9297
|
-
emitInteractiveNudge: () => emitInteractiveNudge,
|
|
9298
|
-
parseVersion: () => parseVersion,
|
|
9299
|
-
readLatestVersionFromCache: () => readLatestVersionFromCache,
|
|
9300
|
-
readLocalVersion: () => readLocalVersion,
|
|
9301
|
-
recordNag: () => recordNag,
|
|
9302
|
-
shouldNag: () => shouldNag
|
|
9303
|
-
});
|
|
9304
|
-
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, existsSync as existsSync6 } from "fs";
|
|
9305
|
-
import { join as join12 } from "path";
|
|
9306
|
-
import { homedir as homedir9 } from "os";
|
|
9307
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9308
|
-
function stateDir() {
|
|
9309
|
-
return process.env.TERMINALHIRE_DIR || join12(homedir9(), ".terminalhire");
|
|
9310
|
-
}
|
|
9311
|
-
function indexCacheFile() {
|
|
9312
|
-
return join12(stateDir(), "index-cache.json");
|
|
9313
|
-
}
|
|
9314
|
-
function nudgeStateFile() {
|
|
9315
|
-
return join12(stateDir(), "version-nudge.json");
|
|
9316
|
-
}
|
|
9317
|
-
function parseVersion(v) {
|
|
9318
|
-
if (typeof v !== "string") return null;
|
|
9319
|
-
const m = v.trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
9320
|
-
if (!m) return null;
|
|
9321
|
-
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
9322
|
-
}
|
|
9323
|
-
function compareVersions(a, b) {
|
|
9324
|
-
const pa = parseVersion(a);
|
|
9325
|
-
const pb = parseVersion(b);
|
|
9326
|
-
if (!pa || !pb) return null;
|
|
9327
|
-
for (let i = 0; i < 3; i++) {
|
|
9328
|
-
if (pa[i] < pb[i]) return -1;
|
|
9329
|
-
if (pa[i] > pb[i]) return 1;
|
|
9330
|
-
}
|
|
9331
|
-
return 0;
|
|
9332
|
-
}
|
|
9333
|
-
function buildStaleNudge(local, latest) {
|
|
9334
|
-
if (compareVersions(local, latest) !== -1) return null;
|
|
9335
|
-
return `your terminalhire CLI is behind (${local} \u2192 ${latest}) \u2014 npm i -g terminalhire@latest`;
|
|
9336
|
-
}
|
|
9337
|
-
function readLocalVersion() {
|
|
9338
|
-
try {
|
|
9339
|
-
const candidates = [
|
|
9340
|
-
join12(__dirname, "..", "..", "package.json"),
|
|
9341
|
-
join12(__dirname, "..", "package.json")
|
|
9342
|
-
];
|
|
9343
|
-
for (const p of candidates) {
|
|
9344
|
-
if (existsSync6(p)) {
|
|
9345
|
-
const pkg = JSON.parse(readFileSync11(p, "utf8"));
|
|
9346
|
-
if (pkg.version) return pkg.version;
|
|
9347
|
-
}
|
|
9348
|
-
}
|
|
9349
|
-
} catch {
|
|
9350
|
-
}
|
|
9351
|
-
return null;
|
|
9352
|
-
}
|
|
9353
|
-
function readLatestVersionFromCache() {
|
|
9354
|
-
try {
|
|
9355
|
-
const cache = JSON.parse(readFileSync11(indexCacheFile(), "utf8"));
|
|
9356
|
-
const v = cache?.index?.cliVersion;
|
|
9357
|
-
return typeof v === "string" ? v : null;
|
|
9358
|
-
} catch {
|
|
9359
|
-
return null;
|
|
9360
|
-
}
|
|
9361
|
-
}
|
|
9362
|
-
function cachedStaleNudge(localVersion) {
|
|
9363
|
-
const local = localVersion ?? readLocalVersion();
|
|
9364
|
-
if (!local) return null;
|
|
9365
|
-
return buildStaleNudge(local, readLatestVersionFromCache());
|
|
9366
|
-
}
|
|
9367
|
-
function shouldNag(now = Date.now()) {
|
|
9368
|
-
try {
|
|
9369
|
-
const state = JSON.parse(readFileSync11(nudgeStateFile(), "utf8"));
|
|
9370
|
-
const last = state?.lastNaggedAt;
|
|
9371
|
-
if (typeof last !== "number" || !Number.isFinite(last)) return true;
|
|
9372
|
-
return now - last >= NAG_INTERVAL_MS;
|
|
9373
|
-
} catch {
|
|
9374
|
-
return true;
|
|
9375
|
-
}
|
|
9376
|
-
}
|
|
9377
|
-
function recordNag(now = Date.now()) {
|
|
9378
|
-
try {
|
|
9379
|
-
mkdirSync9(stateDir(), { recursive: true });
|
|
9380
|
-
writeFileSync9(nudgeStateFile(), JSON.stringify({ lastNaggedAt: now }) + "\n", "utf8");
|
|
9381
|
-
} catch {
|
|
9382
|
-
}
|
|
9383
|
-
}
|
|
9384
|
-
function emitInteractiveNudge({ now = Date.now(), stream = process.stderr, localVersion } = {}) {
|
|
9385
|
-
try {
|
|
9386
|
-
const nudge = cachedStaleNudge(localVersion);
|
|
9387
|
-
if (!nudge) return false;
|
|
9388
|
-
if (!shouldNag(now)) return false;
|
|
9389
|
-
stream.write(`${nudge}
|
|
9390
|
-
`);
|
|
9391
|
-
recordNag(now);
|
|
9392
|
-
return true;
|
|
9393
|
-
} catch {
|
|
9394
|
-
return false;
|
|
9395
|
-
}
|
|
9396
|
-
}
|
|
9397
|
-
var __dirname, NAG_INTERVAL_MS;
|
|
9398
|
-
var init_version_nudge = __esm({
|
|
9399
|
-
"bin/version-nudge.js"() {
|
|
9400
|
-
"use strict";
|
|
9401
|
-
__dirname = fileURLToPath2(new URL(".", import.meta.url));
|
|
9402
|
-
NAG_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
9403
|
-
}
|
|
9404
|
-
});
|
|
9405
|
-
|
|
9406
|
-
// bin/beta-nudge.js
|
|
9407
|
-
var beta_nudge_exports = {};
|
|
9408
|
-
__export(beta_nudge_exports, {
|
|
9409
|
-
buildBetaNudge: () => buildBetaNudge
|
|
9410
|
-
});
|
|
9411
|
-
function buildBetaNudge(betaOpen, betaOptIn) {
|
|
9412
|
-
if (betaOpen !== true) return null;
|
|
9413
|
-
if (betaOptIn === true) return null;
|
|
9414
|
-
return "\u{1F9EA} Beta's open \u2014 run `terminalhire beta` to join as a Founding Contributor";
|
|
9415
|
-
}
|
|
9416
|
-
var init_beta_nudge = __esm({
|
|
9417
|
-
"bin/beta-nudge.js"() {
|
|
9418
|
-
"use strict";
|
|
9419
|
-
}
|
|
9420
|
-
});
|
|
9421
|
-
|
|
9422
9301
|
// src/github-auth.ts
|
|
9423
9302
|
import {
|
|
9424
9303
|
createCipheriv as createCipheriv2,
|
|
@@ -9426,14 +9305,14 @@ import {
|
|
|
9426
9305
|
randomBytes as randomBytes4
|
|
9427
9306
|
} from "crypto";
|
|
9428
9307
|
import {
|
|
9429
|
-
readFileSync as
|
|
9430
|
-
writeFileSync as
|
|
9431
|
-
mkdirSync as
|
|
9432
|
-
existsSync as
|
|
9308
|
+
readFileSync as readFileSync11,
|
|
9309
|
+
writeFileSync as writeFileSync9,
|
|
9310
|
+
mkdirSync as mkdirSync9,
|
|
9311
|
+
existsSync as existsSync6,
|
|
9433
9312
|
rmSync as rmSync2
|
|
9434
9313
|
} from "fs";
|
|
9435
|
-
import { join as
|
|
9436
|
-
import { homedir as
|
|
9314
|
+
import { join as join12 } from "path";
|
|
9315
|
+
import { homedir as homedir9 } from "os";
|
|
9437
9316
|
async function loadKey2() {
|
|
9438
9317
|
try {
|
|
9439
9318
|
const kt = await Promise.resolve().then(() => __toESM(require_keytar2(), 1));
|
|
@@ -9444,12 +9323,12 @@ async function loadKey2() {
|
|
|
9444
9323
|
return key2;
|
|
9445
9324
|
} catch {
|
|
9446
9325
|
}
|
|
9447
|
-
|
|
9448
|
-
if (
|
|
9449
|
-
return Buffer.from(
|
|
9326
|
+
mkdirSync9(TERMINALHIRE_DIR6, { recursive: true });
|
|
9327
|
+
if (existsSync6(KEY_FILE2)) {
|
|
9328
|
+
return Buffer.from(readFileSync11(KEY_FILE2, "utf8").trim(), "hex");
|
|
9450
9329
|
}
|
|
9451
9330
|
const key = randomBytes4(KEY_BYTES2);
|
|
9452
|
-
|
|
9331
|
+
writeFileSync9(KEY_FILE2, key.toString("hex"), { mode: 384, encoding: "utf8" });
|
|
9453
9332
|
return key;
|
|
9454
9333
|
}
|
|
9455
9334
|
function encrypt2(plaintext, key) {
|
|
@@ -9472,9 +9351,9 @@ var TERMINALHIRE_DIR6, TOKEN_FILE, KEY_FILE2, ALGO2, KEY_BYTES2, IV_BYTES2;
|
|
|
9472
9351
|
var init_github_auth = __esm({
|
|
9473
9352
|
"src/github-auth.ts"() {
|
|
9474
9353
|
"use strict";
|
|
9475
|
-
TERMINALHIRE_DIR6 =
|
|
9476
|
-
TOKEN_FILE =
|
|
9477
|
-
KEY_FILE2 =
|
|
9354
|
+
TERMINALHIRE_DIR6 = join12(homedir9(), ".terminalhire");
|
|
9355
|
+
TOKEN_FILE = join12(TERMINALHIRE_DIR6, "github-token.enc");
|
|
9356
|
+
KEY_FILE2 = join12(TERMINALHIRE_DIR6, "key");
|
|
9478
9357
|
ALGO2 = "aes-256-gcm";
|
|
9479
9358
|
KEY_BYTES2 = 32;
|
|
9480
9359
|
IV_BYTES2 = 12;
|
|
@@ -9494,9 +9373,9 @@ __export(claims_exports, {
|
|
|
9494
9373
|
toPushedClaim: () => toPushedClaim,
|
|
9495
9374
|
updateClaim: () => updateClaim
|
|
9496
9375
|
});
|
|
9497
|
-
import { readFileSync as
|
|
9498
|
-
import { join as
|
|
9499
|
-
import { homedir as
|
|
9376
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, renameSync as renameSync6, existsSync as existsSync7 } from "fs";
|
|
9377
|
+
import { join as join13 } from "path";
|
|
9378
|
+
import { homedir as homedir10 } from "os";
|
|
9500
9379
|
function toPushedClaim(claim) {
|
|
9501
9380
|
return {
|
|
9502
9381
|
kind: claim.kind,
|
|
@@ -9516,8 +9395,8 @@ function normalizeClaim(c) {
|
|
|
9516
9395
|
}
|
|
9517
9396
|
function readClaims() {
|
|
9518
9397
|
try {
|
|
9519
|
-
if (!
|
|
9520
|
-
const data = JSON.parse(
|
|
9398
|
+
if (!existsSync7(CLAIMS_FILE)) return [];
|
|
9399
|
+
const data = JSON.parse(readFileSync12(CLAIMS_FILE, "utf8"));
|
|
9521
9400
|
const claims = Array.isArray(data?.claims) ? data.claims : [];
|
|
9522
9401
|
return claims.map(normalizeClaim);
|
|
9523
9402
|
} catch {
|
|
@@ -9525,10 +9404,10 @@ function readClaims() {
|
|
|
9525
9404
|
}
|
|
9526
9405
|
}
|
|
9527
9406
|
function writeClaims(claims) {
|
|
9528
|
-
|
|
9407
|
+
mkdirSync10(TERMINALHIRE_DIR7, { recursive: true });
|
|
9529
9408
|
const tmp = `${CLAIMS_FILE}.tmp`;
|
|
9530
9409
|
const payload = { claims };
|
|
9531
|
-
|
|
9410
|
+
writeFileSync10(tmp, JSON.stringify(payload, null, 2), "utf8");
|
|
9532
9411
|
renameSync6(tmp, CLAIMS_FILE);
|
|
9533
9412
|
}
|
|
9534
9413
|
function findClaim(id) {
|
|
@@ -9589,8 +9468,8 @@ var TERMINALHIRE_DIR7, CLAIMS_FILE, PUSHED_CLAIM_FIELDS, TERMINAL_STATES;
|
|
|
9589
9468
|
var init_claims = __esm({
|
|
9590
9469
|
"src/claims.ts"() {
|
|
9591
9470
|
"use strict";
|
|
9592
|
-
TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR ||
|
|
9593
|
-
CLAIMS_FILE =
|
|
9471
|
+
TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR || join13(homedir10(), ".terminalhire");
|
|
9472
|
+
CLAIMS_FILE = join13(TERMINALHIRE_DIR7, "claims.json");
|
|
9594
9473
|
PUSHED_CLAIM_FIELDS = [
|
|
9595
9474
|
"kind",
|
|
9596
9475
|
"repoFullName",
|
|
@@ -9610,6 +9489,7 @@ __export(claim_push_bg_exports, {
|
|
|
9610
9489
|
AUTO_CONSENT_VERSION: () => AUTO_CONSENT_VERSION,
|
|
9611
9490
|
AUTO_PUSH_THROTTLE_MS: () => AUTO_PUSH_THROTTLE_MS,
|
|
9612
9491
|
CLAIM_PUSH_AUTO_MARKER: () => CLAIM_PUSH_AUTO_MARKER,
|
|
9492
|
+
CLAIM_PUSH_MANUAL_MARKER: () => CLAIM_PUSH_MANUAL_MARKER,
|
|
9613
9493
|
CLAIM_PUSH_TOKEN_FILE: () => CLAIM_PUSH_TOKEN_FILE,
|
|
9614
9494
|
backgroundPushGate: () => backgroundPushGate,
|
|
9615
9495
|
clearAutoMarker: () => clearAutoMarker,
|
|
@@ -9618,24 +9498,26 @@ __export(claim_push_bg_exports, {
|
|
|
9618
9498
|
readAutoMarker: () => readAutoMarker,
|
|
9619
9499
|
readPushTokenEnc: () => readPushTokenEnc,
|
|
9620
9500
|
runBackgroundClaimPush: () => runBackgroundClaimPush,
|
|
9501
|
+
shouldNudgeUnpushed: () => shouldNudgeUnpushed,
|
|
9502
|
+
unpushedNudgeGate: () => unpushedNudgeGate,
|
|
9621
9503
|
writeAutoMarker: () => writeAutoMarker,
|
|
9622
9504
|
writePushTokenEnc: () => writePushTokenEnc
|
|
9623
9505
|
});
|
|
9624
9506
|
import { createHash as createHash3 } from "crypto";
|
|
9625
|
-
import { readFileSync as
|
|
9626
|
-
import { join as
|
|
9627
|
-
import { homedir as
|
|
9507
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, existsSync as existsSync8, rmSync as rmSync3 } from "fs";
|
|
9508
|
+
import { join as join14 } from "path";
|
|
9509
|
+
import { homedir as homedir11 } from "os";
|
|
9628
9510
|
async function writePushTokenEnc(rawToken) {
|
|
9629
|
-
|
|
9511
|
+
mkdirSync11(TERMINALHIRE_DIR8, { recursive: true });
|
|
9630
9512
|
const key = await loadKey2();
|
|
9631
9513
|
const blob = encrypt2(rawToken, key);
|
|
9632
|
-
|
|
9514
|
+
writeFileSync11(CLAIM_PUSH_TOKEN_FILE, JSON.stringify(blob, null, 2), { encoding: "utf8" });
|
|
9633
9515
|
}
|
|
9634
9516
|
async function readPushTokenEnc() {
|
|
9635
|
-
if (!
|
|
9517
|
+
if (!existsSync8(CLAIM_PUSH_TOKEN_FILE)) return void 0;
|
|
9636
9518
|
try {
|
|
9637
9519
|
const key = await loadKey2();
|
|
9638
|
-
const blob = JSON.parse(
|
|
9520
|
+
const blob = JSON.parse(readFileSync13(CLAIM_PUSH_TOKEN_FILE, "utf8"));
|
|
9639
9521
|
return decrypt2(blob, key);
|
|
9640
9522
|
} catch {
|
|
9641
9523
|
return void 0;
|
|
@@ -9649,14 +9531,14 @@ function clearPushTokenEnc() {
|
|
|
9649
9531
|
}
|
|
9650
9532
|
function readAutoMarker() {
|
|
9651
9533
|
try {
|
|
9652
|
-
return
|
|
9534
|
+
return existsSync8(CLAIM_PUSH_AUTO_MARKER) ? JSON.parse(readFileSync13(CLAIM_PUSH_AUTO_MARKER, "utf8")) : null;
|
|
9653
9535
|
} catch {
|
|
9654
9536
|
return null;
|
|
9655
9537
|
}
|
|
9656
9538
|
}
|
|
9657
9539
|
function writeAutoMarker(marker) {
|
|
9658
|
-
|
|
9659
|
-
|
|
9540
|
+
mkdirSync11(TERMINALHIRE_DIR8, { recursive: true });
|
|
9541
|
+
writeFileSync11(CLAIM_PUSH_AUTO_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
9660
9542
|
}
|
|
9661
9543
|
function clearAutoMarker() {
|
|
9662
9544
|
try {
|
|
@@ -9689,9 +9571,46 @@ function backgroundPushGate(params) {
|
|
|
9689
9571
|
}
|
|
9690
9572
|
return { push: true, reason: "ok" };
|
|
9691
9573
|
}
|
|
9574
|
+
function unpushedNudgeGate(params) {
|
|
9575
|
+
const {
|
|
9576
|
+
autoMarkerExists,
|
|
9577
|
+
tokenFileExists,
|
|
9578
|
+
manualMarkerExists,
|
|
9579
|
+
lastSnapshotHash,
|
|
9580
|
+
currentHash,
|
|
9581
|
+
claimCount
|
|
9582
|
+
} = params;
|
|
9583
|
+
if (autoMarkerExists && tokenFileExists) return false;
|
|
9584
|
+
if (!manualMarkerExists) return false;
|
|
9585
|
+
if (!(claimCount > 0)) return false;
|
|
9586
|
+
return lastSnapshotHash !== currentHash;
|
|
9587
|
+
}
|
|
9588
|
+
async function shouldNudgeUnpushed() {
|
|
9589
|
+
try {
|
|
9590
|
+
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
9591
|
+
const pushed = listClaims2().map((c) => toPushedClaim2(c));
|
|
9592
|
+
const currentHash = computeSnapshotHash(pushed);
|
|
9593
|
+
let manual = null;
|
|
9594
|
+
try {
|
|
9595
|
+
manual = existsSync8(CLAIM_PUSH_MANUAL_MARKER) ? JSON.parse(readFileSync13(CLAIM_PUSH_MANUAL_MARKER, "utf8")) : null;
|
|
9596
|
+
} catch {
|
|
9597
|
+
manual = null;
|
|
9598
|
+
}
|
|
9599
|
+
return unpushedNudgeGate({
|
|
9600
|
+
autoMarkerExists: existsSync8(CLAIM_PUSH_AUTO_MARKER),
|
|
9601
|
+
tokenFileExists: existsSync8(CLAIM_PUSH_TOKEN_FILE),
|
|
9602
|
+
manualMarkerExists: !!manual,
|
|
9603
|
+
lastSnapshotHash: manual?.lastSnapshotHash ?? null,
|
|
9604
|
+
currentHash,
|
|
9605
|
+
claimCount: pushed.length
|
|
9606
|
+
});
|
|
9607
|
+
} catch {
|
|
9608
|
+
return false;
|
|
9609
|
+
}
|
|
9610
|
+
}
|
|
9692
9611
|
async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
9693
9612
|
try {
|
|
9694
|
-
if (!
|
|
9613
|
+
if (!existsSync8(CLAIM_PUSH_AUTO_MARKER) || !existsSync8(CLAIM_PUSH_TOKEN_FILE)) return;
|
|
9695
9614
|
const marker = readAutoMarker();
|
|
9696
9615
|
if (!marker || !marker.autoConsentedAt) return;
|
|
9697
9616
|
const { listClaims: listClaims2, toPushedClaim: toPushedClaim2, PUSHED_CLAIM_FIELDS: PUSHED_CLAIM_FIELDS2 } = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
@@ -9729,20 +9648,152 @@ async function runBackgroundClaimPush({ now = Date.now() } = {}) {
|
|
|
9729
9648
|
} catch {
|
|
9730
9649
|
}
|
|
9731
9650
|
}
|
|
9732
|
-
var TERMINALHIRE_DIR8, CLAIM_PUSH_AUTO_MARKER, CLAIM_PUSH_TOKEN_FILE, CLAIM_SYNC_BASE, AUTO_CONSENT_VERSION, AUTO_PUSH_THROTTLE_MS;
|
|
9651
|
+
var TERMINALHIRE_DIR8, CLAIM_PUSH_AUTO_MARKER, CLAIM_PUSH_TOKEN_FILE, CLAIM_PUSH_MANUAL_MARKER, CLAIM_SYNC_BASE, AUTO_CONSENT_VERSION, AUTO_PUSH_THROTTLE_MS;
|
|
9733
9652
|
var init_claim_push_bg = __esm({
|
|
9734
9653
|
"bin/claim-push-bg.js"() {
|
|
9735
9654
|
"use strict";
|
|
9736
9655
|
init_github_auth();
|
|
9737
|
-
TERMINALHIRE_DIR8 = process.env.TERMINALHIRE_DIR ||
|
|
9738
|
-
CLAIM_PUSH_AUTO_MARKER =
|
|
9739
|
-
CLAIM_PUSH_TOKEN_FILE =
|
|
9656
|
+
TERMINALHIRE_DIR8 = process.env.TERMINALHIRE_DIR || join14(homedir11(), ".terminalhire");
|
|
9657
|
+
CLAIM_PUSH_AUTO_MARKER = join14(TERMINALHIRE_DIR8, "claim-push-auto.json");
|
|
9658
|
+
CLAIM_PUSH_TOKEN_FILE = join14(TERMINALHIRE_DIR8, "claim-push-token.enc");
|
|
9659
|
+
CLAIM_PUSH_MANUAL_MARKER = join14(TERMINALHIRE_DIR8, "claim-push.json");
|
|
9740
9660
|
CLAIM_SYNC_BASE = "https://terminalhire.com";
|
|
9741
9661
|
AUTO_CONSENT_VERSION = 2;
|
|
9742
9662
|
AUTO_PUSH_THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
9743
9663
|
}
|
|
9744
9664
|
});
|
|
9745
9665
|
|
|
9666
|
+
// bin/version-nudge.js
|
|
9667
|
+
var version_nudge_exports = {};
|
|
9668
|
+
__export(version_nudge_exports, {
|
|
9669
|
+
buildStaleNudge: () => buildStaleNudge,
|
|
9670
|
+
cachedStaleNudge: () => cachedStaleNudge,
|
|
9671
|
+
compareVersions: () => compareVersions,
|
|
9672
|
+
emitInteractiveNudge: () => emitInteractiveNudge,
|
|
9673
|
+
parseVersion: () => parseVersion,
|
|
9674
|
+
readLatestVersionFromCache: () => readLatestVersionFromCache,
|
|
9675
|
+
readLocalVersion: () => readLocalVersion,
|
|
9676
|
+
recordNag: () => recordNag,
|
|
9677
|
+
shouldNag: () => shouldNag
|
|
9678
|
+
});
|
|
9679
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, existsSync as existsSync9 } from "fs";
|
|
9680
|
+
import { join as join15 } from "path";
|
|
9681
|
+
import { homedir as homedir12 } from "os";
|
|
9682
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9683
|
+
function stateDir() {
|
|
9684
|
+
return process.env.TERMINALHIRE_DIR || join15(homedir12(), ".terminalhire");
|
|
9685
|
+
}
|
|
9686
|
+
function indexCacheFile() {
|
|
9687
|
+
return join15(stateDir(), "index-cache.json");
|
|
9688
|
+
}
|
|
9689
|
+
function nudgeStateFile() {
|
|
9690
|
+
return join15(stateDir(), "version-nudge.json");
|
|
9691
|
+
}
|
|
9692
|
+
function parseVersion(v) {
|
|
9693
|
+
if (typeof v !== "string") return null;
|
|
9694
|
+
const m = v.trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
9695
|
+
if (!m) return null;
|
|
9696
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
9697
|
+
}
|
|
9698
|
+
function compareVersions(a, b) {
|
|
9699
|
+
const pa = parseVersion(a);
|
|
9700
|
+
const pb = parseVersion(b);
|
|
9701
|
+
if (!pa || !pb) return null;
|
|
9702
|
+
for (let i = 0; i < 3; i++) {
|
|
9703
|
+
if (pa[i] < pb[i]) return -1;
|
|
9704
|
+
if (pa[i] > pb[i]) return 1;
|
|
9705
|
+
}
|
|
9706
|
+
return 0;
|
|
9707
|
+
}
|
|
9708
|
+
function buildStaleNudge(local, latest) {
|
|
9709
|
+
if (compareVersions(local, latest) !== -1) return null;
|
|
9710
|
+
return `your terminalhire CLI is behind (${local} \u2192 ${latest}) \u2014 npm i -g terminalhire@latest`;
|
|
9711
|
+
}
|
|
9712
|
+
function readLocalVersion() {
|
|
9713
|
+
try {
|
|
9714
|
+
const candidates = [
|
|
9715
|
+
join15(__dirname, "..", "..", "package.json"),
|
|
9716
|
+
join15(__dirname, "..", "package.json")
|
|
9717
|
+
];
|
|
9718
|
+
for (const p of candidates) {
|
|
9719
|
+
if (existsSync9(p)) {
|
|
9720
|
+
const pkg = JSON.parse(readFileSync14(p, "utf8"));
|
|
9721
|
+
if (pkg.version) return pkg.version;
|
|
9722
|
+
}
|
|
9723
|
+
}
|
|
9724
|
+
} catch {
|
|
9725
|
+
}
|
|
9726
|
+
return null;
|
|
9727
|
+
}
|
|
9728
|
+
function readLatestVersionFromCache() {
|
|
9729
|
+
try {
|
|
9730
|
+
const cache = JSON.parse(readFileSync14(indexCacheFile(), "utf8"));
|
|
9731
|
+
const v = cache?.index?.cliVersion;
|
|
9732
|
+
return typeof v === "string" ? v : null;
|
|
9733
|
+
} catch {
|
|
9734
|
+
return null;
|
|
9735
|
+
}
|
|
9736
|
+
}
|
|
9737
|
+
function cachedStaleNudge(localVersion) {
|
|
9738
|
+
const local = localVersion ?? readLocalVersion();
|
|
9739
|
+
if (!local) return null;
|
|
9740
|
+
return buildStaleNudge(local, readLatestVersionFromCache());
|
|
9741
|
+
}
|
|
9742
|
+
function shouldNag(now = Date.now()) {
|
|
9743
|
+
try {
|
|
9744
|
+
const state = JSON.parse(readFileSync14(nudgeStateFile(), "utf8"));
|
|
9745
|
+
const last = state?.lastNaggedAt;
|
|
9746
|
+
if (typeof last !== "number" || !Number.isFinite(last)) return true;
|
|
9747
|
+
return now - last >= NAG_INTERVAL_MS;
|
|
9748
|
+
} catch {
|
|
9749
|
+
return true;
|
|
9750
|
+
}
|
|
9751
|
+
}
|
|
9752
|
+
function recordNag(now = Date.now()) {
|
|
9753
|
+
try {
|
|
9754
|
+
mkdirSync12(stateDir(), { recursive: true });
|
|
9755
|
+
writeFileSync12(nudgeStateFile(), JSON.stringify({ lastNaggedAt: now }) + "\n", "utf8");
|
|
9756
|
+
} catch {
|
|
9757
|
+
}
|
|
9758
|
+
}
|
|
9759
|
+
function emitInteractiveNudge({ now = Date.now(), stream = process.stderr, localVersion } = {}) {
|
|
9760
|
+
try {
|
|
9761
|
+
const nudge = cachedStaleNudge(localVersion);
|
|
9762
|
+
if (!nudge) return false;
|
|
9763
|
+
if (!shouldNag(now)) return false;
|
|
9764
|
+
stream.write(`${nudge}
|
|
9765
|
+
`);
|
|
9766
|
+
recordNag(now);
|
|
9767
|
+
return true;
|
|
9768
|
+
} catch {
|
|
9769
|
+
return false;
|
|
9770
|
+
}
|
|
9771
|
+
}
|
|
9772
|
+
var __dirname, NAG_INTERVAL_MS;
|
|
9773
|
+
var init_version_nudge = __esm({
|
|
9774
|
+
"bin/version-nudge.js"() {
|
|
9775
|
+
"use strict";
|
|
9776
|
+
__dirname = fileURLToPath2(new URL(".", import.meta.url));
|
|
9777
|
+
NAG_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
9778
|
+
}
|
|
9779
|
+
});
|
|
9780
|
+
|
|
9781
|
+
// bin/beta-nudge.js
|
|
9782
|
+
var beta_nudge_exports = {};
|
|
9783
|
+
__export(beta_nudge_exports, {
|
|
9784
|
+
buildBetaNudge: () => buildBetaNudge
|
|
9785
|
+
});
|
|
9786
|
+
function buildBetaNudge(betaOpen, betaOptIn) {
|
|
9787
|
+
if (betaOpen !== true) return null;
|
|
9788
|
+
if (betaOptIn === true) return null;
|
|
9789
|
+
return "\u{1F9EA} Beta's open \u2014 run `terminalhire beta` to join as a Founding Contributor";
|
|
9790
|
+
}
|
|
9791
|
+
var init_beta_nudge = __esm({
|
|
9792
|
+
"bin/beta-nudge.js"() {
|
|
9793
|
+
"use strict";
|
|
9794
|
+
}
|
|
9795
|
+
});
|
|
9796
|
+
|
|
9746
9797
|
// bin/jpi-refresh.js
|
|
9747
9798
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9748
9799
|
|
|
@@ -10218,6 +10269,12 @@ async function run() {
|
|
|
10218
10269
|
topMatches = filterFreshMatches2(topMatches, seenHistory);
|
|
10219
10270
|
} catch {
|
|
10220
10271
|
}
|
|
10272
|
+
let unpushedClaims = false;
|
|
10273
|
+
try {
|
|
10274
|
+
const { shouldNudgeUnpushed: shouldNudgeUnpushed2 } = await Promise.resolve().then(() => (init_claim_push_bg(), claim_push_bg_exports));
|
|
10275
|
+
unpushedClaims = await shouldNudgeUnpushed2();
|
|
10276
|
+
} catch {
|
|
10277
|
+
}
|
|
10221
10278
|
const cacheEntry = {
|
|
10222
10279
|
index,
|
|
10223
10280
|
matchCount,
|
|
@@ -10226,6 +10283,7 @@ async function run() {
|
|
|
10226
10283
|
incomingPending,
|
|
10227
10284
|
unreadChat,
|
|
10228
10285
|
sessionStale,
|
|
10286
|
+
unpushedClaims,
|
|
10229
10287
|
// In-process-only despite being persisted: the render pass receives it as
|
|
10230
10288
|
// a function argument below. A future cache READER must not gate on this
|
|
10231
10289
|
// field without re-checking isContributeEnabled/isContributePrompted at
|
|
@@ -10264,6 +10322,7 @@ async function run() {
|
|
|
10264
10322
|
incomingPending,
|
|
10265
10323
|
sessionStale,
|
|
10266
10324
|
contributeNudge,
|
|
10325
|
+
unpushedClaims,
|
|
10267
10326
|
baseUrl: API_URL2,
|
|
10268
10327
|
seenHistory,
|
|
10269
10328
|
widen,
|
package/dist/bin/jpi-spinner.js
CHANGED
|
@@ -249,6 +249,9 @@ function buildContributeNudgeLine(contributeNudge) {
|
|
|
249
249
|
function buildSessionStaleLine(sessionStale) {
|
|
250
250
|
return sessionStale === true ? "\u26A0 terminalhire: linked session expired \u2014 run: terminalhire login" : null;
|
|
251
251
|
}
|
|
252
|
+
function buildUnpushedClaimsLine(unpushedClaims) {
|
|
253
|
+
return unpushedClaims === true ? "\u26A0 new claims not yet on your dashboard \u2014 run: terminalhire claim --push --keep-updated" : null;
|
|
254
|
+
}
|
|
252
255
|
function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
253
256
|
const {
|
|
254
257
|
sessionTags,
|
|
@@ -257,16 +260,19 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
257
260
|
incomingPending,
|
|
258
261
|
sessionStale,
|
|
259
262
|
contributeNudge,
|
|
263
|
+
unpushedClaims,
|
|
260
264
|
seenHistory
|
|
261
265
|
} = opts;
|
|
262
266
|
const staleLine = buildSessionStaleLine(sessionStale);
|
|
263
267
|
const withStale = (pool2) => staleLine ? [staleLine, ...pool2] : pool2;
|
|
264
268
|
const introLine = buildIncomingIntroLine(incomingPending);
|
|
265
269
|
const contributeLine = buildContributeNudgeLine(contributeNudge);
|
|
270
|
+
const unpushedLine = buildUnpushedClaimsLine(unpushedClaims);
|
|
266
271
|
const ranked = filterFreshMatches(rankBySessionTags(topMatches, sessionTags), seenHistory);
|
|
267
272
|
if (!Array.isArray(ranked) || ranked.length === 0) {
|
|
268
273
|
if (introLine) return withStale([introLine]);
|
|
269
274
|
if (contributeLine) return withStale([contributeLine]);
|
|
275
|
+
if (unpushedLine) return withStale([unpushedLine]);
|
|
270
276
|
const peerLine = buildPeerLine(topPeers);
|
|
271
277
|
return withStale(peerLine ? [peerLine] : []);
|
|
272
278
|
}
|
|
@@ -276,6 +282,7 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
276
282
|
const pool = [...headers.slice(0, cap), ctaVerb()];
|
|
277
283
|
if (introLine) pool.push(introLine);
|
|
278
284
|
if (contributeLine) pool.push(contributeLine);
|
|
285
|
+
if (unpushedLine) pool.push(unpushedLine);
|
|
279
286
|
return withStale(pool);
|
|
280
287
|
}
|
|
281
288
|
|
package/dist/bin/spinner.js
CHANGED
|
@@ -346,6 +346,9 @@ function buildContributeNudgeLine(contributeNudge) {
|
|
|
346
346
|
function buildSessionStaleLine(sessionStale) {
|
|
347
347
|
return sessionStale === true ? "\u26A0 terminalhire: linked session expired \u2014 run: terminalhire login" : null;
|
|
348
348
|
}
|
|
349
|
+
function buildUnpushedClaimsLine(unpushedClaims) {
|
|
350
|
+
return unpushedClaims === true ? "\u26A0 new claims not yet on your dashboard \u2014 run: terminalhire claim --push --keep-updated" : null;
|
|
351
|
+
}
|
|
349
352
|
function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
350
353
|
const {
|
|
351
354
|
sessionTags,
|
|
@@ -354,16 +357,19 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
354
357
|
incomingPending,
|
|
355
358
|
sessionStale,
|
|
356
359
|
contributeNudge,
|
|
360
|
+
unpushedClaims,
|
|
357
361
|
seenHistory
|
|
358
362
|
} = opts;
|
|
359
363
|
const staleLine = buildSessionStaleLine(sessionStale);
|
|
360
364
|
const withStale = (pool2) => staleLine ? [staleLine, ...pool2] : pool2;
|
|
361
365
|
const introLine = buildIncomingIntroLine(incomingPending);
|
|
362
366
|
const contributeLine = buildContributeNudgeLine(contributeNudge);
|
|
367
|
+
const unpushedLine = buildUnpushedClaimsLine(unpushedClaims);
|
|
363
368
|
const ranked = filterFreshMatches(rankBySessionTags(topMatches, sessionTags), seenHistory);
|
|
364
369
|
if (!Array.isArray(ranked) || ranked.length === 0) {
|
|
365
370
|
if (introLine) return withStale([introLine]);
|
|
366
371
|
if (contributeLine) return withStale([contributeLine]);
|
|
372
|
+
if (unpushedLine) return withStale([unpushedLine]);
|
|
367
373
|
const peerLine = buildPeerLine(topPeers);
|
|
368
374
|
return withStale(peerLine ? [peerLine] : []);
|
|
369
375
|
}
|
|
@@ -373,6 +379,7 @@ function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
|
373
379
|
const pool = [...headers.slice(0, cap), ctaVerb()];
|
|
374
380
|
if (introLine) pool.push(introLine);
|
|
375
381
|
if (contributeLine) pool.push(contributeLine);
|
|
382
|
+
if (unpushedLine) pool.push(unpushedLine);
|
|
376
383
|
return withStale(pool);
|
|
377
384
|
}
|
|
378
385
|
|
|
@@ -1057,6 +1064,7 @@ function renderRefreshSurface(topMatches, sc, opts = {}) {
|
|
|
1057
1064
|
incomingPending: opts.incomingPending,
|
|
1058
1065
|
sessionStale: opts.sessionStale,
|
|
1059
1066
|
contributeNudge: opts.contributeNudge,
|
|
1067
|
+
unpushedClaims: opts.unpushedClaims,
|
|
1060
1068
|
seenHistory
|
|
1061
1069
|
});
|
|
1062
1070
|
if (verbs.length > 0) applySpinnerVerbs(verbs, sc.mode);
|
|
@@ -1083,6 +1091,7 @@ export {
|
|
|
1083
1091
|
buildSpinnerPool,
|
|
1084
1092
|
buildTips,
|
|
1085
1093
|
buildTipsDetailed,
|
|
1094
|
+
buildUnpushedClaimsLine,
|
|
1086
1095
|
clearSpinnerTips,
|
|
1087
1096
|
clearSpinnerVerbs,
|
|
1088
1097
|
ctaVerb,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminalhire",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Local-first job matching for developers — ambient job matches in the Claude Code spinner. Matching runs on your machine; your profile never leaves it.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|