terminalhire 0.42.15 → 0.42.17
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 +3 -1
- package/dist/bin/claim-push-bg.js +20 -11
- package/dist/bin/directory.js +7 -5
- package/dist/bin/founder-bounty-notify.js +2 -2
- package/dist/bin/founder-note-sync.js +2 -0
- package/dist/bin/founder-verdict-sync.js +4 -2
- package/dist/bin/jpi-bounties.js +89 -52
- package/dist/bin/jpi-chat-read.js +45 -18
- package/dist/bin/jpi-chat.js +86 -37
- package/dist/bin/jpi-claim.js +567 -305
- package/dist/bin/jpi-config.js +6 -6
- package/dist/bin/jpi-contribute.js +78 -41
- package/dist/bin/jpi-devs.js +25 -23
- package/dist/bin/jpi-dispatch-dev.js +53 -0
- package/dist/bin/jpi-dispatch.js +859 -496
- package/dist/bin/jpi-hub.js +66 -39
- package/dist/bin/jpi-inbox.js +85 -36
- package/dist/bin/jpi-init.js +24 -22
- package/dist/bin/jpi-intro.js +37 -18
- package/dist/bin/jpi-jobs.js +102 -49
- package/dist/bin/jpi-link.js +75 -16
- package/dist/bin/jpi-login.js +38 -31
- package/dist/bin/jpi-mcp-chat.js +47 -20
- package/dist/bin/jpi-mcp.js +586 -320
- package/dist/bin/jpi-post.js +8 -6
- package/dist/bin/jpi-project.js +14 -12
- package/dist/bin/jpi-refresh.js +178 -94
- package/dist/bin/jpi-run.js +78 -68
- package/dist/bin/jpi-spinner.js +30 -4
- package/dist/bin/jpi-statusline.js +28 -3
- package/dist/bin/jpi-sync.js +29 -20
- package/dist/bin/jpi-trajectory.js +46 -27
- package/dist/bin/jpi.js +42 -4
- package/dist/bin/peer-connect-prompt.js +4 -2
- package/dist/bin/pulse-prompt.js +24 -5
- package/dist/bin/recall-check.js +7 -5
- package/dist/bin/spinner-render.js +32 -4
- package/dist/bin/spinner.js +32 -4
- package/dist/src/api-base.js +16 -0
- package/dist/src/chat-client.js +26 -7
- package/dist/src/intro.js +37 -18
- package/dist/src/link.js +61 -11
- package/dist/src/trajectory.js +46 -27
- package/dist/src/web-session.js +40 -5
- package/package.json +4 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/api-base.ts
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
2
4
|
var PROD_API_BASE = "https://terminalhire.com";
|
|
3
5
|
var DEV_API_BASE = "https://dev.terminalhire.com";
|
|
4
6
|
var ApiBaseError = class extends Error {
|
|
@@ -103,7 +105,7 @@ function approvalsNudgeGate({ autoMarkerExists, tokenFileExists, awaitingApprova
|
|
|
103
105
|
function buildApprovalsNudge(awaitingApproval) {
|
|
104
106
|
if (!Number.isInteger(awaitingApproval) || awaitingApproval <= 0) return null;
|
|
105
107
|
const n = awaitingApproval;
|
|
106
|
-
return ` \u26A0 ${n} claim${n === 1 ? "" : "s"} awaiting
|
|
108
|
+
return ` \u26A0 ${n} claim${n === 1 ? "" : "s"} awaiting poster approval \u2014 terminalhire cannot check in the background until you enrol:
|
|
107
109
|
terminalhire claim --push --keep-updated (or check one now: terminalhire claim slice <id>)`;
|
|
108
110
|
}
|
|
109
111
|
async function syncApprovedClaims({
|
|
@@ -115,8 +115,8 @@ import {
|
|
|
115
115
|
statSync
|
|
116
116
|
} from "fs";
|
|
117
117
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
118
|
-
import { join as
|
|
119
|
-
import { homedir as
|
|
118
|
+
import { join as join5 } from "path";
|
|
119
|
+
import { homedir as homedir4 } from "os";
|
|
120
120
|
function sleepSync(ms) {
|
|
121
121
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
122
122
|
}
|
|
@@ -310,8 +310,8 @@ var init_claims = __esm({
|
|
|
310
310
|
"src/claims.ts"() {
|
|
311
311
|
"use strict";
|
|
312
312
|
init_state_dir();
|
|
313
|
-
TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR ||
|
|
314
|
-
CLAIMS_FILE =
|
|
313
|
+
TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR || join5(homedir4(), ".terminalhire");
|
|
314
|
+
CLAIMS_FILE = join5(TERMINALHIRE_DIR3, "claims.json");
|
|
315
315
|
LOCK_DIR = `${CLAIMS_FILE}.lock`;
|
|
316
316
|
LOCK_STALE_MS = Number(process.env.TERMINALHIRE_LOCK_STALE_MS) || 1e4;
|
|
317
317
|
LOCK_RETRY_MS = Number(process.env.TERMINALHIRE_LOCK_RETRY_MS) || 25;
|
|
@@ -369,8 +369,8 @@ var init_claims = __esm({
|
|
|
369
369
|
// bin/claim-push-bg.js
|
|
370
370
|
import { createHash } from "crypto";
|
|
371
371
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync5, rmSync as rmSync3 } from "fs";
|
|
372
|
-
import { join as
|
|
373
|
-
import { homedir as
|
|
372
|
+
import { join as join6 } from "path";
|
|
373
|
+
import { homedir as homedir5 } from "os";
|
|
374
374
|
|
|
375
375
|
// src/github-auth.ts
|
|
376
376
|
init_state_dir();
|
|
@@ -511,8 +511,11 @@ function decrypt(blob, key) {
|
|
|
511
511
|
init_state_dir();
|
|
512
512
|
|
|
513
513
|
// src/api-base.ts
|
|
514
|
+
import { homedir as homedir3 } from "os";
|
|
515
|
+
import { join as join4 } from "path";
|
|
514
516
|
var PROD_API_BASE = "https://terminalhire.com";
|
|
515
517
|
var DEV_API_BASE = "https://dev.terminalhire.com";
|
|
518
|
+
var DEV_STATE_DIR_NAME = ".terminalhire-dev";
|
|
516
519
|
var ApiBaseError = class extends Error {
|
|
517
520
|
constructor(message) {
|
|
518
521
|
super(message);
|
|
@@ -613,6 +616,7 @@ function isNonProdApiBase(base = resolveApiBaseOrProd()) {
|
|
|
613
616
|
}
|
|
614
617
|
function warnSharedCredentialsIfNonProd(base, stream = process.stderr) {
|
|
615
618
|
if (!isNonProdApiBase(base)) return;
|
|
619
|
+
if (usingSeparateStateDir()) return;
|
|
616
620
|
try {
|
|
617
621
|
stream.write(
|
|
618
622
|
"terminalhire: non-prod API base \u2014 using the same local session/push credentials as prod; do not mix environments casually.\n"
|
|
@@ -620,12 +624,17 @@ function warnSharedCredentialsIfNonProd(base, stream = process.stderr) {
|
|
|
620
624
|
} catch {
|
|
621
625
|
}
|
|
622
626
|
}
|
|
627
|
+
function usingSeparateStateDir(env = process.env) {
|
|
628
|
+
const dir = env["TERMINALHIRE_DIR"];
|
|
629
|
+
if (dir === void 0 || dir === "") return false;
|
|
630
|
+
return dir.endsWith(DEV_STATE_DIR_NAME);
|
|
631
|
+
}
|
|
623
632
|
|
|
624
633
|
// bin/claim-push-bg.js
|
|
625
|
-
var TERMINALHIRE_DIR4 = process.env.TERMINALHIRE_DIR ||
|
|
626
|
-
var CLAIM_PUSH_AUTO_MARKER =
|
|
627
|
-
var CLAIM_PUSH_TOKEN_FILE =
|
|
628
|
-
var CLAIM_PUSH_MANUAL_MARKER =
|
|
634
|
+
var TERMINALHIRE_DIR4 = process.env.TERMINALHIRE_DIR || join6(homedir5(), ".terminalhire");
|
|
635
|
+
var CLAIM_PUSH_AUTO_MARKER = join6(TERMINALHIRE_DIR4, "claim-push-auto.json");
|
|
636
|
+
var CLAIM_PUSH_TOKEN_FILE = join6(TERMINALHIRE_DIR4, "claim-push-token.enc");
|
|
637
|
+
var CLAIM_PUSH_MANUAL_MARKER = join6(TERMINALHIRE_DIR4, "claim-push.json");
|
|
629
638
|
var CLAIM_SYNC_BASE = resolveApiBase();
|
|
630
639
|
warnSharedCredentialsIfNonProd(CLAIM_SYNC_BASE);
|
|
631
640
|
var AUTO_CONSENT_VERSION = 3;
|
|
@@ -731,7 +740,7 @@ async function shouldNudgeUnpushed() {
|
|
|
731
740
|
return false;
|
|
732
741
|
}
|
|
733
742
|
}
|
|
734
|
-
var CLAIM_HEARTBEAT_FILE =
|
|
743
|
+
var CLAIM_HEARTBEAT_FILE = join6(TERMINALHIRE_DIR4, "claim-heartbeat.json");
|
|
735
744
|
var HEARTBEAT_MIN_INTERVAL_MS = 3e4;
|
|
736
745
|
var HEARTBEAT_MIN_CONSENT_VERSION = 3;
|
|
737
746
|
function readHeartbeatState() {
|
package/dist/bin/directory.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// bin/directory.js
|
|
4
4
|
import { readFileSync, writeFileSync, renameSync } from "fs";
|
|
5
|
-
import { join } from "path";
|
|
6
|
-
import { homedir } from "os";
|
|
5
|
+
import { join as join2 } from "path";
|
|
6
|
+
import { homedir as homedir2 } from "os";
|
|
7
7
|
|
|
8
8
|
// src/state-dir.ts
|
|
9
9
|
import { closeSync, constants, fchmodSync, fstatSync, mkdirSync, openSync } from "fs";
|
|
@@ -54,6 +54,8 @@ function ensureStateDir(dir) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// src/api-base.ts
|
|
57
|
+
import { homedir } from "os";
|
|
58
|
+
import { join } from "path";
|
|
57
59
|
var PROD_API_BASE = "https://terminalhire.com";
|
|
58
60
|
var DEV_API_BASE = "https://dev.terminalhire.com";
|
|
59
61
|
var ApiBaseError = class extends Error {
|
|
@@ -146,9 +148,9 @@ function normalizeOverride(raw) {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
// bin/directory.js
|
|
149
|
-
var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR ||
|
|
150
|
-
var DIRECTORY_CACHE_FILE =
|
|
151
|
-
var PROJECT_FILE =
|
|
151
|
+
var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR || join2(homedir2(), ".terminalhire");
|
|
152
|
+
var DIRECTORY_CACHE_FILE = join2(TERMINALHIRE_DIR, "directory-cache.json");
|
|
153
|
+
var PROJECT_FILE = join2(TERMINALHIRE_DIR, "project.json");
|
|
152
154
|
var INDEX_TTL_MS = 15 * 60 * 1e3;
|
|
153
155
|
var API_URL = resolveApiBase();
|
|
154
156
|
function readDirectoryCache() {
|
|
@@ -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, '\\"');
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/api-base.ts
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
2
4
|
var PROD_API_BASE = "https://terminalhire.com";
|
|
3
5
|
var DEV_API_BASE = "https://dev.terminalhire.com";
|
|
4
6
|
var ApiBaseError = class extends Error {
|
|
@@ -149,10 +151,10 @@ function buildVerdictNotice(t) {
|
|
|
149
151
|
if (!t || typeof t.to !== "string") return null;
|
|
150
152
|
const amount = typeof t.amountUSD === "number" && t.amountUSD > 0 ? `$${t.amountUSD}` : null;
|
|
151
153
|
if (t.verdict === "rejected") {
|
|
152
|
-
return ` \u2717
|
|
154
|
+
return ` \u2717 poster rejected${amount ? ` \u2014 ${amount}` : ""} \xB7 claim moved to ${t.to}`;
|
|
153
155
|
}
|
|
154
156
|
const paid = t.settled ? " \xB7 paid" : "";
|
|
155
|
-
return ` \u2713
|
|
157
|
+
return ` \u2713 poster accepted${amount ? ` \u2014 ${amount}` : ""}${paid} \xB7 claim moved to ${t.to}`;
|
|
156
158
|
}
|
|
157
159
|
async function syncFounderVerdicts({
|
|
158
160
|
claimsModule,
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -10562,17 +10562,17 @@ var init_founder_pin = __esm({
|
|
|
10562
10562
|
|
|
10563
10563
|
// src/test-race-barrier.ts
|
|
10564
10564
|
import { closeSync as closeSync2, constants as constants2, existsSync, lstatSync, openSync as openSync2 } from "fs";
|
|
10565
|
-
import { join as
|
|
10565
|
+
import { join as join4 } from "path";
|
|
10566
10566
|
function syncSleepMs(ms) {
|
|
10567
10567
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
10568
10568
|
}
|
|
10569
10569
|
function waitForTestRaceBarrier(phase) {
|
|
10570
10570
|
const root = process.env[ENV_VAR];
|
|
10571
10571
|
if (!root) return;
|
|
10572
|
-
const phaseDir =
|
|
10572
|
+
const phaseDir = join4(root, phase);
|
|
10573
10573
|
if (!existsSync(phaseDir)) return;
|
|
10574
|
-
const readyFile =
|
|
10575
|
-
const goFile =
|
|
10574
|
+
const readyFile = join4(phaseDir, `ready-${process.pid}`);
|
|
10575
|
+
const goFile = join4(phaseDir, "go");
|
|
10576
10576
|
const noFollow = constants2.O_NOFOLLOW ?? 0;
|
|
10577
10577
|
if (lstatSync(readyFile, { throwIfNoEntry: false })) {
|
|
10578
10578
|
throw new Error(
|
|
@@ -10612,8 +10612,8 @@ var init_test_race_barrier = __esm({
|
|
|
10612
10612
|
// src/shared-key.ts
|
|
10613
10613
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
10614
10614
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync2, linkSync, unlinkSync } from "fs";
|
|
10615
|
-
import { join as
|
|
10616
|
-
import { homedir as
|
|
10615
|
+
import { join as join5 } from "path";
|
|
10616
|
+
import { homedir as homedir3 } from "os";
|
|
10617
10617
|
function isValidKeyHex(value) {
|
|
10618
10618
|
return KEY_HEX_RE.test(value);
|
|
10619
10619
|
}
|
|
@@ -10667,8 +10667,8 @@ var init_shared_key = __esm({
|
|
|
10667
10667
|
"use strict";
|
|
10668
10668
|
init_state_dir();
|
|
10669
10669
|
init_test_race_barrier();
|
|
10670
|
-
TERMINALHIRE_DIR2 = process.env.TERMINALHIRE_DIR ||
|
|
10671
|
-
KEY_FILE =
|
|
10670
|
+
TERMINALHIRE_DIR2 = process.env.TERMINALHIRE_DIR || join5(homedir3(), ".terminalhire");
|
|
10671
|
+
KEY_FILE = join5(TERMINALHIRE_DIR2, "key");
|
|
10672
10672
|
KEY_BYTES = 32;
|
|
10673
10673
|
KEY_HEX_RE = new RegExp(`^[0-9a-f]{${KEY_BYTES * 2}}$`);
|
|
10674
10674
|
}
|
|
@@ -10677,7 +10677,7 @@ var init_shared_key = __esm({
|
|
|
10677
10677
|
// src/crypto-store.ts
|
|
10678
10678
|
import { createCipheriv, createDecipheriv, randomBytes as randomBytes4 } from "crypto";
|
|
10679
10679
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync3, renameSync as renameSync2, rmSync, readdirSync } from "fs";
|
|
10680
|
-
import { join as
|
|
10680
|
+
import { join as join6, dirname, basename } from "path";
|
|
10681
10681
|
import { createRequire } from "module";
|
|
10682
10682
|
function encrypt(plaintext, key) {
|
|
10683
10683
|
const iv = randomBytes4(IV_BYTES);
|
|
@@ -10732,7 +10732,7 @@ function makeWarnOnce() {
|
|
|
10732
10732
|
function atomicWriteFileSync(filePath, content) {
|
|
10733
10733
|
const dir = dirname(filePath);
|
|
10734
10734
|
ensureStateDirForSecret(dir);
|
|
10735
|
-
const tmp =
|
|
10735
|
+
const tmp = join6(
|
|
10736
10736
|
dir,
|
|
10737
10737
|
`.${basename(filePath)}.tmp-${process.pid}-${randomBytes4(6).toString("hex")}`
|
|
10738
10738
|
);
|
|
@@ -10750,7 +10750,7 @@ async function deleteKey() {
|
|
|
10750
10750
|
}
|
|
10751
10751
|
for (const name of encFiles) {
|
|
10752
10752
|
try {
|
|
10753
|
-
rmSync(
|
|
10753
|
+
rmSync(join6(stateDir, name));
|
|
10754
10754
|
} catch (e) {
|
|
10755
10755
|
const code = e.code;
|
|
10756
10756
|
if (code !== "ENOENT") {
|
|
@@ -10841,8 +10841,8 @@ __export(profile_exports, {
|
|
|
10841
10841
|
removeSavedJob: () => removeSavedJob,
|
|
10842
10842
|
writeProfile: () => writeProfile
|
|
10843
10843
|
});
|
|
10844
|
-
import { join as
|
|
10845
|
-
import { homedir as
|
|
10844
|
+
import { join as join7 } from "path";
|
|
10845
|
+
import { homedir as homedir4 } from "os";
|
|
10846
10846
|
function blankProfile() {
|
|
10847
10847
|
return {
|
|
10848
10848
|
version: 3,
|
|
@@ -10975,8 +10975,8 @@ var init_profile = __esm({
|
|
|
10975
10975
|
"use strict";
|
|
10976
10976
|
init_src();
|
|
10977
10977
|
init_crypto_store();
|
|
10978
|
-
TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR ||
|
|
10979
|
-
PROFILE_FILE =
|
|
10978
|
+
TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR || join7(homedir4(), ".terminalhire");
|
|
10979
|
+
PROFILE_FILE = join7(TERMINALHIRE_DIR3, "profile.enc");
|
|
10980
10980
|
profileStore = createEncryptedStore(PROFILE_FILE, {
|
|
10981
10981
|
blank: blankProfile,
|
|
10982
10982
|
keyPolicy: "keytar-first-file-fallback"
|
|
@@ -11028,8 +11028,8 @@ __export(repo_experience_exports, {
|
|
|
11028
11028
|
recordPolicySnapshot: () => recordPolicySnapshot,
|
|
11029
11029
|
writeTombstone: () => writeTombstone
|
|
11030
11030
|
});
|
|
11031
|
-
import { join as
|
|
11032
|
-
import { homedir as
|
|
11031
|
+
import { join as join8 } from "path";
|
|
11032
|
+
import { homedir as homedir5 } from "os";
|
|
11033
11033
|
function blankFile() {
|
|
11034
11034
|
return { version: 1, repos: {} };
|
|
11035
11035
|
}
|
|
@@ -11236,8 +11236,8 @@ var init_repo_experience = __esm({
|
|
|
11236
11236
|
"use strict";
|
|
11237
11237
|
init_crypto_store();
|
|
11238
11238
|
init_profile();
|
|
11239
|
-
TERMINALHIRE_DIR4 = process.env.TERMINALHIRE_DIR ||
|
|
11240
|
-
REPO_EXPERIENCE_FILE =
|
|
11239
|
+
TERMINALHIRE_DIR4 = process.env.TERMINALHIRE_DIR || join8(homedir5(), ".terminalhire");
|
|
11240
|
+
REPO_EXPERIENCE_FILE = join8(TERMINALHIRE_DIR4, "repo-experience.enc");
|
|
11241
11241
|
MAX_REPOS = 100;
|
|
11242
11242
|
MAX_CULTURE_SAMPLES = 12;
|
|
11243
11243
|
MAX_NOTES = 10;
|
|
@@ -11278,8 +11278,8 @@ import {
|
|
|
11278
11278
|
statSync
|
|
11279
11279
|
} from "fs";
|
|
11280
11280
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
11281
|
-
import { join as
|
|
11282
|
-
import { homedir as
|
|
11281
|
+
import { join as join9 } from "path";
|
|
11282
|
+
import { homedir as homedir6 } from "os";
|
|
11283
11283
|
function sleepSync(ms) {
|
|
11284
11284
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
11285
11285
|
}
|
|
@@ -11473,8 +11473,8 @@ var init_claims = __esm({
|
|
|
11473
11473
|
"src/claims.ts"() {
|
|
11474
11474
|
"use strict";
|
|
11475
11475
|
init_state_dir();
|
|
11476
|
-
TERMINALHIRE_DIR5 = process.env.TERMINALHIRE_DIR ||
|
|
11477
|
-
CLAIMS_FILE =
|
|
11476
|
+
TERMINALHIRE_DIR5 = process.env.TERMINALHIRE_DIR || join9(homedir6(), ".terminalhire");
|
|
11477
|
+
CLAIMS_FILE = join9(TERMINALHIRE_DIR5, "claims.json");
|
|
11478
11478
|
LOCK_DIR = `${CLAIMS_FILE}.lock`;
|
|
11479
11479
|
LOCK_STALE_MS = Number(process.env.TERMINALHIRE_LOCK_STALE_MS) || 1e4;
|
|
11480
11480
|
LOCK_RETRY_MS = Number(process.env.TERMINALHIRE_LOCK_RETRY_MS) || 25;
|
|
@@ -11547,8 +11547,8 @@ __export(config_exports, {
|
|
|
11547
11547
|
writeConfig: () => writeConfig
|
|
11548
11548
|
});
|
|
11549
11549
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync5 } from "fs";
|
|
11550
|
-
import { join as
|
|
11551
|
-
import { homedir as
|
|
11550
|
+
import { join as join10 } from "path";
|
|
11551
|
+
import { homedir as homedir7 } from "os";
|
|
11552
11552
|
function readConfig() {
|
|
11553
11553
|
try {
|
|
11554
11554
|
if (!existsSync5(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
|
|
@@ -11630,8 +11630,8 @@ var init_config = __esm({
|
|
|
11630
11630
|
"src/config.ts"() {
|
|
11631
11631
|
"use strict";
|
|
11632
11632
|
init_state_dir();
|
|
11633
|
-
TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR ||
|
|
11634
|
-
CONFIG_FILE =
|
|
11633
|
+
TERMINALHIRE_DIR6 = process.env.TERMINALHIRE_DIR || join10(homedir7(), ".terminalhire");
|
|
11634
|
+
CONFIG_FILE = join10(TERMINALHIRE_DIR6, "config.json");
|
|
11635
11635
|
DEFAULT_CONFIG = {
|
|
11636
11636
|
nudge: "session",
|
|
11637
11637
|
peerConnect: false,
|
|
@@ -11749,38 +11749,73 @@ __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";
|
|
11756
|
-
import { homedir as
|
|
11757
|
-
import { join as
|
|
11759
|
+
import { homedir as homedir8 } from "os";
|
|
11760
|
+
import { join as join11 } from "path";
|
|
11758
11761
|
function terminalhireDir() {
|
|
11759
|
-
return process.env.TERMINALHIRE_DIR ||
|
|
11762
|
+
return process.env.TERMINALHIRE_DIR || join11(homedir8(), ".terminalhire");
|
|
11760
11763
|
}
|
|
11761
11764
|
function webSessionFilePath() {
|
|
11762
|
-
return
|
|
11765
|
+
return join11(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 {
|
|
@@ -11815,13 +11850,13 @@ __export(jpi_decline_exports, {
|
|
|
11815
11850
|
});
|
|
11816
11851
|
import { createInterface } from "readline";
|
|
11817
11852
|
import { existsSync as existsSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync7, rmSync as rmSync4 } from "fs";
|
|
11818
|
-
import { homedir as
|
|
11819
|
-
import { join as
|
|
11853
|
+
import { homedir as homedir9 } from "os";
|
|
11854
|
+
import { join as join12 } from "path";
|
|
11820
11855
|
function terminalhireDir2() {
|
|
11821
|
-
return process.env.TERMINALHIRE_DIR ||
|
|
11856
|
+
return process.env.TERMINALHIRE_DIR || join12(homedir9(), ".terminalhire");
|
|
11822
11857
|
}
|
|
11823
11858
|
function consentFilePath() {
|
|
11824
|
-
return
|
|
11859
|
+
return join12(terminalhireDir2(), "decline-consent");
|
|
11825
11860
|
}
|
|
11826
11861
|
function postingIdFromJobId(jobId) {
|
|
11827
11862
|
const id = String(jobId ?? "");
|
|
@@ -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);
|
|
@@ -11959,8 +11994,8 @@ var init_jpi_decline = __esm({
|
|
|
11959
11994
|
// bin/jpi-bounties.js
|
|
11960
11995
|
init_src();
|
|
11961
11996
|
import { readFileSync as readFileSync9 } from "fs";
|
|
11962
|
-
import { join as
|
|
11963
|
-
import { homedir as
|
|
11997
|
+
import { join as join13 } from "path";
|
|
11998
|
+
import { homedir as homedir10 } from "os";
|
|
11964
11999
|
import { createInterface as createInterface2 } from "readline";
|
|
11965
12000
|
|
|
11966
12001
|
// ../../packages/core/src/payout-split.ts
|
|
@@ -12177,6 +12212,8 @@ function linkTitle(title, url) {
|
|
|
12177
12212
|
}
|
|
12178
12213
|
|
|
12179
12214
|
// src/api-base.ts
|
|
12215
|
+
import { homedir as homedir2 } from "os";
|
|
12216
|
+
import { join as join3 } from "path";
|
|
12180
12217
|
var PROD_API_BASE = "https://terminalhire.com";
|
|
12181
12218
|
var DEV_API_BASE = "https://dev.terminalhire.com";
|
|
12182
12219
|
var ApiBaseError = class extends Error {
|
|
@@ -12270,8 +12307,8 @@ function normalizeOverride(raw) {
|
|
|
12270
12307
|
|
|
12271
12308
|
// bin/jpi-bounties.js
|
|
12272
12309
|
init_founder_pin();
|
|
12273
|
-
var TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR ||
|
|
12274
|
-
var INDEX_CACHE_FILE2 =
|
|
12310
|
+
var TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR || join13(homedir10(), ".terminalhire");
|
|
12311
|
+
var INDEX_CACHE_FILE2 = join13(TERMINALHIRE_DIR7, "index-cache.json");
|
|
12275
12312
|
var INDEX_TTL_MS = 15 * 60 * 1e3;
|
|
12276
12313
|
var API_URL2 = resolveApiBase();
|
|
12277
12314
|
var RANK_MODE = process.env["TERMINALHIRE_BOUNTY_RANK"] ?? "winnability";
|
|
@@ -12335,7 +12372,7 @@ function founderClaimBlurb(amountUSD, paidWork) {
|
|
|
12335
12372
|
if (typeof amountUSD === "number" && Number.isFinite(amountUSD) && amountUSD > 0) {
|
|
12336
12373
|
share = ` You'd receive ${formatCents(developerShareCents(Math.round(amountUSD * 100)))} of the ${formatCents(Math.round(amountUSD * 100))} posted; terminalhire keeps 10%.`;
|
|
12337
12374
|
}
|
|
12338
|
-
return `Claim it from here \u2014 the
|
|
12375
|
+
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
12376
|
}
|
|
12340
12377
|
function founderClaimBlock(job) {
|
|
12341
12378
|
const ref = opportunityShortToken(job.id);
|
|
@@ -12383,7 +12420,7 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
|
12383
12420
|
}
|
|
12384
12421
|
if (b.bountySource === "founder" && b.specProvenance) {
|
|
12385
12422
|
console.log(
|
|
12386
|
-
` Spec: ${b.specProvenance === "agent_drafted_human_confirmed" ? "agent drafted \xB7
|
|
12423
|
+
` Spec: ${b.specProvenance === "agent_drafted_human_confirmed" ? "agent drafted \xB7 poster confirmed" : "poster authored"}`
|
|
12387
12424
|
);
|
|
12388
12425
|
}
|
|
12389
12426
|
if (matchedTags && matchedTags.length)
|
|
@@ -12597,7 +12634,7 @@ Enter a number to open a bounty's claim page, d<number> to say why you're passin
|
|
|
12597
12634
|
const postingId = postingIdFromJobId2(shown[dIdx]?.id);
|
|
12598
12635
|
if (!postingId) {
|
|
12599
12636
|
console.log(
|
|
12600
|
-
"\nThat one is scraped from a public tracker \u2014 there is no
|
|
12637
|
+
"\nThat one is scraped from a public tracker \u2014 there is no poster here to tell."
|
|
12601
12638
|
);
|
|
12602
12639
|
return;
|
|
12603
12640
|
}
|