terminalhire 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/claim-push-bg.js +2 -2
- package/dist/bin/jpi-bounties.js +114 -28
- package/dist/bin/jpi-chat-read.js +72 -10
- package/dist/bin/jpi-chat.js +262 -80
- package/dist/bin/jpi-claim.js +79 -4
- package/dist/bin/jpi-contribute.js +19 -2
- package/dist/bin/jpi-devs.js +130 -39
- package/dist/bin/jpi-dispatch.js +1716 -255
- package/dist/bin/jpi-hub.js +9712 -0
- package/dist/bin/jpi-inbox.js +261 -80
- package/dist/bin/jpi-init.js +77 -2
- package/dist/bin/jpi-intro.js +71 -35
- package/dist/bin/jpi-jobs.js +118 -25
- package/dist/bin/jpi-learn.js +19 -2
- package/dist/bin/jpi-login.js +79 -4
- package/dist/bin/jpi-profile.js +19 -2
- package/dist/bin/jpi-project.js +77 -2
- package/dist/bin/jpi-refresh.js +79 -4
- package/dist/bin/jpi-save.js +19 -2
- package/dist/bin/jpi-spinner.js +9 -0
- package/dist/bin/jpi-sync.js +19 -2
- package/dist/bin/jpi-trajectory.js +19 -2
- package/dist/bin/spinner.js +9 -0
- package/dist/bin/tui-core.js +440 -0
- package/dist/src/chat-client.js +11 -2
- package/dist/src/chat-keystore.js +11 -2
- package/dist/src/github-auth.js +2 -2
- package/dist/src/intro.js +71 -35
- package/dist/src/profile.js +11 -2
- package/dist/src/signal.js +9 -0
- package/dist/src/trajectory.js +19 -2
- package/package.json +1 -1
|
@@ -45,9 +45,9 @@ var init_keytar = __esm({
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
// node-file:/Users
|
|
48
|
+
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
|
|
49
49
|
var require_keytar = __commonJS({
|
|
50
|
-
"node-file:/Users
|
|
50
|
+
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
51
51
|
"use strict";
|
|
52
52
|
init_keytar();
|
|
53
53
|
try {
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -749,6 +749,30 @@ var init_contribution_gate = __esm({
|
|
|
749
749
|
}
|
|
750
750
|
});
|
|
751
751
|
|
|
752
|
+
// ../../packages/core/src/credential/rigor.ts
|
|
753
|
+
function deriveRigorTiers(input) {
|
|
754
|
+
const tiers = {};
|
|
755
|
+
if (input.reviewerAssociations !== void 0) {
|
|
756
|
+
tiers.maintainerReviewed = input.reviewerAssociations.some(
|
|
757
|
+
(a) => MAINTAINER_SET.has(String(a).toUpperCase())
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
return tiers;
|
|
761
|
+
}
|
|
762
|
+
var RIGOR, MAINTAINER_SET;
|
|
763
|
+
var init_rigor = __esm({
|
|
764
|
+
"../../packages/core/src/credential/rigor.ts"() {
|
|
765
|
+
"use strict";
|
|
766
|
+
RIGOR = {
|
|
767
|
+
/** `authorAssociation` values that count as a maintainer review. */
|
|
768
|
+
MAINTAINER_ASSOCIATIONS: ["OWNER", "MEMBER", "COLLABORATOR"]
|
|
769
|
+
};
|
|
770
|
+
MAINTAINER_SET = new Set(
|
|
771
|
+
RIGOR.MAINTAINER_ASSOCIATIONS.map((a) => a.toUpperCase())
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
|
|
752
776
|
// ../../packages/core/src/github.ts
|
|
753
777
|
function ghHeaders(token) {
|
|
754
778
|
const headers = {
|
|
@@ -1027,6 +1051,33 @@ async function computeAcceptanceFromSearch(login, token, ownedOrgs, cache, gates
|
|
|
1027
1051
|
if (mergedAt > b.lastMergedAt) b.lastMergedAt = mergedAt;
|
|
1028
1052
|
}
|
|
1029
1053
|
}
|
|
1054
|
+
if (token) {
|
|
1055
|
+
const enrichStats = { transient: 0 };
|
|
1056
|
+
const enrichCount = Math.min(qualifyingPRs.length, MAX_ENRICH_PRS);
|
|
1057
|
+
for (let i = 0; i < enrichCount; i++) {
|
|
1058
|
+
const pr = qualifyingPRs[i];
|
|
1059
|
+
const ref = parseGitHubRef(pr.url);
|
|
1060
|
+
if (!ref || ref.kind !== "pull") continue;
|
|
1061
|
+
try {
|
|
1062
|
+
const reviews = await ghFetch(
|
|
1063
|
+
`/repos/${ref.owner}/${ref.repo}/pulls/${ref.number}/reviews?per_page=100`,
|
|
1064
|
+
token
|
|
1065
|
+
);
|
|
1066
|
+
const reviewerAssociations = reviews.map((r) => r.author_association);
|
|
1067
|
+
const tiers = deriveRigorTiers({ reviewerAssociations });
|
|
1068
|
+
if (tiers.maintainerReviewed !== void 0) pr.maintainerReviewed = tiers.maintainerReviewed;
|
|
1069
|
+
} catch (err) {
|
|
1070
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1071
|
+
if (TRANSIENT_META_ERROR.test(msg)) {
|
|
1072
|
+
enrichStats.transient += 1;
|
|
1073
|
+
console.warn(
|
|
1074
|
+
`[acceptance] ${login}: per-PR rigor enrichment transient failure (${enrichStats.transient}) \u2014 leaving remaining tiers undefined rather than fabricating a false`
|
|
1075
|
+
);
|
|
1076
|
+
break;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1030
1081
|
const finalDomains = {};
|
|
1031
1082
|
for (const [d, b] of Object.entries(byDomain)) {
|
|
1032
1083
|
finalDomains[d] = {
|
|
@@ -1233,6 +1284,17 @@ async function fetchPRScoringFacts(prUrl, token, signal) {
|
|
|
1233
1284
|
}
|
|
1234
1285
|
const contributors = await repoContributorCount(owner, repo, token, sig);
|
|
1235
1286
|
const { closesIssues, linkageSource } = await resolveClosingIssues(owner, repo, number, pr.body ?? "", token, sig);
|
|
1287
|
+
let reviewerAssociations;
|
|
1288
|
+
try {
|
|
1289
|
+
const reviews = await ghFetch(
|
|
1290
|
+
`/repos/${owner}/${repo}/pulls/${number}/reviews?per_page=100`,
|
|
1291
|
+
token,
|
|
1292
|
+
sig
|
|
1293
|
+
);
|
|
1294
|
+
reviewerAssociations = reviews.map((r) => r.author_association);
|
|
1295
|
+
} catch {
|
|
1296
|
+
reviewerAssociations = void 0;
|
|
1297
|
+
}
|
|
1236
1298
|
return {
|
|
1237
1299
|
repo: `${owner}/${repo}`,
|
|
1238
1300
|
prNumber: number,
|
|
@@ -1250,17 +1312,24 @@ async function fetchPRScoringFacts(prUrl, token, signal) {
|
|
|
1250
1312
|
repoArchived: !!repoMeta?.archived,
|
|
1251
1313
|
repoFork: !!repoMeta?.fork,
|
|
1252
1314
|
repoPrivate: !!repoMeta?.private,
|
|
1315
|
+
additions: pr.additions ?? null,
|
|
1316
|
+
deletions: pr.deletions ?? null,
|
|
1317
|
+
changedFiles: pr.changed_files ?? null,
|
|
1318
|
+
repoForks: repoMeta?.forks_count ?? null,
|
|
1319
|
+
reviewerAssociations,
|
|
1253
1320
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1254
1321
|
};
|
|
1255
1322
|
}
|
|
1256
|
-
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1323
|
+
var TRACTION_TOP_N, CANDIDATE_PR_PAGE, MAX_ENRICH_PRS, OPEN_PR_PAGE, TRANSIENT_META_ERROR, RESUME_DECAY_HALF_LIFE_MS, RESUME_MIN_SCORE;
|
|
1257
1324
|
var init_github = __esm({
|
|
1258
1325
|
"../../packages/core/src/github.ts"() {
|
|
1259
1326
|
"use strict";
|
|
1260
1327
|
init_vocabulary();
|
|
1261
1328
|
init_contribution_gate();
|
|
1329
|
+
init_rigor();
|
|
1262
1330
|
TRACTION_TOP_N = 6;
|
|
1263
1331
|
CANDIDATE_PR_PAGE = 50;
|
|
1332
|
+
MAX_ENRICH_PRS = 12;
|
|
1264
1333
|
OPEN_PR_PAGE = 20;
|
|
1265
1334
|
TRANSIENT_META_ERROR = /HTTP 403|HTTP 429|rate limit|HTTP 5\d\d|timeout|network|fetch failed/i;
|
|
1266
1335
|
RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -6772,10 +6841,13 @@ function deriveLegibleProfile(credential, recency, traction, seniorityBand) {
|
|
|
6772
6841
|
if (daysAgo !== void 0) s += ` \u2014 most recent ${daysAgo}d ago`;
|
|
6773
6842
|
proofSentence = `${s}.`;
|
|
6774
6843
|
}
|
|
6844
|
+
const enrichedPRs = ok ? credential.qualifyingPRs ?? [] : [];
|
|
6845
|
+
const maintainerReviewedCount = enrichedPRs.some((p) => p.maintainerReviewed !== void 0) ? enrichedPRs.filter((p) => p.maintainerReviewed === true).length : void 0;
|
|
6775
6846
|
const auditableBadge = ok ? {
|
|
6776
6847
|
mergedTotal: credential.qualifyingTotal,
|
|
6777
6848
|
distinctOrgs: orgCount,
|
|
6778
|
-
thresholds: { stars: MIN_STARS, contributors: MIN_CONTRIBUTORS }
|
|
6849
|
+
thresholds: { stars: MIN_STARS, contributors: MIN_CONTRIBUTORS },
|
|
6850
|
+
...maintainerReviewedCount !== void 0 ? { maintainerReviewedCount } : {}
|
|
6779
6851
|
} : null;
|
|
6780
6852
|
const profile = {
|
|
6781
6853
|
headline,
|
|
@@ -6971,6 +7043,7 @@ __export(src_exports, {
|
|
|
6971
7043
|
MENTION_DELTA: () => MENTION_DELTA,
|
|
6972
7044
|
MIN_CONTRIBUTORS: () => MIN_CONTRIBUTORS,
|
|
6973
7045
|
MIN_STARS: () => MIN_STARS,
|
|
7046
|
+
RIGOR: () => RIGOR,
|
|
6974
7047
|
STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
|
|
6975
7048
|
SYNONYMS: () => SYNONYMS,
|
|
6976
7049
|
TRIVIAL_PR_TITLE: () => TRIVIAL_PR_TITLE,
|
|
@@ -6999,6 +7072,7 @@ __export(src_exports, {
|
|
|
6999
7072
|
decryptMessage: () => decryptMessage,
|
|
7000
7073
|
deriveLegibleProfile: () => deriveLegibleProfile,
|
|
7001
7074
|
deriveResumeTrend: () => deriveResumeTrend,
|
|
7075
|
+
deriveRigorTiers: () => deriveRigorTiers,
|
|
7002
7076
|
deriveSharedKey: () => deriveSharedKey,
|
|
7003
7077
|
deriveTrajectoryNarrative: () => deriveTrajectoryNarrative,
|
|
7004
7078
|
displayableDrift: () => displayableDrift,
|
|
@@ -7078,6 +7152,7 @@ var init_src = __esm({
|
|
|
7078
7152
|
init_job_status();
|
|
7079
7153
|
init_legible();
|
|
7080
7154
|
init_legible_trajectory();
|
|
7155
|
+
init_rigor();
|
|
7081
7156
|
init_short_token();
|
|
7082
7157
|
}
|
|
7083
7158
|
});
|
|
@@ -7090,9 +7165,9 @@ var init_keytar = __esm({
|
|
|
7090
7165
|
}
|
|
7091
7166
|
});
|
|
7092
7167
|
|
|
7093
|
-
// node-file:/Users
|
|
7168
|
+
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
|
|
7094
7169
|
var require_keytar = __commonJS({
|
|
7095
|
-
"node-file:/Users
|
|
7170
|
+
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
7096
7171
|
"use strict";
|
|
7097
7172
|
init_keytar();
|
|
7098
7173
|
try {
|
|
@@ -7512,36 +7587,46 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
|
7512
7587
|
console.log(` Claim: ${sanitizeText(b.claimUrl ?? job.url)}`);
|
|
7513
7588
|
console.log(` \u2192 terminalhire claim ${ref}`);
|
|
7514
7589
|
}
|
|
7590
|
+
async function getBounties({ quiet = false, offline = false } = {}) {
|
|
7591
|
+
if (!quiet) console.log(`Fetching bounty index from ${API_URL}/api/index...`);
|
|
7592
|
+
const index = offline ? readIndexCache() : await fetchIndex();
|
|
7593
|
+
if (offline && !index) return { status: "no-cache" };
|
|
7594
|
+
let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");
|
|
7595
|
+
if (PRICED_ONLY) bounties = bounties.filter((j) => j.bounty?.amountUSD != null);
|
|
7596
|
+
if (WINNABLE_ONLY) bounties = bounties.filter((j) => (j.bounty?.competingOpenPRs ?? 0) === 0);
|
|
7597
|
+
if (bounties.length === 0) {
|
|
7598
|
+
return { status: "empty" };
|
|
7599
|
+
}
|
|
7600
|
+
const ranked = /* @__PURE__ */ new Map();
|
|
7601
|
+
try {
|
|
7602
|
+
const { readProfile: readProfile2, profileToFingerprint: profileToFingerprint2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
|
|
7603
|
+
const { match: match2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
7604
|
+
const profile = await readProfile2();
|
|
7605
|
+
if (profile.skillTags.length > 0) {
|
|
7606
|
+
const fp = profileToFingerprint2(profile);
|
|
7607
|
+
for (const r of match2(fp, bounties, bounties.length)) {
|
|
7608
|
+
ranked.set(r.job.id, { score: r.score, reason: r.reason, matchedTags: r.matchedTags });
|
|
7609
|
+
}
|
|
7610
|
+
}
|
|
7611
|
+
} catch {
|
|
7612
|
+
}
|
|
7613
|
+
const score = (j) => ranked.get(j.id)?.score ?? 0;
|
|
7614
|
+
const amt = (j) => j.bounty?.amountUSD ?? -1;
|
|
7615
|
+
const contested = (j) => (j.bounty?.competingOpenPRs ?? 0) > 0 ? 1 : 0;
|
|
7616
|
+
bounties.sort((a, b) => contested(a) - contested(b) || score(b) - score(a) || amt(b) - amt(a));
|
|
7617
|
+
const matchedCount = bounties.filter((j) => score(j) > 0).length;
|
|
7618
|
+
return { status: "ok", bounties, ranked, matchedCount };
|
|
7619
|
+
}
|
|
7515
7620
|
async function run() {
|
|
7516
7621
|
try {
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");
|
|
7520
|
-
if (PRICED_ONLY) bounties = bounties.filter((j) => j.bounty?.amountUSD != null);
|
|
7521
|
-
if (WINNABLE_ONLY) bounties = bounties.filter((j) => (j.bounty?.competingOpenPRs ?? 0) === 0);
|
|
7522
|
-
if (bounties.length === 0) {
|
|
7622
|
+
const result = await getBounties();
|
|
7623
|
+
if (result.status === "empty") {
|
|
7523
7624
|
console.log("\nNo bounties available right now. Try again later \u2014 supply refreshes through the day.");
|
|
7524
7625
|
return;
|
|
7525
7626
|
}
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
const { readProfile: readProfile2, profileToFingerprint: profileToFingerprint2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
|
|
7529
|
-
const { match: match2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
7530
|
-
const profile = await readProfile2();
|
|
7531
|
-
if (profile.skillTags.length > 0) {
|
|
7532
|
-
const fp = profileToFingerprint2(profile);
|
|
7533
|
-
for (const r of match2(fp, bounties, bounties.length)) {
|
|
7534
|
-
ranked.set(r.job.id, { score: r.score, reason: r.reason, matchedTags: r.matchedTags });
|
|
7535
|
-
}
|
|
7536
|
-
}
|
|
7537
|
-
} catch {
|
|
7538
|
-
}
|
|
7539
|
-
const score = (j) => ranked.get(j.id)?.score ?? 0;
|
|
7540
|
-
const amt = (j) => j.bounty?.amountUSD ?? -1;
|
|
7541
|
-
const contested = (j) => (j.bounty?.competingOpenPRs ?? 0) > 0 ? 1 : 0;
|
|
7542
|
-
bounties.sort((a, b) => contested(a) - contested(b) || score(b) - score(a) || amt(b) - amt(a));
|
|
7627
|
+
if (result.status !== "ok") return;
|
|
7628
|
+
const { bounties, ranked, matchedCount } = result;
|
|
7543
7629
|
const shown = SHOW_ALL ? bounties : bounties.slice(0, LIMIT);
|
|
7544
|
-
const matchedCount = bounties.filter((j) => score(j) > 0).length;
|
|
7545
7630
|
console.log(
|
|
7546
7631
|
`
|
|
7547
7632
|
\u26A1 ${bounties.length} bount${bounties.length === 1 ? "y" : "ies"} you could knock out` + (matchedCount ? ` \u2014 ${matchedCount} matched to your profile` : "") + ` (local rank \u2014 no data sent)
|
|
@@ -7573,6 +7658,7 @@ Open this to claim/work the bounty (you go straight to the source \u2014 we neve
|
|
|
7573
7658
|
}
|
|
7574
7659
|
}
|
|
7575
7660
|
export {
|
|
7661
|
+
getBounties,
|
|
7576
7662
|
run
|
|
7577
7663
|
};
|
|
7578
7664
|
/*! Bundled license information:
|
|
@@ -462,6 +462,21 @@ var init_contribution_gate = __esm({
|
|
|
462
462
|
}
|
|
463
463
|
});
|
|
464
464
|
|
|
465
|
+
// ../../packages/core/src/credential/rigor.ts
|
|
466
|
+
var RIGOR, MAINTAINER_SET;
|
|
467
|
+
var init_rigor = __esm({
|
|
468
|
+
"../../packages/core/src/credential/rigor.ts"() {
|
|
469
|
+
"use strict";
|
|
470
|
+
RIGOR = {
|
|
471
|
+
/** `authorAssociation` values that count as a maintainer review. */
|
|
472
|
+
MAINTAINER_ASSOCIATIONS: ["OWNER", "MEMBER", "COLLABORATOR"]
|
|
473
|
+
};
|
|
474
|
+
MAINTAINER_SET = new Set(
|
|
475
|
+
RIGOR.MAINTAINER_ASSOCIATIONS.map((a) => a.toUpperCase())
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
|
|
465
480
|
// ../../packages/core/src/github.ts
|
|
466
481
|
var RESUME_DECAY_HALF_LIFE_MS;
|
|
467
482
|
var init_github = __esm({
|
|
@@ -469,6 +484,7 @@ var init_github = __esm({
|
|
|
469
484
|
"use strict";
|
|
470
485
|
init_vocabulary();
|
|
471
486
|
init_contribution_gate();
|
|
487
|
+
init_rigor();
|
|
472
488
|
RESUME_DECAY_HALF_LIFE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
473
489
|
}
|
|
474
490
|
});
|
|
@@ -3963,6 +3979,7 @@ var init_src = __esm({
|
|
|
3963
3979
|
init_job_status();
|
|
3964
3980
|
init_legible();
|
|
3965
3981
|
init_legible_trajectory();
|
|
3982
|
+
init_rigor();
|
|
3966
3983
|
init_short_token();
|
|
3967
3984
|
}
|
|
3968
3985
|
});
|
|
@@ -3975,9 +3992,9 @@ var init_keytar = __esm({
|
|
|
3975
3992
|
}
|
|
3976
3993
|
});
|
|
3977
3994
|
|
|
3978
|
-
// node-file:/Users
|
|
3995
|
+
// node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
|
|
3979
3996
|
var require_keytar = __commonJS({
|
|
3980
|
-
"node-file:/Users
|
|
3997
|
+
"node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
3981
3998
|
"use strict";
|
|
3982
3999
|
init_keytar();
|
|
3983
4000
|
try {
|
|
@@ -4439,14 +4456,62 @@ var init_config = __esm({
|
|
|
4439
4456
|
}
|
|
4440
4457
|
});
|
|
4441
4458
|
|
|
4459
|
+
// bin/tui-core.js
|
|
4460
|
+
function sanitizeLine(text) {
|
|
4461
|
+
return String(text).replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(ANSI_OTHER, "").replace(C0_C1_DEL, "");
|
|
4462
|
+
}
|
|
4463
|
+
var ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, PALETTE, COLOR_ROLES;
|
|
4464
|
+
var init_tui_core = __esm({
|
|
4465
|
+
"bin/tui-core.js"() {
|
|
4466
|
+
"use strict";
|
|
4467
|
+
ANSI_CSI = /\x1b\[[0-?]*[ -/]*[@-~]/g;
|
|
4468
|
+
ANSI_OSC = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
4469
|
+
ANSI_OTHER = /\x1b[@-_]/g;
|
|
4470
|
+
C0_C1_DEL = /[\x00-\x1f\x7f-\x9f]/g;
|
|
4471
|
+
PALETTE = {
|
|
4472
|
+
truecolor: {
|
|
4473
|
+
bg: "\x1B[48;2;13;17;23m",
|
|
4474
|
+
panel: "\x1B[48;2;22;27;34m",
|
|
4475
|
+
rule: "\x1B[38;2;48;54;61m",
|
|
4476
|
+
text: "\x1B[38;2;201;209;217m",
|
|
4477
|
+
muted: "\x1B[38;2;125;133;144m",
|
|
4478
|
+
accent: "\x1B[38;2;88;166;255m",
|
|
4479
|
+
"accent-bright": "\x1B[38;2;121;192;255m",
|
|
4480
|
+
green: "\x1B[38;2;63;185;80m",
|
|
4481
|
+
amber: "\x1B[38;2;210;153;34m"
|
|
4482
|
+
},
|
|
4483
|
+
256: {
|
|
4484
|
+
bg: "\x1B[48;5;233m",
|
|
4485
|
+
panel: "\x1B[48;5;235m",
|
|
4486
|
+
rule: "\x1B[38;5;240m",
|
|
4487
|
+
text: "\x1B[38;5;252m",
|
|
4488
|
+
muted: "\x1B[38;5;245m",
|
|
4489
|
+
accent: "\x1B[38;5;75m",
|
|
4490
|
+
"accent-bright": "\x1B[38;5;117m",
|
|
4491
|
+
green: "\x1B[38;5;71m",
|
|
4492
|
+
amber: "\x1B[38;5;178m"
|
|
4493
|
+
},
|
|
4494
|
+
16: {
|
|
4495
|
+
bg: "\x1B[40m",
|
|
4496
|
+
panel: "\x1B[100m",
|
|
4497
|
+
rule: "\x1B[90m",
|
|
4498
|
+
text: "\x1B[37m",
|
|
4499
|
+
muted: "\x1B[90m",
|
|
4500
|
+
accent: "\x1B[94m",
|
|
4501
|
+
"accent-bright": "\x1B[96m",
|
|
4502
|
+
green: "\x1B[92m",
|
|
4503
|
+
amber: "\x1B[93m"
|
|
4504
|
+
}
|
|
4505
|
+
};
|
|
4506
|
+
COLOR_ROLES = Object.keys(PALETTE.truecolor);
|
|
4507
|
+
}
|
|
4508
|
+
});
|
|
4509
|
+
|
|
4442
4510
|
// bin/jpi-chat.js
|
|
4443
4511
|
import { createInterface } from "readline";
|
|
4444
4512
|
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
4445
4513
|
import { homedir as homedir6 } from "os";
|
|
4446
4514
|
import { join as join7 } from "path";
|
|
4447
|
-
function sanitizeLine(text) {
|
|
4448
|
-
return String(text).replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(ANSI_OTHER, "").replace(C0_C1_DEL, "");
|
|
4449
|
-
}
|
|
4450
4515
|
function defaultPromptAck({ input = process.stdin, output = process.stdout } = {}) {
|
|
4451
4516
|
if (!input || input.isTTY !== true) return Promise.resolve(false);
|
|
4452
4517
|
const rl = createInterface({ input, output });
|
|
@@ -4565,19 +4630,16 @@ function formatPresence(presence, now = /* @__PURE__ */ new Date()) {
|
|
|
4565
4630
|
}
|
|
4566
4631
|
return "\u25D0 reachable";
|
|
4567
4632
|
}
|
|
4568
|
-
var CHAT_BASE2, GH_SESSION_COOKIE2,
|
|
4633
|
+
var CHAT_BASE2, GH_SESSION_COOKIE2, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, ACTIVE_WINDOW_MS;
|
|
4569
4634
|
var init_jpi_chat = __esm({
|
|
4570
4635
|
"bin/jpi-chat.js"() {
|
|
4571
4636
|
"use strict";
|
|
4572
4637
|
init_chat_client();
|
|
4573
4638
|
init_config();
|
|
4574
4639
|
init_web_session();
|
|
4640
|
+
init_tui_core();
|
|
4575
4641
|
CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
|
|
4576
4642
|
GH_SESSION_COOKIE2 = "__jpi_gh_session";
|
|
4577
|
-
ANSI_CSI = /\x1b\[[0-?]*[ -/]*[@-~]/g;
|
|
4578
|
-
ANSI_OSC = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
4579
|
-
ANSI_OTHER = /\x1b[@-_]/g;
|
|
4580
|
-
C0_C1_DEL = /[\x00-\x1f\x7f-\x9f]/g;
|
|
4581
4643
|
CHAT_DISCLOSURE = "Messages are end-to-end encrypted using keys stored only on your device. Our server cannot read message content. Since we distribute your contact's public key, verify your connection by comparing Safety Numbers to rule out a server-side substitution. We store metadata: who messaged whom, when, and message count. Content is purged after 90 days.";
|
|
4582
4644
|
CHAT_AT_REST = "Your private key is encrypted against casual access, not full machine compromise.";
|
|
4583
4645
|
CHAT_CODE_OF_CONDUCT = "Code of conduct: keep it professional \u2014 harassment, spam, or abuse gets you blocked and removed.";
|