terminalhire 0.42.14 → 0.42.16
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/approved-claims-sync.js +1 -1
- package/dist/bin/founder-bounty-notify.js +2 -2
- package/dist/bin/founder-verdict-sync.js +2 -2
- package/dist/bin/jpi-bounties.js +48 -13
- package/dist/bin/jpi-chat-read.js +20 -3
- package/dist/bin/jpi-chat.js +20 -3
- package/dist/bin/jpi-claim.js +647 -322
- package/dist/bin/jpi-config.js +6 -6
- package/dist/bin/jpi-contribute.js +40 -5
- package/dist/bin/jpi-dispatch.js +583 -209
- package/dist/bin/jpi-hub.js +20 -3
- package/dist/bin/jpi-inbox.js +20 -3
- package/dist/bin/jpi-intro.js +20 -3
- package/dist/bin/jpi-jobs.js +36 -7
- package/dist/bin/jpi-link.js +69 -12
- package/dist/bin/jpi-login.js +8 -3
- package/dist/bin/jpi-mcp-chat.js +20 -3
- package/dist/bin/jpi-mcp.js +643 -314
- package/dist/bin/jpi-refresh.js +51 -11
- package/dist/bin/jpi-run.js +14 -3
- package/dist/bin/jpi-spinner.js +15 -4
- package/dist/bin/jpi-statusline.js +14 -1
- package/dist/bin/jpi-trajectory.js +20 -3
- package/dist/bin/peer-connect-prompt.js +2 -2
- package/dist/bin/pulse-prompt.js +20 -3
- package/dist/bin/spinner-render.js +16 -4
- package/dist/bin/spinner.js +16 -4
- package/dist/src/chat-client.js +20 -3
- package/dist/src/intro.js +20 -3
- package/dist/src/link.js +59 -11
- package/dist/src/trajectory.js +20 -3
- package/dist/src/web-session.js +40 -5
- package/package.json +1 -1
|
@@ -103,7 +103,7 @@ function approvalsNudgeGate({ autoMarkerExists, tokenFileExists, awaitingApprova
|
|
|
103
103
|
function buildApprovalsNudge(awaitingApproval) {
|
|
104
104
|
if (!Number.isInteger(awaitingApproval) || awaitingApproval <= 0) return null;
|
|
105
105
|
const n = awaitingApproval;
|
|
106
|
-
return ` \u26A0 ${n} claim${n === 1 ? "" : "s"} awaiting
|
|
106
|
+
return ` \u26A0 ${n} claim${n === 1 ? "" : "s"} awaiting poster approval \u2014 terminalhire cannot check in the background until you enrol:
|
|
107
107
|
terminalhire claim --push --keep-updated (or check one now: terminalhire claim slice <id>)`;
|
|
108
108
|
}
|
|
109
109
|
async function syncApprovedClaims({
|
|
@@ -39,9 +39,9 @@ function formatFounderBountyNotifyBody(index, fireIds) {
|
|
|
39
39
|
const j = byId.get(fireIds[0]);
|
|
40
40
|
const amount = j && j.bounty && typeof j.bounty.amountUSD === "number" ? j.bounty.amountUSD : null;
|
|
41
41
|
const price = typeof amount === "number" && Number.isFinite(amount) && amount > 0 ? `$${Math.round(amount)} ` : "";
|
|
42
|
-
return `${price}
|
|
42
|
+
return `${price}posted bounty available \u2014 run: terminalhire bounties`;
|
|
43
43
|
}
|
|
44
|
-
return `${fireIds.length}
|
|
44
|
+
return `${fireIds.length} posted bounties available \u2014 run: terminalhire bounties`;
|
|
45
45
|
}
|
|
46
46
|
function escapeAppleScriptString(s) {
|
|
47
47
|
return String(s).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -149,10 +149,10 @@ function buildVerdictNotice(t) {
|
|
|
149
149
|
if (!t || typeof t.to !== "string") return null;
|
|
150
150
|
const amount = typeof t.amountUSD === "number" && t.amountUSD > 0 ? `$${t.amountUSD}` : null;
|
|
151
151
|
if (t.verdict === "rejected") {
|
|
152
|
-
return ` \u2717
|
|
152
|
+
return ` \u2717 poster rejected${amount ? ` \u2014 ${amount}` : ""} \xB7 claim moved to ${t.to}`;
|
|
153
153
|
}
|
|
154
154
|
const paid = t.settled ? " \xB7 paid" : "";
|
|
155
|
-
return ` \u2713
|
|
155
|
+
return ` \u2713 poster accepted${amount ? ` \u2014 ${amount}` : ""}${paid} \xB7 claim moved to ${t.to}`;
|
|
156
156
|
}
|
|
157
157
|
async function syncFounderVerdicts({
|
|
158
158
|
claimsModule,
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -11749,7 +11749,10 @@ __export(web_session_exports, {
|
|
|
11749
11749
|
clearWebSessionFile: () => clearWebSessionFile,
|
|
11750
11750
|
readWebSessionCookie: () => readWebSessionCookie,
|
|
11751
11751
|
readWebSessionFile: () => readWebSessionFile,
|
|
11752
|
+
readWebSessionRecord: () => readWebSessionRecord,
|
|
11753
|
+
webSessionCookieForHost: () => webSessionCookieForHost,
|
|
11752
11754
|
webSessionFilePath: () => webSessionFilePath,
|
|
11755
|
+
webSessionForHost: () => webSessionForHost,
|
|
11753
11756
|
writeWebSessionFile: () => writeWebSessionFile
|
|
11754
11757
|
});
|
|
11755
11758
|
import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
@@ -11761,26 +11764,58 @@ function terminalhireDir() {
|
|
|
11761
11764
|
function webSessionFilePath() {
|
|
11762
11765
|
return join10(terminalhireDir(), "web-session");
|
|
11763
11766
|
}
|
|
11764
|
-
function
|
|
11767
|
+
function parseWebSessionFile(raw) {
|
|
11768
|
+
const trimmed = raw.trim();
|
|
11769
|
+
if (trimmed.length === 0) return null;
|
|
11770
|
+
if (!trimmed.startsWith("{")) return { token: trimmed, host: null };
|
|
11771
|
+
try {
|
|
11772
|
+
const parsed = JSON.parse(trimmed);
|
|
11773
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
11774
|
+
const rec = parsed;
|
|
11775
|
+
if (typeof rec.token !== "string" || rec.token.length === 0) return null;
|
|
11776
|
+
const host = typeof rec.host === "string" ? rec.host.trim() : "";
|
|
11777
|
+
return { token: rec.token, host: host === "" ? null : host };
|
|
11778
|
+
} catch {
|
|
11779
|
+
return null;
|
|
11780
|
+
}
|
|
11781
|
+
}
|
|
11782
|
+
function readWebSessionRecord() {
|
|
11765
11783
|
try {
|
|
11766
11784
|
const path = webSessionFilePath();
|
|
11767
11785
|
if (!existsSync6(path)) return null;
|
|
11768
|
-
|
|
11769
|
-
return v.length > 0 ? v : null;
|
|
11786
|
+
return parseWebSessionFile(readFileSync7(path, "utf8"));
|
|
11770
11787
|
} catch {
|
|
11771
11788
|
return null;
|
|
11772
11789
|
}
|
|
11773
11790
|
}
|
|
11791
|
+
function readWebSessionFile() {
|
|
11792
|
+
return readWebSessionRecord()?.token ?? null;
|
|
11793
|
+
}
|
|
11794
|
+
function webSessionForHost(apiBase) {
|
|
11795
|
+
const record = readWebSessionRecord();
|
|
11796
|
+
if (!record) return { cookie: null, mismatch: null };
|
|
11797
|
+
if (record.host !== null && record.host !== apiBase) {
|
|
11798
|
+
return { cookie: null, mismatch: { linkedHost: record.host, currentHost: apiBase } };
|
|
11799
|
+
}
|
|
11800
|
+
return { cookie: record.token, mismatch: null };
|
|
11801
|
+
}
|
|
11802
|
+
function webSessionCookieForHost(apiBase) {
|
|
11803
|
+
const fromFile = webSessionForHost(apiBase);
|
|
11804
|
+
if (fromFile.cookie || fromFile.mismatch) return fromFile;
|
|
11805
|
+
const env = process.env["TERMINALHIRE_WEB_SESSION"];
|
|
11806
|
+
return { cookie: typeof env === "string" && env.length > 0 ? env : null, mismatch: null };
|
|
11807
|
+
}
|
|
11774
11808
|
function readWebSessionCookie() {
|
|
11775
11809
|
const fromFile = readWebSessionFile();
|
|
11776
11810
|
if (fromFile) return fromFile;
|
|
11777
11811
|
const env = process.env["TERMINALHIRE_WEB_SESSION"];
|
|
11778
11812
|
return typeof env === "string" && env.length > 0 ? env : null;
|
|
11779
11813
|
}
|
|
11780
|
-
function writeWebSessionFile(token) {
|
|
11814
|
+
function writeWebSessionFile(token, host) {
|
|
11781
11815
|
ensureStateDirForSecret(terminalhireDir());
|
|
11782
11816
|
const path = webSessionFilePath();
|
|
11783
|
-
|
|
11817
|
+
const body = typeof host === "string" && host.length > 0 ? JSON.stringify({ v: 1, host, token }) : token;
|
|
11818
|
+
writeFileSync6(path, body, { mode: 384, encoding: "utf8" });
|
|
11784
11819
|
try {
|
|
11785
11820
|
chmodSync(path, 384);
|
|
11786
11821
|
} catch {
|
|
@@ -11839,12 +11874,12 @@ function declineBody(bountyId, reason) {
|
|
|
11839
11874
|
function consentNotice(bountyId, reason) {
|
|
11840
11875
|
return [
|
|
11841
11876
|
"",
|
|
11842
|
-
"This is the first thing you have sent a
|
|
11877
|
+
"This is the first thing you have sent a poster from this machine, so:",
|
|
11843
11878
|
"",
|
|
11844
11879
|
" Sending this posts EXACTLY this, and nothing else:",
|
|
11845
11880
|
` ${JSON.stringify(declineBody(bountyId, reason))}`,
|
|
11846
11881
|
"",
|
|
11847
|
-
" The
|
|
11882
|
+
" The poster sees a COUNT, never your name \u2014 answers are pooled across",
|
|
11848
11883
|
" developers, and the breakdown stays hidden until enough people have",
|
|
11849
11884
|
" answered that no single answer points at one person.",
|
|
11850
11885
|
"",
|
|
@@ -11906,7 +11941,7 @@ async function sendDecline(bountyId, reason) {
|
|
|
11906
11941
|
const { readWebSessionCookie: readWebSessionCookie2 } = await Promise.resolve().then(() => (init_web_session(), web_session_exports));
|
|
11907
11942
|
const cookie = readWebSessionCookie2();
|
|
11908
11943
|
if (!cookie) {
|
|
11909
|
-
console.log("\nRun `terminalhire link` first \u2014 a
|
|
11944
|
+
console.log("\nRun `terminalhire link` first \u2014 a poster needs to know the answer is real.");
|
|
11910
11945
|
return false;
|
|
11911
11946
|
}
|
|
11912
11947
|
if (!await ensureDeclineConsent(bountyId, reason)) return false;
|
|
@@ -11925,7 +11960,7 @@ async function sendDecline(bountyId, reason) {
|
|
|
11925
11960
|
Could not send that (${res.status}). Nothing else was sent.`);
|
|
11926
11961
|
return false;
|
|
11927
11962
|
}
|
|
11928
|
-
console.log("\nSent \u2014 thanks. The
|
|
11963
|
+
console.log("\nSent \u2014 thanks. The poster sees a count, never your name.");
|
|
11929
11964
|
return true;
|
|
11930
11965
|
} catch {
|
|
11931
11966
|
console.log("\nCould not reach terminalhire. Nothing else was sent.");
|
|
@@ -11933,7 +11968,7 @@ Could not send that (${res.status}). Nothing else was sent.`);
|
|
|
11933
11968
|
}
|
|
11934
11969
|
}
|
|
11935
11970
|
async function runDeclinePrompt(bountyId, { ask = prompt } = {}) {
|
|
11936
|
-
console.log("\nWhy are you passing? The
|
|
11971
|
+
console.log("\nWhy are you passing? The poster sees a count, never your name.");
|
|
11937
11972
|
for (const c of DECLINE_CHOICES) console.log(` ${c.key}. ${c.label}`);
|
|
11938
11973
|
const pick = await ask("\nEnter a number, or press Enter to skip: ");
|
|
11939
11974
|
const reason = reasonForKey(pick);
|
|
@@ -12335,7 +12370,7 @@ function founderClaimBlurb(amountUSD, paidWork) {
|
|
|
12335
12370
|
if (typeof amountUSD === "number" && Number.isFinite(amountUSD) && amountUSD > 0) {
|
|
12336
12371
|
share = ` You'd receive ${formatCents(developerShareCents(Math.round(amountUSD * 100)))} of the ${formatCents(Math.round(amountUSD * 100))} posted; terminalhire keeps 10%.`;
|
|
12337
12372
|
}
|
|
12338
|
-
return `Claim it from here \u2014 the
|
|
12373
|
+
return `Claim it from here \u2014 the poster pays through terminalhire rather than off-platform, and their acceptance is what triggers your payout.${share}`;
|
|
12339
12374
|
}
|
|
12340
12375
|
function founderClaimBlock(job) {
|
|
12341
12376
|
const ref = opportunityShortToken(job.id);
|
|
@@ -12383,7 +12418,7 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
|
12383
12418
|
}
|
|
12384
12419
|
if (b.bountySource === "founder" && b.specProvenance) {
|
|
12385
12420
|
console.log(
|
|
12386
|
-
` Spec: ${b.specProvenance === "agent_drafted_human_confirmed" ? "agent drafted \xB7
|
|
12421
|
+
` Spec: ${b.specProvenance === "agent_drafted_human_confirmed" ? "agent drafted \xB7 poster confirmed" : "poster authored"}`
|
|
12387
12422
|
);
|
|
12388
12423
|
}
|
|
12389
12424
|
if (matchedTags && matchedTags.length)
|
|
@@ -12597,7 +12632,7 @@ Enter a number to open a bounty's claim page, d<number> to say why you're passin
|
|
|
12597
12632
|
const postingId = postingIdFromJobId2(shown[dIdx]?.id);
|
|
12598
12633
|
if (!postingId) {
|
|
12599
12634
|
console.log(
|
|
12600
|
-
"\nThat one is scraped from a public tracker \u2014 there is no
|
|
12635
|
+
"\nThat one is scraped from a public tracker \u2014 there is no poster here to tell."
|
|
12601
12636
|
);
|
|
12602
12637
|
return;
|
|
12603
12638
|
}
|
|
@@ -4590,16 +4590,33 @@ function terminalhireDir() {
|
|
|
4590
4590
|
function webSessionFilePath() {
|
|
4591
4591
|
return join6(terminalhireDir(), "web-session");
|
|
4592
4592
|
}
|
|
4593
|
-
function
|
|
4593
|
+
function parseWebSessionFile(raw) {
|
|
4594
|
+
const trimmed = raw.trim();
|
|
4595
|
+
if (trimmed.length === 0) return null;
|
|
4596
|
+
if (!trimmed.startsWith("{")) return { token: trimmed, host: null };
|
|
4597
|
+
try {
|
|
4598
|
+
const parsed = JSON.parse(trimmed);
|
|
4599
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
4600
|
+
const rec = parsed;
|
|
4601
|
+
if (typeof rec.token !== "string" || rec.token.length === 0) return null;
|
|
4602
|
+
const host = typeof rec.host === "string" ? rec.host.trim() : "";
|
|
4603
|
+
return { token: rec.token, host: host === "" ? null : host };
|
|
4604
|
+
} catch {
|
|
4605
|
+
return null;
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
function readWebSessionRecord() {
|
|
4594
4609
|
try {
|
|
4595
4610
|
const path = webSessionFilePath();
|
|
4596
4611
|
if (!existsSync5(path)) return null;
|
|
4597
|
-
|
|
4598
|
-
return v.length > 0 ? v : null;
|
|
4612
|
+
return parseWebSessionFile(readFileSync5(path, "utf8"));
|
|
4599
4613
|
} catch {
|
|
4600
4614
|
return null;
|
|
4601
4615
|
}
|
|
4602
4616
|
}
|
|
4617
|
+
function readWebSessionFile() {
|
|
4618
|
+
return readWebSessionRecord()?.token ?? null;
|
|
4619
|
+
}
|
|
4603
4620
|
function readWebSessionCookie() {
|
|
4604
4621
|
const fromFile = readWebSessionFile();
|
|
4605
4622
|
if (fromFile) return fromFile;
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -4619,16 +4619,33 @@ function terminalhireDir() {
|
|
|
4619
4619
|
function webSessionFilePath() {
|
|
4620
4620
|
return join6(terminalhireDir(), "web-session");
|
|
4621
4621
|
}
|
|
4622
|
-
function
|
|
4622
|
+
function parseWebSessionFile(raw) {
|
|
4623
|
+
const trimmed = raw.trim();
|
|
4624
|
+
if (trimmed.length === 0) return null;
|
|
4625
|
+
if (!trimmed.startsWith("{")) return { token: trimmed, host: null };
|
|
4626
|
+
try {
|
|
4627
|
+
const parsed = JSON.parse(trimmed);
|
|
4628
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
4629
|
+
const rec = parsed;
|
|
4630
|
+
if (typeof rec.token !== "string" || rec.token.length === 0) return null;
|
|
4631
|
+
const host = typeof rec.host === "string" ? rec.host.trim() : "";
|
|
4632
|
+
return { token: rec.token, host: host === "" ? null : host };
|
|
4633
|
+
} catch {
|
|
4634
|
+
return null;
|
|
4635
|
+
}
|
|
4636
|
+
}
|
|
4637
|
+
function readWebSessionRecord() {
|
|
4623
4638
|
try {
|
|
4624
4639
|
const path = webSessionFilePath();
|
|
4625
4640
|
if (!existsSync5(path)) return null;
|
|
4626
|
-
|
|
4627
|
-
return v.length > 0 ? v : null;
|
|
4641
|
+
return parseWebSessionFile(readFileSync5(path, "utf8"));
|
|
4628
4642
|
} catch {
|
|
4629
4643
|
return null;
|
|
4630
4644
|
}
|
|
4631
4645
|
}
|
|
4646
|
+
function readWebSessionFile() {
|
|
4647
|
+
return readWebSessionRecord()?.token ?? null;
|
|
4648
|
+
}
|
|
4632
4649
|
function readWebSessionCookie() {
|
|
4633
4650
|
const fromFile = readWebSessionFile();
|
|
4634
4651
|
if (fromFile) return fromFile;
|