terminalhire 0.7.0 → 0.8.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/jpi-bounties.js +11 -0
- package/dist/bin/jpi-config.js +39 -6
- package/dist/bin/jpi-devs.js +57 -41
- package/dist/bin/jpi-dispatch.js +372 -202
- package/dist/bin/jpi-intro.js +8 -0
- package/dist/bin/jpi-jobs.js +11 -0
- package/dist/bin/jpi-learn.js +8 -0
- package/dist/bin/jpi-login.js +106 -4
- package/dist/bin/jpi-profile.js +8 -0
- package/dist/bin/jpi-project.js +11 -0
- package/dist/bin/jpi-refresh.js +604 -447
- package/dist/bin/jpi-save.js +8 -0
- package/dist/bin/jpi-spinner.js +10 -2
- package/dist/bin/jpi-sync.js +8 -0
- package/dist/bin/jpi-trajectory.js +8 -0
- package/dist/bin/peer-connect-prompt.js +75 -0
- package/dist/bin/spinner.js +11 -2
- package/dist/src/config.js +7 -1
- package/dist/src/intro.js +8 -0
- package/dist/src/trajectory.js +8 -0
- package/package.json +1 -1
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -3047,6 +3047,15 @@ var init_intro = __esm({
|
|
|
3047
3047
|
}
|
|
3048
3048
|
});
|
|
3049
3049
|
|
|
3050
|
+
// ../../packages/core/src/directoryThreshold.ts
|
|
3051
|
+
var STRONG_MATCH_THRESHOLD;
|
|
3052
|
+
var init_directoryThreshold = __esm({
|
|
3053
|
+
"../../packages/core/src/directoryThreshold.ts"() {
|
|
3054
|
+
"use strict";
|
|
3055
|
+
STRONG_MATCH_THRESHOLD = 0.58;
|
|
3056
|
+
}
|
|
3057
|
+
});
|
|
3058
|
+
|
|
3050
3059
|
// ../../packages/core/src/index.ts
|
|
3051
3060
|
var src_exports = {};
|
|
3052
3061
|
__export(src_exports, {
|
|
@@ -3066,6 +3075,7 @@ __export(src_exports, {
|
|
|
3066
3075
|
INTRO_ALLOWED_FIELDS: () => INTRO_ALLOWED_FIELDS,
|
|
3067
3076
|
INTRO_PENDING_TTL_MS: () => INTRO_PENDING_TTL_MS,
|
|
3068
3077
|
LEVER_SLUGS_BY_TIER: () => LEVER_SLUGS_BY_TIER,
|
|
3078
|
+
STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
|
|
3069
3079
|
SYNONYMS: () => SYNONYMS,
|
|
3070
3080
|
VOCABULARY: () => VOCABULARY,
|
|
3071
3081
|
VOCAB_NODES: () => VOCAB_NODES,
|
|
@@ -3134,6 +3144,7 @@ var init_src = __esm({
|
|
|
3134
3144
|
init_partners();
|
|
3135
3145
|
init_github();
|
|
3136
3146
|
init_intro();
|
|
3147
|
+
init_directoryThreshold();
|
|
3137
3148
|
}
|
|
3138
3149
|
});
|
|
3139
3150
|
|
|
@@ -3377,6 +3388,95 @@ var init_profile = __esm({
|
|
|
3377
3388
|
}
|
|
3378
3389
|
});
|
|
3379
3390
|
|
|
3391
|
+
// src/config.ts
|
|
3392
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
|
|
3393
|
+
import { join as join4 } from "path";
|
|
3394
|
+
import { homedir as homedir3 } from "os";
|
|
3395
|
+
function readConfig() {
|
|
3396
|
+
try {
|
|
3397
|
+
if (!existsSync3(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
|
|
3398
|
+
const raw = readFileSync4(CONFIG_FILE, "utf8");
|
|
3399
|
+
const parsed = JSON.parse(raw);
|
|
3400
|
+
return { ...DEFAULT_CONFIG, ...parsed };
|
|
3401
|
+
} catch {
|
|
3402
|
+
return { ...DEFAULT_CONFIG };
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
function writeConfig(config) {
|
|
3406
|
+
mkdirSync3(TERMINALHIRE_DIR3, { recursive: true });
|
|
3407
|
+
const current = readConfig();
|
|
3408
|
+
const merged = { ...current, ...config };
|
|
3409
|
+
writeFileSync3(CONFIG_FILE, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
3410
|
+
}
|
|
3411
|
+
function isPeerConnectEnabled() {
|
|
3412
|
+
return readConfig().peerConnect === true;
|
|
3413
|
+
}
|
|
3414
|
+
var TERMINALHIRE_DIR3, CONFIG_FILE, DEFAULT_CONFIG;
|
|
3415
|
+
var init_config = __esm({
|
|
3416
|
+
"src/config.ts"() {
|
|
3417
|
+
"use strict";
|
|
3418
|
+
TERMINALHIRE_DIR3 = join4(homedir3(), ".terminalhire");
|
|
3419
|
+
CONFIG_FILE = join4(TERMINALHIRE_DIR3, "config.json");
|
|
3420
|
+
DEFAULT_CONFIG = {
|
|
3421
|
+
nudge: "session",
|
|
3422
|
+
peerConnect: false,
|
|
3423
|
+
peerConnectPrompted: false
|
|
3424
|
+
};
|
|
3425
|
+
}
|
|
3426
|
+
});
|
|
3427
|
+
|
|
3428
|
+
// bin/peer-connect-prompt.js
|
|
3429
|
+
var peer_connect_prompt_exports = {};
|
|
3430
|
+
__export(peer_connect_prompt_exports, {
|
|
3431
|
+
maybePromptPeerConnect: () => maybePromptPeerConnect
|
|
3432
|
+
});
|
|
3433
|
+
import { createInterface } from "readline";
|
|
3434
|
+
async function maybePromptPeerConnect({
|
|
3435
|
+
input = process.stdin,
|
|
3436
|
+
output = process.stdout,
|
|
3437
|
+
isInteractive = Boolean(process.stdin.isTTY && process.stdout.isTTY)
|
|
3438
|
+
} = {}) {
|
|
3439
|
+
const cfg = readConfig();
|
|
3440
|
+
if (cfg.peerConnectPrompted) {
|
|
3441
|
+
return { prompted: false, peerConnect: cfg.peerConnect === true };
|
|
3442
|
+
}
|
|
3443
|
+
if (!isInteractive) {
|
|
3444
|
+
return { prompted: false, peerConnect: cfg.peerConnect === true };
|
|
3445
|
+
}
|
|
3446
|
+
const rl = createInterface({ input, output });
|
|
3447
|
+
const answer = await new Promise((resolve2) => {
|
|
3448
|
+
rl.question(PROMPT, (a) => {
|
|
3449
|
+
rl.close();
|
|
3450
|
+
resolve2(String(a).trim().toLowerCase());
|
|
3451
|
+
});
|
|
3452
|
+
});
|
|
3453
|
+
const optedIn = answer === "y" || answer === "yes";
|
|
3454
|
+
writeConfig({ peerConnect: optedIn, peerConnectPrompted: true });
|
|
3455
|
+
output.write(
|
|
3456
|
+
optedIn ? "\n Peer-connect ON \u2014 peers & founders may surface in your spinner.\n Turn it off anytime: terminalhire config --connect off\n\n" : "\n Peer-connect stays OFF. Enable anytime: terminalhire config --connect on\n\n"
|
|
3457
|
+
);
|
|
3458
|
+
return { prompted: true, peerConnect: optedIn };
|
|
3459
|
+
}
|
|
3460
|
+
var PROMPT;
|
|
3461
|
+
var init_peer_connect_prompt = __esm({
|
|
3462
|
+
"bin/peer-connect-prompt.js"() {
|
|
3463
|
+
"use strict";
|
|
3464
|
+
init_config();
|
|
3465
|
+
PROMPT = [
|
|
3466
|
+
"",
|
|
3467
|
+
" Connect with other builders?",
|
|
3468
|
+
"",
|
|
3469
|
+
" See peers and founders building what you're building \u2014 matched on your machine,",
|
|
3470
|
+
" so nothing about you leaves it. The only thing ever sent is anonymous: the",
|
|
3471
|
+
" matched person's public username, never yours, never your profile or fingerprint.",
|
|
3472
|
+
"",
|
|
3473
|
+
" Change it anytime: terminalhire config --connect on|off",
|
|
3474
|
+
"",
|
|
3475
|
+
" Opt in? [y/N]: "
|
|
3476
|
+
].join("\n");
|
|
3477
|
+
}
|
|
3478
|
+
});
|
|
3479
|
+
|
|
3380
3480
|
// bin/jpi-login.js
|
|
3381
3481
|
var jpi_login_exports = {};
|
|
3382
3482
|
__export(jpi_login_exports, {
|
|
@@ -3411,9 +3511,9 @@ async function runLogin() {
|
|
|
3411
3511
|
if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
|
|
3412
3512
|
const { createRequire: createRequire2 } = await import("module");
|
|
3413
3513
|
const { fileURLToPath: fileURLToPath7 } = await import("url");
|
|
3414
|
-
const { join:
|
|
3514
|
+
const { join: join21, dirname: dirname3 } = await import("path");
|
|
3415
3515
|
const __dirname6 = fileURLToPath7(new URL(".", import.meta.url));
|
|
3416
|
-
const fixturePath =
|
|
3516
|
+
const fixturePath = join21(__dirname6, "../../fixtures/github-sample.json");
|
|
3417
3517
|
const { readFileSync: readFileSync19 } = await import("fs");
|
|
3418
3518
|
ghProfile = JSON.parse(readFileSync19(fixturePath, "utf8"));
|
|
3419
3519
|
} else {
|
|
@@ -3486,6 +3586,11 @@ async function runLogin() {
|
|
|
3486
3586
|
} catch {
|
|
3487
3587
|
}
|
|
3488
3588
|
}
|
|
3589
|
+
try {
|
|
3590
|
+
const { maybePromptPeerConnect: maybePromptPeerConnect2 } = await Promise.resolve().then(() => (init_peer_connect_prompt(), peer_connect_prompt_exports));
|
|
3591
|
+
await maybePromptPeerConnect2();
|
|
3592
|
+
} catch {
|
|
3593
|
+
}
|
|
3489
3594
|
console.log(" Run `terminalhire jobs` to see matching roles using your enriched profile.");
|
|
3490
3595
|
console.log("");
|
|
3491
3596
|
} catch (err) {
|
|
@@ -3532,14 +3637,14 @@ var jpi_jobs_exports = {};
|
|
|
3532
3637
|
__export(jpi_jobs_exports, {
|
|
3533
3638
|
run: () => run2
|
|
3534
3639
|
});
|
|
3535
|
-
import { readFileSync as
|
|
3536
|
-
import { join as
|
|
3537
|
-
import { homedir as
|
|
3538
|
-
import { createInterface } from "readline";
|
|
3640
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync4 } from "fs";
|
|
3641
|
+
import { join as join5 } from "path";
|
|
3642
|
+
import { homedir as homedir4 } from "os";
|
|
3643
|
+
import { createInterface as createInterface2 } from "readline";
|
|
3539
3644
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3540
3645
|
function readIndexCache() {
|
|
3541
3646
|
try {
|
|
3542
|
-
const raw =
|
|
3647
|
+
const raw = readFileSync5(INDEX_CACHE_FILE, "utf8");
|
|
3543
3648
|
const entry = JSON.parse(raw);
|
|
3544
3649
|
if (Date.now() - entry.ts < INDEX_TTL_MS) return entry.index;
|
|
3545
3650
|
return null;
|
|
@@ -3548,8 +3653,8 @@ function readIndexCache() {
|
|
|
3548
3653
|
}
|
|
3549
3654
|
}
|
|
3550
3655
|
function writeIndexCache(index) {
|
|
3551
|
-
|
|
3552
|
-
|
|
3656
|
+
mkdirSync4(TERMINALHIRE_DIR4, { recursive: true });
|
|
3657
|
+
writeFileSync4(INDEX_CACHE_FILE, JSON.stringify({ ts: Date.now(), index }), "utf8");
|
|
3553
3658
|
}
|
|
3554
3659
|
async function fetchIndex() {
|
|
3555
3660
|
const cached = readIndexCache();
|
|
@@ -3563,7 +3668,7 @@ async function fetchIndex() {
|
|
|
3563
3668
|
return index;
|
|
3564
3669
|
}
|
|
3565
3670
|
function prompt(question) {
|
|
3566
|
-
const rl =
|
|
3671
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
3567
3672
|
return new Promise((resolve2) => {
|
|
3568
3673
|
rl.question(question, (answer) => {
|
|
3569
3674
|
rl.close();
|
|
@@ -3714,10 +3819,10 @@ async function run2() {
|
|
|
3714
3819
|
acceptance: profile.acceptance
|
|
3715
3820
|
});
|
|
3716
3821
|
try {
|
|
3717
|
-
const cacheRaw =
|
|
3822
|
+
const cacheRaw = readFileSync5(INDEX_CACHE_FILE, "utf8");
|
|
3718
3823
|
const cacheEntry = JSON.parse(cacheRaw);
|
|
3719
3824
|
cacheEntry.matchCount = results.length;
|
|
3720
|
-
|
|
3825
|
+
writeFileSync4(INDEX_CACHE_FILE, JSON.stringify(cacheEntry), "utf8");
|
|
3721
3826
|
} catch {
|
|
3722
3827
|
}
|
|
3723
3828
|
if (results.length === 0) {
|
|
@@ -3762,13 +3867,13 @@ Open this URL to apply directly (no data shared):
|
|
|
3762
3867
|
process.exit(1);
|
|
3763
3868
|
}
|
|
3764
3869
|
}
|
|
3765
|
-
var __dirname,
|
|
3870
|
+
var __dirname, TERMINALHIRE_DIR4, INDEX_CACHE_FILE, INDEX_TTL_MS, API_URL, DEFAULT_LIMIT, args, limitArg, LIMIT, REMOTE_ONLY, SHOW_ALL;
|
|
3766
3871
|
var init_jpi_jobs = __esm({
|
|
3767
3872
|
"bin/jpi-jobs.js"() {
|
|
3768
3873
|
"use strict";
|
|
3769
3874
|
__dirname = fileURLToPath2(new URL(".", import.meta.url));
|
|
3770
|
-
|
|
3771
|
-
INDEX_CACHE_FILE =
|
|
3875
|
+
TERMINALHIRE_DIR4 = join5(homedir4(), ".terminalhire");
|
|
3876
|
+
INDEX_CACHE_FILE = join5(TERMINALHIRE_DIR4, "index-cache.json");
|
|
3772
3877
|
INDEX_TTL_MS = 15 * 60 * 1e3;
|
|
3773
3878
|
API_URL = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
3774
3879
|
DEFAULT_LIMIT = 10;
|
|
@@ -3780,19 +3885,13 @@ var init_jpi_jobs = __esm({
|
|
|
3780
3885
|
}
|
|
3781
3886
|
});
|
|
3782
3887
|
|
|
3783
|
-
// bin/
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
run: () => run3
|
|
3788
|
-
});
|
|
3789
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
3790
|
-
import { join as join5 } from "path";
|
|
3791
|
-
import { homedir as homedir4 } from "os";
|
|
3792
|
-
import { createInterface as createInterface2 } from "readline";
|
|
3888
|
+
// bin/directory.js
|
|
3889
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
3890
|
+
import { join as join6 } from "path";
|
|
3891
|
+
import { homedir as homedir5 } from "os";
|
|
3793
3892
|
function readDirectoryCache() {
|
|
3794
3893
|
try {
|
|
3795
|
-
const entry = JSON.parse(
|
|
3894
|
+
const entry = JSON.parse(readFileSync6(DIRECTORY_CACHE_FILE, "utf8"));
|
|
3796
3895
|
if (typeof entry.ts === "number" && Number.isFinite(entry.ts) && Date.now() - entry.ts < INDEX_TTL_MS2) {
|
|
3797
3896
|
return { index: entry.index, ts: entry.ts };
|
|
3798
3897
|
}
|
|
@@ -3802,12 +3901,12 @@ function readDirectoryCache() {
|
|
|
3802
3901
|
}
|
|
3803
3902
|
}
|
|
3804
3903
|
function writeDirectoryCache(index) {
|
|
3805
|
-
|
|
3806
|
-
|
|
3904
|
+
mkdirSync5(TERMINALHIRE_DIR5, { recursive: true });
|
|
3905
|
+
writeFileSync5(DIRECTORY_CACHE_FILE, JSON.stringify({ ts: Date.now(), index }), "utf8");
|
|
3807
3906
|
}
|
|
3808
3907
|
function readProject() {
|
|
3809
3908
|
try {
|
|
3810
|
-
return JSON.parse(
|
|
3909
|
+
return JSON.parse(readFileSync6(PROJECT_FILE, "utf8"));
|
|
3811
3910
|
} catch {
|
|
3812
3911
|
return null;
|
|
3813
3912
|
}
|
|
@@ -3818,13 +3917,13 @@ function relativeTime(ts) {
|
|
|
3818
3917
|
const mins = Math.round(secs / 60);
|
|
3819
3918
|
return mins < 60 ? `${mins}m ago` : `${Math.round(mins / 60)}h ago`;
|
|
3820
3919
|
}
|
|
3821
|
-
async function fetchDirectory() {
|
|
3920
|
+
async function fetchDirectory({ quiet = false } = {}) {
|
|
3822
3921
|
const cached = readDirectoryCache();
|
|
3823
3922
|
if (cached) {
|
|
3824
|
-
console.log(`\u2713 Using cached directory (updated ${relativeTime(cached.ts)})`);
|
|
3923
|
+
if (!quiet) console.log(`\u2713 Using cached directory (updated ${relativeTime(cached.ts)})`);
|
|
3825
3924
|
return cached.index;
|
|
3826
3925
|
}
|
|
3827
|
-
console.log(`\u21BB Refreshing builder directory from ${API_URL2}/api/directory...`);
|
|
3926
|
+
if (!quiet) console.log(`\u21BB Refreshing builder directory from ${API_URL2}/api/directory...`);
|
|
3828
3927
|
const res = await fetch(`${API_URL2}/api/directory`, { signal: AbortSignal.timeout(1e4) });
|
|
3829
3928
|
if (!res.ok) throw new Error(`/api/directory returned ${res.status}`);
|
|
3830
3929
|
const index = await res.json();
|
|
@@ -3839,7 +3938,7 @@ function reportMatched(results, fetchImpl = fetch) {
|
|
|
3839
3938
|
)
|
|
3840
3939
|
];
|
|
3841
3940
|
if (logins.length === 0) return;
|
|
3842
|
-
Promise.resolve(
|
|
3941
|
+
return Promise.resolve(
|
|
3843
3942
|
fetchImpl(`${API_URL2}/api/directory/matched`, {
|
|
3844
3943
|
method: "POST",
|
|
3845
3944
|
headers: { "Content-Type": "application/json" },
|
|
@@ -3851,8 +3950,27 @@ function reportMatched(results, fetchImpl = fetch) {
|
|
|
3851
3950
|
} catch {
|
|
3852
3951
|
}
|
|
3853
3952
|
}
|
|
3953
|
+
var TERMINALHIRE_DIR5, DIRECTORY_CACHE_FILE, PROJECT_FILE, INDEX_TTL_MS2, API_URL2;
|
|
3954
|
+
var init_directory2 = __esm({
|
|
3955
|
+
"bin/directory.js"() {
|
|
3956
|
+
"use strict";
|
|
3957
|
+
TERMINALHIRE_DIR5 = join6(homedir5(), ".terminalhire");
|
|
3958
|
+
DIRECTORY_CACHE_FILE = join6(TERMINALHIRE_DIR5, "directory-cache.json");
|
|
3959
|
+
PROJECT_FILE = join6(TERMINALHIRE_DIR5, "project.json");
|
|
3960
|
+
INDEX_TTL_MS2 = 15 * 60 * 1e3;
|
|
3961
|
+
API_URL2 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
3962
|
+
}
|
|
3963
|
+
});
|
|
3964
|
+
|
|
3965
|
+
// bin/jpi-devs.js
|
|
3966
|
+
var jpi_devs_exports = {};
|
|
3967
|
+
__export(jpi_devs_exports, {
|
|
3968
|
+
reportMatched: () => reportMatched,
|
|
3969
|
+
run: () => run3
|
|
3970
|
+
});
|
|
3971
|
+
import { createInterface as createInterface3 } from "readline";
|
|
3854
3972
|
function prompt2(question) {
|
|
3855
|
-
const rl =
|
|
3973
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
3856
3974
|
return new Promise((resolve2) => {
|
|
3857
3975
|
rl.question(question, (answer) => {
|
|
3858
3976
|
rl.close();
|
|
@@ -3862,7 +3980,7 @@ function prompt2(question) {
|
|
|
3862
3980
|
}
|
|
3863
3981
|
function credentialUrl(job) {
|
|
3864
3982
|
const u = job.url ?? "";
|
|
3865
|
-
return u.startsWith("http") ? u : `${
|
|
3983
|
+
return u.startsWith("http") ? u : `${API_URL3}${u}`;
|
|
3866
3984
|
}
|
|
3867
3985
|
function linkTitle2(title, url) {
|
|
3868
3986
|
const isTTY = process.stdout.isTTY;
|
|
@@ -3947,15 +4065,12 @@ Open this public credential (no data shared):
|
|
|
3947
4065
|
process.exit(1);
|
|
3948
4066
|
}
|
|
3949
4067
|
}
|
|
3950
|
-
var
|
|
4068
|
+
var API_URL3, DEFAULT_LIMIT2, args2, limitArg2, LIMIT2, SHOW_ALL2, AS_PROJECT;
|
|
3951
4069
|
var init_jpi_devs = __esm({
|
|
3952
4070
|
"bin/jpi-devs.js"() {
|
|
3953
4071
|
"use strict";
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
PROJECT_FILE = join5(TERMINALHIRE_DIR4, "project.json");
|
|
3957
|
-
INDEX_TTL_MS2 = 15 * 60 * 1e3;
|
|
3958
|
-
API_URL2 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
4072
|
+
init_directory2();
|
|
4073
|
+
API_URL3 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
3959
4074
|
DEFAULT_LIMIT2 = 10;
|
|
3960
4075
|
args2 = process.argv.slice(2);
|
|
3961
4076
|
limitArg2 = args2.indexOf("--limit");
|
|
@@ -3970,19 +4085,19 @@ var jpi_project_exports = {};
|
|
|
3970
4085
|
__export(jpi_project_exports, {
|
|
3971
4086
|
run: () => run4
|
|
3972
4087
|
});
|
|
3973
|
-
import { readFileSync as
|
|
3974
|
-
import { join as
|
|
3975
|
-
import { homedir as
|
|
3976
|
-
import { createInterface as
|
|
4088
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
4089
|
+
import { join as join7 } from "path";
|
|
4090
|
+
import { homedir as homedir6 } from "os";
|
|
4091
|
+
import { createInterface as createInterface4 } from "readline";
|
|
3977
4092
|
function readProject2() {
|
|
3978
4093
|
try {
|
|
3979
|
-
return JSON.parse(
|
|
4094
|
+
return JSON.parse(readFileSync7(PROJECT_FILE2, "utf8"));
|
|
3980
4095
|
} catch {
|
|
3981
4096
|
return null;
|
|
3982
4097
|
}
|
|
3983
4098
|
}
|
|
3984
4099
|
function promptRaw(question) {
|
|
3985
|
-
const rl =
|
|
4100
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
3986
4101
|
return new Promise((resolve2) => {
|
|
3987
4102
|
rl.question(question, (answer) => {
|
|
3988
4103
|
rl.close();
|
|
@@ -4052,8 +4167,8 @@ async function run4() {
|
|
|
4052
4167
|
prefs: {},
|
|
4053
4168
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4054
4169
|
};
|
|
4055
|
-
|
|
4056
|
-
|
|
4170
|
+
mkdirSync6(TERMINALHIRE_DIR6, { recursive: true });
|
|
4171
|
+
writeFileSync6(PROJECT_FILE2, JSON.stringify(project, null, 2), "utf8");
|
|
4057
4172
|
console.log(`
|
|
4058
4173
|
\u2726 Project saved locally (never sent): ${title}`);
|
|
4059
4174
|
console.log(` Skills: ${skillTags.join(", ")}`);
|
|
@@ -4064,12 +4179,12 @@ async function run4() {
|
|
|
4064
4179
|
process.exit(1);
|
|
4065
4180
|
}
|
|
4066
4181
|
}
|
|
4067
|
-
var
|
|
4182
|
+
var TERMINALHIRE_DIR6, PROJECT_FILE2, args3, SHOW, declarationArg;
|
|
4068
4183
|
var init_jpi_project = __esm({
|
|
4069
4184
|
"bin/jpi-project.js"() {
|
|
4070
4185
|
"use strict";
|
|
4071
|
-
|
|
4072
|
-
PROJECT_FILE2 =
|
|
4186
|
+
TERMINALHIRE_DIR6 = join7(homedir6(), ".terminalhire");
|
|
4187
|
+
PROJECT_FILE2 = join7(TERMINALHIRE_DIR6, "project.json");
|
|
4073
4188
|
args3 = process.argv.slice(2);
|
|
4074
4189
|
SHOW = args3.includes("--show");
|
|
4075
4190
|
declarationArg = args3.filter((a) => !a.startsWith("--")).join(" ").trim();
|
|
@@ -4081,13 +4196,13 @@ var jpi_bounties_exports = {};
|
|
|
4081
4196
|
__export(jpi_bounties_exports, {
|
|
4082
4197
|
run: () => run5
|
|
4083
4198
|
});
|
|
4084
|
-
import { readFileSync as
|
|
4085
|
-
import { join as
|
|
4086
|
-
import { homedir as
|
|
4087
|
-
import { createInterface as
|
|
4199
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
|
|
4200
|
+
import { join as join8 } from "path";
|
|
4201
|
+
import { homedir as homedir7 } from "os";
|
|
4202
|
+
import { createInterface as createInterface5 } from "readline";
|
|
4088
4203
|
function readIndexCache2() {
|
|
4089
4204
|
try {
|
|
4090
|
-
const entry = JSON.parse(
|
|
4205
|
+
const entry = JSON.parse(readFileSync8(INDEX_CACHE_FILE2, "utf8"));
|
|
4091
4206
|
if (Date.now() - entry.ts < INDEX_TTL_MS3) return entry.index;
|
|
4092
4207
|
return null;
|
|
4093
4208
|
} catch {
|
|
@@ -4095,20 +4210,20 @@ function readIndexCache2() {
|
|
|
4095
4210
|
}
|
|
4096
4211
|
}
|
|
4097
4212
|
function writeIndexCache2(index) {
|
|
4098
|
-
|
|
4099
|
-
|
|
4213
|
+
mkdirSync7(TERMINALHIRE_DIR7, { recursive: true });
|
|
4214
|
+
writeFileSync7(INDEX_CACHE_FILE2, JSON.stringify({ ts: Date.now(), index }), "utf8");
|
|
4100
4215
|
}
|
|
4101
4216
|
async function fetchIndex2() {
|
|
4102
4217
|
const cached = readIndexCache2();
|
|
4103
4218
|
if (cached) return cached;
|
|
4104
|
-
const res = await fetch(`${
|
|
4219
|
+
const res = await fetch(`${API_URL4}/api/index`, { signal: AbortSignal.timeout(1e4) });
|
|
4105
4220
|
if (!res.ok) throw new Error(`/api/index returned ${res.status}`);
|
|
4106
4221
|
const index = await res.json();
|
|
4107
4222
|
writeIndexCache2(index);
|
|
4108
4223
|
return index;
|
|
4109
4224
|
}
|
|
4110
4225
|
function prompt3(question) {
|
|
4111
|
-
const rl =
|
|
4226
|
+
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
4112
4227
|
return new Promise((resolve2) => {
|
|
4113
4228
|
rl.question(question, (answer) => {
|
|
4114
4229
|
rl.close();
|
|
@@ -4142,7 +4257,7 @@ ${i + 1}. ${linkTitle3(job.title, job.url)}`);
|
|
|
4142
4257
|
}
|
|
4143
4258
|
async function run5() {
|
|
4144
4259
|
try {
|
|
4145
|
-
console.log(`Fetching bounty index from ${
|
|
4260
|
+
console.log(`Fetching bounty index from ${API_URL4}/api/index...`);
|
|
4146
4261
|
const index = await fetchIndex2();
|
|
4147
4262
|
let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");
|
|
4148
4263
|
if (PRICED_ONLY) bounties = bounties.filter((j) => j.bounty?.amountUSD != null);
|
|
@@ -4200,14 +4315,14 @@ Open this to claim/work the bounty (you go straight to the source \u2014 we neve
|
|
|
4200
4315
|
process.exit(1);
|
|
4201
4316
|
}
|
|
4202
4317
|
}
|
|
4203
|
-
var
|
|
4318
|
+
var TERMINALHIRE_DIR7, INDEX_CACHE_FILE2, INDEX_TTL_MS3, API_URL4, DEFAULT_LIMIT3, args4, limitArg3, LIMIT3, PRICED_ONLY, SHOW_ALL3, WINNABLE_ONLY, EFFORT_LABEL;
|
|
4204
4319
|
var init_jpi_bounties = __esm({
|
|
4205
4320
|
"bin/jpi-bounties.js"() {
|
|
4206
4321
|
"use strict";
|
|
4207
|
-
|
|
4208
|
-
INDEX_CACHE_FILE2 =
|
|
4322
|
+
TERMINALHIRE_DIR7 = join8(homedir7(), ".terminalhire");
|
|
4323
|
+
INDEX_CACHE_FILE2 = join8(TERMINALHIRE_DIR7, "index-cache.json");
|
|
4209
4324
|
INDEX_TTL_MS3 = 15 * 60 * 1e3;
|
|
4210
|
-
|
|
4325
|
+
API_URL4 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
4211
4326
|
DEFAULT_LIMIT3 = 15;
|
|
4212
4327
|
args4 = process.argv.slice(2);
|
|
4213
4328
|
limitArg3 = args4.indexOf("--limit");
|
|
@@ -4230,26 +4345,26 @@ __export(claims_exports, {
|
|
|
4230
4345
|
removeClaim: () => removeClaim,
|
|
4231
4346
|
updateClaim: () => updateClaim
|
|
4232
4347
|
});
|
|
4233
|
-
import { readFileSync as
|
|
4234
|
-
import { join as
|
|
4235
|
-
import { homedir as
|
|
4348
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, renameSync, existsSync as existsSync5 } from "fs";
|
|
4349
|
+
import { join as join9 } from "path";
|
|
4350
|
+
import { homedir as homedir8 } from "os";
|
|
4236
4351
|
function nowISO() {
|
|
4237
4352
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4238
4353
|
}
|
|
4239
4354
|
function readClaims() {
|
|
4240
4355
|
try {
|
|
4241
|
-
if (!
|
|
4242
|
-
const data = JSON.parse(
|
|
4356
|
+
if (!existsSync5(CLAIMS_FILE)) return [];
|
|
4357
|
+
const data = JSON.parse(readFileSync9(CLAIMS_FILE, "utf8"));
|
|
4243
4358
|
return Array.isArray(data?.claims) ? data.claims : [];
|
|
4244
4359
|
} catch {
|
|
4245
4360
|
return [];
|
|
4246
4361
|
}
|
|
4247
4362
|
}
|
|
4248
4363
|
function writeClaims(claims) {
|
|
4249
|
-
|
|
4364
|
+
mkdirSync8(TERMINALHIRE_DIR8, { recursive: true });
|
|
4250
4365
|
const tmp = `${CLAIMS_FILE}.tmp`;
|
|
4251
4366
|
const payload = { claims };
|
|
4252
|
-
|
|
4367
|
+
writeFileSync8(tmp, JSON.stringify(payload, null, 2), "utf8");
|
|
4253
4368
|
renameSync(tmp, CLAIMS_FILE);
|
|
4254
4369
|
}
|
|
4255
4370
|
function findClaim(id) {
|
|
@@ -4302,12 +4417,12 @@ function acceptedPRRate(claims = readClaims()) {
|
|
|
4302
4417
|
const merged = claims.filter((c) => c.state === "merged").length;
|
|
4303
4418
|
return { merged, total, rate: total === 0 ? 0 : merged / total };
|
|
4304
4419
|
}
|
|
4305
|
-
var
|
|
4420
|
+
var TERMINALHIRE_DIR8, CLAIMS_FILE, TERMINAL_STATES;
|
|
4306
4421
|
var init_claims = __esm({
|
|
4307
4422
|
"src/claims.ts"() {
|
|
4308
4423
|
"use strict";
|
|
4309
|
-
|
|
4310
|
-
CLAIMS_FILE =
|
|
4424
|
+
TERMINALHIRE_DIR8 = join9(homedir8(), ".terminalhire");
|
|
4425
|
+
CLAIMS_FILE = join9(TERMINALHIRE_DIR8, "claims.json");
|
|
4311
4426
|
TERMINAL_STATES = /* @__PURE__ */ new Set(["merged", "abandoned"]);
|
|
4312
4427
|
}
|
|
4313
4428
|
});
|
|
@@ -4317,18 +4432,18 @@ var jpi_claim_exports = {};
|
|
|
4317
4432
|
__export(jpi_claim_exports, {
|
|
4318
4433
|
run: () => run6
|
|
4319
4434
|
});
|
|
4320
|
-
import { readFileSync as
|
|
4321
|
-
import { join as
|
|
4322
|
-
import { homedir as
|
|
4435
|
+
import { readFileSync as readFileSync10, existsSync as existsSync6 } from "fs";
|
|
4436
|
+
import { join as join10 } from "path";
|
|
4437
|
+
import { homedir as homedir9 } from "os";
|
|
4323
4438
|
import { execFile } from "child_process";
|
|
4324
4439
|
import { promisify } from "util";
|
|
4325
|
-
import { createInterface as
|
|
4440
|
+
import { createInterface as createInterface6 } from "readline";
|
|
4326
4441
|
async function sh(cmd, args5, opts = {}) {
|
|
4327
4442
|
const { stdout } = await pExecFile(cmd, args5, { ...opts, shell: false, maxBuffer: 16 * 1024 * 1024 });
|
|
4328
4443
|
return String(stdout).trim();
|
|
4329
4444
|
}
|
|
4330
4445
|
async function confirm(question) {
|
|
4331
|
-
const rl =
|
|
4446
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
4332
4447
|
try {
|
|
4333
4448
|
const ans = await new Promise((resolve2) => rl.question(question, resolve2));
|
|
4334
4449
|
return /^y(es)?$/i.test(String(ans).trim());
|
|
@@ -4366,8 +4481,8 @@ function parseRepoFromRemote(url) {
|
|
|
4366
4481
|
}
|
|
4367
4482
|
function findBountyInCache(bountyId) {
|
|
4368
4483
|
try {
|
|
4369
|
-
if (!
|
|
4370
|
-
const entry = JSON.parse(
|
|
4484
|
+
if (!existsSync6(INDEX_CACHE_FILE3)) return null;
|
|
4485
|
+
const entry = JSON.parse(readFileSync10(INDEX_CACHE_FILE3, "utf8"));
|
|
4371
4486
|
const jobs = entry?.index?.jobs ?? [];
|
|
4372
4487
|
const job = jobs.find((j) => j.id === bountyId && j.source === "bounty");
|
|
4373
4488
|
return job ?? null;
|
|
@@ -4871,12 +4986,12 @@ async function run6() {
|
|
|
4871
4986
|
process.exit(1);
|
|
4872
4987
|
}
|
|
4873
4988
|
}
|
|
4874
|
-
var
|
|
4989
|
+
var TERMINALHIRE_DIR9, INDEX_CACHE_FILE3, GH_API, GH_HEADERS, pExecFile, VALUE_FLAGS;
|
|
4875
4990
|
var init_jpi_claim = __esm({
|
|
4876
4991
|
"bin/jpi-claim.js"() {
|
|
4877
4992
|
"use strict";
|
|
4878
|
-
|
|
4879
|
-
INDEX_CACHE_FILE3 =
|
|
4993
|
+
TERMINALHIRE_DIR9 = join10(homedir9(), ".terminalhire");
|
|
4994
|
+
INDEX_CACHE_FILE3 = join10(TERMINALHIRE_DIR9, "index-cache.json");
|
|
4880
4995
|
GH_API = "https://api.github.com";
|
|
4881
4996
|
GH_HEADERS = { "User-Agent": "terminalhire-claim", Accept: "application/vnd.github+json" };
|
|
4882
4997
|
pExecFile = promisify(execFile);
|
|
@@ -5160,7 +5275,7 @@ function finalize(build) {
|
|
|
5160
5275
|
};
|
|
5161
5276
|
}
|
|
5162
5277
|
function reconstruct(files, opts = {}) {
|
|
5163
|
-
const
|
|
5278
|
+
const join21 = opts.joinSidechains !== false;
|
|
5164
5279
|
const mains = [];
|
|
5165
5280
|
const sidechains = [];
|
|
5166
5281
|
for (const file of files) {
|
|
@@ -5185,7 +5300,7 @@ function reconstruct(files, opts = {}) {
|
|
|
5185
5300
|
}
|
|
5186
5301
|
const orphanedSidechainPaths = [];
|
|
5187
5302
|
const joinedPaths = /* @__PURE__ */ new Set();
|
|
5188
|
-
if (
|
|
5303
|
+
if (join21) {
|
|
5189
5304
|
const sidechainsBySession = /* @__PURE__ */ new Map();
|
|
5190
5305
|
for (const sc of sidechains) {
|
|
5191
5306
|
const acc = sidechainsBySession.get(sc.sessionId) ?? [];
|
|
@@ -5739,14 +5854,14 @@ __export(trajectory_exports, {
|
|
|
5739
5854
|
runTrajectoryPush: () => runTrajectoryPush
|
|
5740
5855
|
});
|
|
5741
5856
|
import {
|
|
5742
|
-
existsSync as
|
|
5743
|
-
mkdirSync as
|
|
5744
|
-
readFileSync as
|
|
5857
|
+
existsSync as existsSync7,
|
|
5858
|
+
mkdirSync as mkdirSync9,
|
|
5859
|
+
readFileSync as readFileSync11,
|
|
5745
5860
|
readdirSync,
|
|
5746
|
-
writeFileSync as
|
|
5861
|
+
writeFileSync as writeFileSync9
|
|
5747
5862
|
} from "fs";
|
|
5748
|
-
import { homedir as
|
|
5749
|
-
import { join as
|
|
5863
|
+
import { homedir as homedir10 } from "os";
|
|
5864
|
+
import { join as join11 } from "path";
|
|
5750
5865
|
function isRecord4(value) {
|
|
5751
5866
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5752
5867
|
}
|
|
@@ -5778,7 +5893,7 @@ function findJsonlFiles(dir) {
|
|
|
5778
5893
|
return out;
|
|
5779
5894
|
}
|
|
5780
5895
|
for (const entry of entries) {
|
|
5781
|
-
const full =
|
|
5896
|
+
const full = join11(dir, entry.name);
|
|
5782
5897
|
if (entry.isDirectory()) {
|
|
5783
5898
|
out.push(...findJsonlFiles(full));
|
|
5784
5899
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -5792,7 +5907,7 @@ function loadCorpus(paths) {
|
|
|
5792
5907
|
for (const path of paths) {
|
|
5793
5908
|
let text;
|
|
5794
5909
|
try {
|
|
5795
|
-
text =
|
|
5910
|
+
text = readFileSync11(path, "utf8");
|
|
5796
5911
|
} catch {
|
|
5797
5912
|
continue;
|
|
5798
5913
|
}
|
|
@@ -5891,12 +6006,12 @@ function renderMarkdown(view) {
|
|
|
5891
6006
|
return lines.join("\n");
|
|
5892
6007
|
}
|
|
5893
6008
|
function writeExportArtifacts(score, markdown) {
|
|
5894
|
-
const dir =
|
|
5895
|
-
|
|
5896
|
-
const jsonPath =
|
|
5897
|
-
const mdPath =
|
|
5898
|
-
|
|
5899
|
-
|
|
6009
|
+
const dir = join11(homedir10(), ".terminalhire");
|
|
6010
|
+
mkdirSync9(dir, { recursive: true });
|
|
6011
|
+
const jsonPath = join11(dir, "trajectory-export.json");
|
|
6012
|
+
const mdPath = join11(dir, "trajectory-export.md");
|
|
6013
|
+
writeFileSync9(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
|
|
6014
|
+
writeFileSync9(mdPath, markdown, "utf8");
|
|
5900
6015
|
return { jsonPath, mdPath };
|
|
5901
6016
|
}
|
|
5902
6017
|
function renderInward(allNodes, view, files) {
|
|
@@ -5915,8 +6030,8 @@ function renderInward(allNodes, view, files) {
|
|
|
5915
6030
|
console.log("");
|
|
5916
6031
|
}
|
|
5917
6032
|
function buildTrajectory() {
|
|
5918
|
-
const projectsDir =
|
|
5919
|
-
if (!
|
|
6033
|
+
const projectsDir = join11(homedir10(), ".claude", "projects");
|
|
6034
|
+
if (!existsSync7(projectsDir)) return null;
|
|
5920
6035
|
const paths = findJsonlFiles(projectsDir);
|
|
5921
6036
|
if (paths.length === 0) return null;
|
|
5922
6037
|
const files = loadCorpus(paths);
|
|
@@ -5989,8 +6104,8 @@ function defaultPushDeps() {
|
|
|
5989
6104
|
}
|
|
5990
6105
|
},
|
|
5991
6106
|
prompt: async (question) => {
|
|
5992
|
-
const { createInterface:
|
|
5993
|
-
const rl =
|
|
6107
|
+
const { createInterface: createInterface11 } = await import("readline");
|
|
6108
|
+
const rl = createInterface11({ input: process.stdin, output: process.stdout });
|
|
5994
6109
|
return new Promise((res) => {
|
|
5995
6110
|
rl.question(question, (answer) => {
|
|
5996
6111
|
rl.close();
|
|
@@ -6240,8 +6355,8 @@ function defaultIntroDeps() {
|
|
|
6240
6355
|
}
|
|
6241
6356
|
},
|
|
6242
6357
|
prompt: async (question) => {
|
|
6243
|
-
const { createInterface:
|
|
6244
|
-
const rl =
|
|
6358
|
+
const { createInterface: createInterface11 } = await import("readline");
|
|
6359
|
+
const rl = createInterface11({ input: process.stdin, output: process.stdout });
|
|
6245
6360
|
return new Promise((res) => {
|
|
6246
6361
|
rl.question(question, (answer) => {
|
|
6247
6362
|
rl.close();
|
|
@@ -6594,9 +6709,9 @@ var jpi_profile_exports = {};
|
|
|
6594
6709
|
__export(jpi_profile_exports, {
|
|
6595
6710
|
run: () => run9
|
|
6596
6711
|
});
|
|
6597
|
-
import { createInterface as
|
|
6712
|
+
import { createInterface as createInterface7 } from "readline";
|
|
6598
6713
|
function prompt4(question) {
|
|
6599
|
-
const rl =
|
|
6714
|
+
const rl = createInterface7({ input: process.stdin, output: process.stdout });
|
|
6600
6715
|
return new Promise((resolve2) => {
|
|
6601
6716
|
rl.question(question, (answer) => {
|
|
6602
6717
|
rl.close();
|
|
@@ -6677,9 +6792,9 @@ var signal_exports = {};
|
|
|
6677
6792
|
__export(signal_exports, {
|
|
6678
6793
|
extractFingerprint: () => extractFingerprint
|
|
6679
6794
|
});
|
|
6680
|
-
import { readFileSync as
|
|
6795
|
+
import { readFileSync as readFileSync12, readdirSync as readdirSync2 } from "fs";
|
|
6681
6796
|
import { execFileSync } from "child_process";
|
|
6682
|
-
import { join as
|
|
6797
|
+
import { join as join12 } from "path";
|
|
6683
6798
|
function safeGit(args5, cwd) {
|
|
6684
6799
|
try {
|
|
6685
6800
|
return execFileSync("git", ["-C", cwd, ...args5], {
|
|
@@ -6707,20 +6822,20 @@ function isEmployerContext(cwd) {
|
|
|
6707
6822
|
}
|
|
6708
6823
|
function readJsonSafe(path) {
|
|
6709
6824
|
try {
|
|
6710
|
-
return JSON.parse(
|
|
6825
|
+
return JSON.parse(readFileSync12(path, "utf8"));
|
|
6711
6826
|
} catch {
|
|
6712
6827
|
return null;
|
|
6713
6828
|
}
|
|
6714
6829
|
}
|
|
6715
6830
|
function readFileSafe(path) {
|
|
6716
6831
|
try {
|
|
6717
|
-
return
|
|
6832
|
+
return readFileSync12(path, "utf8");
|
|
6718
6833
|
} catch {
|
|
6719
6834
|
return "";
|
|
6720
6835
|
}
|
|
6721
6836
|
}
|
|
6722
6837
|
function tokensFromPackageJson(cwd) {
|
|
6723
|
-
const pkg = readJsonSafe(
|
|
6838
|
+
const pkg = readJsonSafe(join12(cwd, "package.json"));
|
|
6724
6839
|
if (!pkg || typeof pkg !== "object") return [];
|
|
6725
6840
|
const p = pkg;
|
|
6726
6841
|
const deps = {
|
|
@@ -6734,9 +6849,9 @@ function workspaceMemberDirs(cwd) {
|
|
|
6734
6849
|
const dirs = [cwd];
|
|
6735
6850
|
for (const group of ["apps", "packages"]) {
|
|
6736
6851
|
try {
|
|
6737
|
-
const groupDir =
|
|
6852
|
+
const groupDir = join12(cwd, group);
|
|
6738
6853
|
for (const e of readdirSync2(groupDir, { withFileTypes: true })) {
|
|
6739
|
-
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(
|
|
6854
|
+
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join12(groupDir, e.name));
|
|
6740
6855
|
}
|
|
6741
6856
|
} catch {
|
|
6742
6857
|
}
|
|
@@ -6744,18 +6859,18 @@ function workspaceMemberDirs(cwd) {
|
|
|
6744
6859
|
return dirs;
|
|
6745
6860
|
}
|
|
6746
6861
|
function tokensFromRequirementsTxt(cwd) {
|
|
6747
|
-
const content = readFileSafe(
|
|
6862
|
+
const content = readFileSafe(join12(cwd, "requirements.txt"));
|
|
6748
6863
|
if (!content) return [];
|
|
6749
6864
|
return content.split("\n").map((l) => l.trim().split(/[>=<!\[;]/)[0].trim().toLowerCase()).filter(Boolean);
|
|
6750
6865
|
}
|
|
6751
6866
|
function tokensFromGoMod(cwd) {
|
|
6752
|
-
const content = readFileSafe(
|
|
6867
|
+
const content = readFileSafe(join12(cwd, "go.mod"));
|
|
6753
6868
|
if (!content) return [];
|
|
6754
6869
|
const requires = Array.from(content.matchAll(/^\s+([^\s]+)\s+v/gm)).map((m) => m[1].split("/").pop() ?? "").filter(Boolean);
|
|
6755
6870
|
return ["go", ...requires];
|
|
6756
6871
|
}
|
|
6757
6872
|
function tokensFromCargoToml(cwd) {
|
|
6758
|
-
const content = readFileSafe(
|
|
6873
|
+
const content = readFileSafe(join12(cwd, "Cargo.toml"));
|
|
6759
6874
|
if (!content) return [];
|
|
6760
6875
|
const deps = [];
|
|
6761
6876
|
let inDeps = false;
|
|
@@ -6776,7 +6891,7 @@ function tokensFromFileExtensions(cwd) {
|
|
|
6776
6891
|
const tokens = [];
|
|
6777
6892
|
const scanDirs = [cwd];
|
|
6778
6893
|
try {
|
|
6779
|
-
const srcDir =
|
|
6894
|
+
const srcDir = join12(cwd, "src");
|
|
6780
6895
|
readdirSync2(srcDir);
|
|
6781
6896
|
scanDirs.push(srcDir);
|
|
6782
6897
|
} catch {
|
|
@@ -6976,22 +7091,8 @@ var jpi_config_exports = {};
|
|
|
6976
7091
|
__export(jpi_config_exports, {
|
|
6977
7092
|
run: () => run11
|
|
6978
7093
|
});
|
|
6979
|
-
import {
|
|
6980
|
-
import {
|
|
6981
|
-
import { homedir as homedir10 } from "os";
|
|
6982
|
-
function readConfig() {
|
|
6983
|
-
try {
|
|
6984
|
-
if (!existsSync7(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
|
|
6985
|
-
return { ...DEFAULT_CONFIG, ...JSON.parse(readFileSync12(CONFIG_FILE, "utf8")) };
|
|
6986
|
-
} catch {
|
|
6987
|
-
return { ...DEFAULT_CONFIG };
|
|
6988
|
-
}
|
|
6989
|
-
}
|
|
6990
|
-
function writeConfig(patch) {
|
|
6991
|
-
mkdirSync9(TERMINALHIRE_DIR9, { recursive: true });
|
|
6992
|
-
const merged = { ...readConfig(), ...patch };
|
|
6993
|
-
writeFileSync9(CONFIG_FILE, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
6994
|
-
}
|
|
7094
|
+
import { join as join13 } from "path";
|
|
7095
|
+
import { homedir as homedir11 } from "os";
|
|
6995
7096
|
function parseNudgeMode(raw) {
|
|
6996
7097
|
if (raw === "session" || raw === "always") return raw;
|
|
6997
7098
|
const m = /^every:(\d+)$/.exec(raw);
|
|
@@ -7011,13 +7112,18 @@ async function run11() {
|
|
|
7011
7112
|
if (envOverride) {
|
|
7012
7113
|
console.log(` (overridden by TERMINALHIRE_NUDGE=${envOverride} at runtime)`);
|
|
7013
7114
|
}
|
|
7014
|
-
console.log(`
|
|
7115
|
+
console.log(` peer-connect: ${cfg.peerConnect ? "on" : "off"} (ambient peer & founder surfacing; default off)`);
|
|
7116
|
+
console.log(` config file: ${CONFIG_FILE2}`);
|
|
7015
7117
|
console.log("");
|
|
7016
7118
|
console.log(" Valid nudge values:");
|
|
7017
7119
|
console.log(" session \u2014 print at most once per Claude Code session (default)");
|
|
7018
7120
|
console.log(" always \u2014 print every statusLine render when matches exist");
|
|
7019
7121
|
console.log(" every:N \u2014 print every Nth render (e.g. every:3)");
|
|
7020
7122
|
console.log("");
|
|
7123
|
+
console.log(" Peer-connect (--connect on|off):");
|
|
7124
|
+
console.log(" on \u2014 surface peers & founders in the spinner + send an anonymous matched signal");
|
|
7125
|
+
console.log(" off \u2014 no peer matching, no directory fetch, no signal (default)");
|
|
7126
|
+
console.log("");
|
|
7021
7127
|
return;
|
|
7022
7128
|
}
|
|
7023
7129
|
const nudgeIdx = filtered.indexOf("--nudge");
|
|
@@ -7034,20 +7140,33 @@ async function run11() {
|
|
|
7034
7140
|
}
|
|
7035
7141
|
writeConfig({ nudge: parsed });
|
|
7036
7142
|
console.log(` nudge set to: ${parsed}`);
|
|
7037
|
-
console.log(` (saved to ${
|
|
7143
|
+
console.log(` (saved to ${CONFIG_FILE2})`);
|
|
7144
|
+
return;
|
|
7145
|
+
}
|
|
7146
|
+
const connectIdx = filtered.indexOf("--connect");
|
|
7147
|
+
if (connectIdx !== -1) {
|
|
7148
|
+
const value = filtered[connectIdx + 1];
|
|
7149
|
+
if (value !== "on" && value !== "off") {
|
|
7150
|
+
console.error("Error: --connect requires a value: on | off");
|
|
7151
|
+
process.exit(1);
|
|
7152
|
+
}
|
|
7153
|
+
writeConfig({ peerConnect: value === "on", peerConnectPrompted: true });
|
|
7154
|
+
console.log(` peer-connect set to: ${value}`);
|
|
7155
|
+
console.log(` (saved to ${CONFIG_FILE2})`);
|
|
7038
7156
|
return;
|
|
7039
7157
|
}
|
|
7040
7158
|
console.error("Usage: terminalhire config --nudge <session|always|every:N>");
|
|
7159
|
+
console.error(" terminalhire config --connect <on|off>");
|
|
7041
7160
|
console.error(" terminalhire config --show");
|
|
7042
7161
|
process.exit(1);
|
|
7043
7162
|
}
|
|
7044
|
-
var
|
|
7163
|
+
var TERMINALHIRE_DIR10, CONFIG_FILE2;
|
|
7045
7164
|
var init_jpi_config = __esm({
|
|
7046
7165
|
"bin/jpi-config.js"() {
|
|
7047
7166
|
"use strict";
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7167
|
+
init_config();
|
|
7168
|
+
TERMINALHIRE_DIR10 = join13(homedir11(), ".terminalhire");
|
|
7169
|
+
CONFIG_FILE2 = join13(TERMINALHIRE_DIR10, "config.json");
|
|
7051
7170
|
}
|
|
7052
7171
|
});
|
|
7053
7172
|
|
|
@@ -7058,6 +7177,7 @@ __export(spinner_exports, {
|
|
|
7058
7177
|
applySpinnerTips: () => applySpinnerTips,
|
|
7059
7178
|
applySpinnerVerbs: () => applySpinnerVerbs,
|
|
7060
7179
|
buildContextVerbs: () => buildContextVerbs,
|
|
7180
|
+
buildPeerLine: () => buildPeerLine,
|
|
7061
7181
|
buildSpinnerPool: () => buildSpinnerPool,
|
|
7062
7182
|
buildTips: () => buildTips,
|
|
7063
7183
|
clearSpinnerTips: () => clearSpinnerTips,
|
|
@@ -7075,8 +7195,8 @@ import {
|
|
|
7075
7195
|
mkdirSync as mkdirSync10,
|
|
7076
7196
|
renameSync as renameSync2
|
|
7077
7197
|
} from "fs";
|
|
7078
|
-
import { join as
|
|
7079
|
-
import { homedir as
|
|
7198
|
+
import { join as join14, dirname } from "path";
|
|
7199
|
+
import { homedir as homedir12 } from "os";
|
|
7080
7200
|
function readJson(path, fallback) {
|
|
7081
7201
|
try {
|
|
7082
7202
|
return existsSync8(path) ? JSON.parse(readFileSync13(path, "utf8")) : fallback;
|
|
@@ -7094,7 +7214,7 @@ function titleCase(s) {
|
|
|
7094
7214
|
return String(s || "").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
7095
7215
|
}
|
|
7096
7216
|
function readSpinnerConfig() {
|
|
7097
|
-
const cfg = readJson(
|
|
7217
|
+
const cfg = readJson(CONFIG_FILE3, {});
|
|
7098
7218
|
const spinner = cfg && typeof cfg.spinner === "object" ? cfg.spinner : {};
|
|
7099
7219
|
const merged = { ...SPINNER_DEFAULTS, ...spinner };
|
|
7100
7220
|
if (merged.mode !== "append" && merged.mode !== "replace") merged.mode = SPINNER_DEFAULTS.mode;
|
|
@@ -7174,10 +7294,18 @@ function buildContextVerbs(topMatches, sessionTags) {
|
|
|
7174
7294
|
if (hasBounty) headers.push(`\u2726 Roles + \u{1F48E} paid bounties in your stack \u2014 link below`);
|
|
7175
7295
|
return headers;
|
|
7176
7296
|
}
|
|
7297
|
+
function buildPeerLine(topPeers) {
|
|
7298
|
+
const n = (Array.isArray(topPeers) ? topPeers : []).filter(Boolean).length;
|
|
7299
|
+
if (n < 1) return null;
|
|
7300
|
+
return n === 1 ? `\u25C6 1 builder matches what you're building \xB7 terminalhire devs` : `\u25C6 ${n} builders match what you're building \xB7 terminalhire devs`;
|
|
7301
|
+
}
|
|
7177
7302
|
function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
7178
|
-
const { sessionTags, frequency = "always" } = opts;
|
|
7303
|
+
const { sessionTags, frequency = "always", topPeers } = opts;
|
|
7179
7304
|
const ranked = rankBySessionTags(topMatches, sessionTags);
|
|
7180
|
-
if (!Array.isArray(ranked) || ranked.length === 0)
|
|
7305
|
+
if (!Array.isArray(ranked) || ranked.length === 0) {
|
|
7306
|
+
const peerLine = buildPeerLine(topPeers);
|
|
7307
|
+
return peerLine ? [peerLine] : [];
|
|
7308
|
+
}
|
|
7181
7309
|
const headers = buildContextVerbs(ranked, sessionTags);
|
|
7182
7310
|
const cap = Math.max(1, verbCountForFrequency(frequency, headers.length));
|
|
7183
7311
|
return [...headers.slice(0, cap), ctaVerb()];
|
|
@@ -7335,14 +7463,14 @@ function clearSpinnerTips() {
|
|
|
7335
7463
|
}
|
|
7336
7464
|
return { cleared: true };
|
|
7337
7465
|
}
|
|
7338
|
-
var TH_DIR, CLAUDE_SETTINGS,
|
|
7466
|
+
var TH_DIR, CLAUDE_SETTINGS, CONFIG_FILE3, SPINNER_STATE_FILE, SPINNER_DEFAULTS, VERB_INTROS;
|
|
7339
7467
|
var init_spinner = __esm({
|
|
7340
7468
|
"bin/spinner.js"() {
|
|
7341
7469
|
"use strict";
|
|
7342
|
-
TH_DIR = process.env["TERMINALHIRE_DIR"] ||
|
|
7343
|
-
CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
7344
|
-
|
|
7345
|
-
SPINNER_STATE_FILE =
|
|
7470
|
+
TH_DIR = process.env["TERMINALHIRE_DIR"] || join14(homedir12(), ".terminalhire");
|
|
7471
|
+
CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join14(homedir12(), ".claude", "settings.json");
|
|
7472
|
+
CONFIG_FILE3 = join14(TH_DIR, "config.json");
|
|
7473
|
+
SPINNER_STATE_FILE = join14(TH_DIR, "spinner-state.json");
|
|
7346
7474
|
SPINNER_DEFAULTS = { enabled: false, mode: "append", max: 6, frequency: "sometimes" };
|
|
7347
7475
|
VERB_INTROS = ["Matched:", "You\u2019d fit:", "Worth a look:", "On your radar:", "Fits your stack:"];
|
|
7348
7476
|
}
|
|
@@ -7360,12 +7488,12 @@ import {
|
|
|
7360
7488
|
existsSync as existsSync9,
|
|
7361
7489
|
mkdirSync as mkdirSync11
|
|
7362
7490
|
} from "fs";
|
|
7363
|
-
import { join as
|
|
7364
|
-
import { homedir as
|
|
7365
|
-
import { createInterface as
|
|
7491
|
+
import { join as join15 } from "path";
|
|
7492
|
+
import { homedir as homedir13 } from "os";
|
|
7493
|
+
import { createInterface as createInterface8 } from "readline";
|
|
7366
7494
|
function readConfig2() {
|
|
7367
7495
|
try {
|
|
7368
|
-
return existsSync9(
|
|
7496
|
+
return existsSync9(CONFIG_FILE4) ? JSON.parse(readFileSync14(CONFIG_FILE4, "utf8")) : {};
|
|
7369
7497
|
} catch {
|
|
7370
7498
|
return {};
|
|
7371
7499
|
}
|
|
@@ -7373,7 +7501,7 @@ function readConfig2() {
|
|
|
7373
7501
|
function writeConfig2(patch) {
|
|
7374
7502
|
mkdirSync11(TH_DIR2, { recursive: true });
|
|
7375
7503
|
const merged = { ...readConfig2(), ...patch };
|
|
7376
|
-
writeFileSync11(
|
|
7504
|
+
writeFileSync11(CONFIG_FILE4, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
7377
7505
|
}
|
|
7378
7506
|
function backupSettings() {
|
|
7379
7507
|
if (!existsSync9(SETTINGS_PATH)) return null;
|
|
@@ -7383,7 +7511,7 @@ function backupSettings() {
|
|
|
7383
7511
|
return backupPath;
|
|
7384
7512
|
}
|
|
7385
7513
|
function ask(question) {
|
|
7386
|
-
const rl =
|
|
7514
|
+
const rl = createInterface8({ input: process.stdin, output: process.stdout });
|
|
7387
7515
|
return new Promise((res) => {
|
|
7388
7516
|
rl.question(question, (answer) => {
|
|
7389
7517
|
rl.close();
|
|
@@ -7531,15 +7659,15 @@ async function run12() {
|
|
|
7531
7659
|
console.error("Usage: terminalhire spinner --on | --off | --show | --mode <append|replace> | --max N | --frequency <always|sometimes|rare>");
|
|
7532
7660
|
process.exit(1);
|
|
7533
7661
|
}
|
|
7534
|
-
var TH_DIR2,
|
|
7662
|
+
var TH_DIR2, CONFIG_FILE4, SETTINGS_PATH, CACHE_FILE;
|
|
7535
7663
|
var init_jpi_spinner = __esm({
|
|
7536
7664
|
"bin/jpi-spinner.js"() {
|
|
7537
7665
|
"use strict";
|
|
7538
7666
|
init_spinner();
|
|
7539
|
-
TH_DIR2 = process.env["TERMINALHIRE_DIR"] ||
|
|
7540
|
-
|
|
7541
|
-
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
7542
|
-
CACHE_FILE =
|
|
7667
|
+
TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join15(homedir13(), ".terminalhire");
|
|
7668
|
+
CONFIG_FILE4 = join15(TH_DIR2, "config.json");
|
|
7669
|
+
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join15(homedir13(), ".claude", "settings.json");
|
|
7670
|
+
CACHE_FILE = join15(TH_DIR2, "index-cache.json");
|
|
7543
7671
|
}
|
|
7544
7672
|
});
|
|
7545
7673
|
|
|
@@ -7549,11 +7677,11 @@ __export(jpi_sync_exports, {
|
|
|
7549
7677
|
run: () => run13
|
|
7550
7678
|
});
|
|
7551
7679
|
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, existsSync as existsSync10, rmSync as rmSync2 } from "fs";
|
|
7552
|
-
import { join as
|
|
7553
|
-
import { homedir as
|
|
7554
|
-
import { createInterface as
|
|
7680
|
+
import { join as join16 } from "path";
|
|
7681
|
+
import { homedir as homedir14, hostname as osHostname } from "os";
|
|
7682
|
+
import { createInterface as createInterface9 } from "readline";
|
|
7555
7683
|
function ask2(question) {
|
|
7556
|
-
const rl =
|
|
7684
|
+
const rl = createInterface9({ input: process.stdin, output: process.stdout });
|
|
7557
7685
|
return new Promise((res) => {
|
|
7558
7686
|
rl.question(question, (answer) => {
|
|
7559
7687
|
rl.close();
|
|
@@ -7636,7 +7764,7 @@ async function runPush() {
|
|
|
7636
7764
|
const fields = buildConsentFields(profile);
|
|
7637
7765
|
renderPreview(fields);
|
|
7638
7766
|
await new Promise((resolve2) => {
|
|
7639
|
-
const rl =
|
|
7767
|
+
const rl = createInterface9({ input: process.stdin, output: process.stdout });
|
|
7640
7768
|
rl.question(
|
|
7641
7769
|
" Press Enter to open your browser to authorize + consent (or Ctrl-C to cancel)... ",
|
|
7642
7770
|
() => {
|
|
@@ -7834,7 +7962,7 @@ async function runDelete() {
|
|
|
7834
7962
|
console.log("\n Requesting deletion...");
|
|
7835
7963
|
let res;
|
|
7836
7964
|
try {
|
|
7837
|
-
res = await fetch(`${
|
|
7965
|
+
res = await fetch(`${API_URL5}/api/profile-sync`, {
|
|
7838
7966
|
method: "DELETE",
|
|
7839
7967
|
headers: { "Content-Type": "application/json" },
|
|
7840
7968
|
body: JSON.stringify({ consentToken, login, deleteToken }),
|
|
@@ -7884,14 +8012,14 @@ async function run13() {
|
|
|
7884
8012
|
console.log(" This is NOT required to use terminalhire.");
|
|
7885
8013
|
console.log("");
|
|
7886
8014
|
}
|
|
7887
|
-
var TH_DIR3, TIER1_MARKER,
|
|
8015
|
+
var TH_DIR3, TIER1_MARKER, API_URL5, SYNC_BASE, POLL_INTERVAL_MS, POLL_TIMEOUT_MS, CONSENT_VERSION;
|
|
7888
8016
|
var init_jpi_sync = __esm({
|
|
7889
8017
|
"bin/jpi-sync.js"() {
|
|
7890
8018
|
"use strict";
|
|
7891
8019
|
init_open_url();
|
|
7892
|
-
TH_DIR3 = process.env["TERMINALHIRE_DIR"] ||
|
|
7893
|
-
TIER1_MARKER =
|
|
7894
|
-
|
|
8020
|
+
TH_DIR3 = process.env["TERMINALHIRE_DIR"] || join16(homedir14(), ".terminalhire");
|
|
8021
|
+
TIER1_MARKER = join16(TH_DIR3, "tier1.json");
|
|
8022
|
+
API_URL5 = process.env["TERMINALHIRE_API_URL"] || process.env["JPI_API_URL"] || "https://terminalhire.com";
|
|
7895
8023
|
SYNC_BASE = "https://www.terminalhire.com";
|
|
7896
8024
|
POLL_INTERVAL_MS = 2e3;
|
|
7897
8025
|
POLL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
@@ -7905,13 +8033,13 @@ __export(jpi_init_exports, {
|
|
|
7905
8033
|
run: () => run14
|
|
7906
8034
|
});
|
|
7907
8035
|
import { existsSync as existsSync11 } from "fs";
|
|
7908
|
-
import { join as
|
|
8036
|
+
import { join as join17, resolve } from "path";
|
|
7909
8037
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7910
|
-
import { createInterface as
|
|
8038
|
+
import { createInterface as createInterface10 } from "readline";
|
|
7911
8039
|
import { spawnSync, spawn as spawn2 } from "child_process";
|
|
7912
|
-
import { homedir as
|
|
8040
|
+
import { homedir as homedir15 } from "os";
|
|
7913
8041
|
function ask3(question) {
|
|
7914
|
-
const rl =
|
|
8042
|
+
const rl = createInterface10({ input: process.stdin, output: process.stdout });
|
|
7915
8043
|
return new Promise((resolve2) => {
|
|
7916
8044
|
rl.question(question, (answer) => {
|
|
7917
8045
|
rl.close();
|
|
@@ -7920,13 +8048,13 @@ function ask3(question) {
|
|
|
7920
8048
|
});
|
|
7921
8049
|
}
|
|
7922
8050
|
function resolveScript(name) {
|
|
7923
|
-
const distPath = resolve(
|
|
7924
|
-
const legacyPath = resolve(
|
|
8051
|
+
const distPath = resolve(join17(__dirname2, "..", "..", "dist", "bin", `${name}.js`));
|
|
8052
|
+
const legacyPath = resolve(join17(__dirname2, `${name}.js`));
|
|
7925
8053
|
return existsSync11(distPath) ? distPath : legacyPath;
|
|
7926
8054
|
}
|
|
7927
8055
|
function resolveInstallJs() {
|
|
7928
|
-
const fromDist = resolve(
|
|
7929
|
-
const fromBin = resolve(
|
|
8056
|
+
const fromDist = resolve(join17(__dirname2, "..", "..", "install.js"));
|
|
8057
|
+
const fromBin = resolve(join17(__dirname2, "..", "install.js"));
|
|
7930
8058
|
if (existsSync11(fromDist)) return fromDist;
|
|
7931
8059
|
if (existsSync11(fromBin)) return fromBin;
|
|
7932
8060
|
return fromBin;
|
|
@@ -8037,14 +8165,14 @@ __export(jpi_refresh_exports, {
|
|
|
8037
8165
|
run: () => run15
|
|
8038
8166
|
});
|
|
8039
8167
|
import { readFileSync as readFileSync16, writeFileSync as writeFileSync13, existsSync as existsSync12, mkdirSync as mkdirSync13 } from "fs";
|
|
8040
|
-
import { join as
|
|
8041
|
-
import { homedir as
|
|
8168
|
+
import { join as join18 } from "path";
|
|
8169
|
+
import { homedir as homedir16 } from "os";
|
|
8042
8170
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
8043
8171
|
async function run15() {
|
|
8044
8172
|
try {
|
|
8045
8173
|
let index;
|
|
8046
8174
|
try {
|
|
8047
|
-
const res = await fetch(`${
|
|
8175
|
+
const res = await fetch(`${API_URL6}/api/index`, {
|
|
8048
8176
|
signal: AbortSignal.timeout(15e3),
|
|
8049
8177
|
headers: { "Accept": "application/json" }
|
|
8050
8178
|
});
|
|
@@ -8092,12 +8220,51 @@ async function run15() {
|
|
|
8092
8220
|
}
|
|
8093
8221
|
} catch {
|
|
8094
8222
|
}
|
|
8095
|
-
|
|
8223
|
+
let topPeers = [];
|
|
8224
|
+
if (isPeerConnectEnabled()) try {
|
|
8225
|
+
const { match: match2, STRONG_MATCH_THRESHOLD: STRONG_MATCH_THRESHOLD2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
8226
|
+
const { extractFingerprint: extractFingerprint2 } = await Promise.resolve().then(() => (init_signal(), signal_exports));
|
|
8227
|
+
const sig = extractFingerprint2(process.cwd());
|
|
8228
|
+
const project = readProject();
|
|
8229
|
+
const skillTags = [
|
|
8230
|
+
.../* @__PURE__ */ new Set([
|
|
8231
|
+
...Array.isArray(sig?.skillTags) ? sig.skillTags : [],
|
|
8232
|
+
...project && Array.isArray(project.skillTags) ? project.skillTags : []
|
|
8233
|
+
])
|
|
8234
|
+
];
|
|
8235
|
+
if (skillTags.length > 0) {
|
|
8236
|
+
const fp = { skillTags, prefs: project?.prefs ?? {} };
|
|
8237
|
+
const directory = await fetchDirectory({ quiet: true });
|
|
8238
|
+
const cards = directory?.cards ?? [];
|
|
8239
|
+
if (cards.length > 0) {
|
|
8240
|
+
const peerResults = match2(fp, cards, cards.length).filter(
|
|
8241
|
+
(r) => r.score >= STRONG_MATCH_THRESHOLD2
|
|
8242
|
+
);
|
|
8243
|
+
topPeers = peerResults.map((r) => ({
|
|
8244
|
+
login: r.job.company,
|
|
8245
|
+
// public handle (person login / project owner)
|
|
8246
|
+
title: r.job.title,
|
|
8247
|
+
// public card title (name or project title)
|
|
8248
|
+
score: r.score,
|
|
8249
|
+
matchedTags: r.matchedTags,
|
|
8250
|
+
source: r.job.source,
|
|
8251
|
+
// 'person' | 'project'
|
|
8252
|
+
url: r.job.url,
|
|
8253
|
+
// public /r/<login> credential link
|
|
8254
|
+
id: r.job.id
|
|
8255
|
+
}));
|
|
8256
|
+
await reportMatched(peerResults);
|
|
8257
|
+
}
|
|
8258
|
+
}
|
|
8259
|
+
} catch {
|
|
8260
|
+
}
|
|
8261
|
+
mkdirSync13(TERMINALHIRE_DIR11, { recursive: true });
|
|
8096
8262
|
const cacheEntry = {
|
|
8097
8263
|
ts: Date.now(),
|
|
8098
8264
|
index,
|
|
8099
8265
|
matchCount,
|
|
8100
|
-
topMatches
|
|
8266
|
+
topMatches,
|
|
8267
|
+
topPeers
|
|
8101
8268
|
};
|
|
8102
8269
|
writeFileSync13(INDEX_CACHE_FILE4, JSON.stringify(cacheEntry), "utf8");
|
|
8103
8270
|
try {
|
|
@@ -8123,10 +8290,10 @@ async function run15() {
|
|
|
8123
8290
|
} catch {
|
|
8124
8291
|
}
|
|
8125
8292
|
const ranked = rankBySessionTags2(topMatches, sessionTags);
|
|
8126
|
-
const verbs = buildSpinnerPool2(ranked, sc.max, { sessionTags, frequency: sc.frequency });
|
|
8293
|
+
const verbs = buildSpinnerPool2(ranked, sc.max, { sessionTags, frequency: sc.frequency, topPeers });
|
|
8127
8294
|
if (verbs.length > 0) applySpinnerVerbs2(verbs, sc.mode);
|
|
8128
8295
|
else clearSpinnerVerbs2();
|
|
8129
|
-
const tips = buildTips2(ranked,
|
|
8296
|
+
const tips = buildTips2(ranked, API_URL6, 8);
|
|
8130
8297
|
if (tips.length > 0) applySpinnerTips2(tips);
|
|
8131
8298
|
else clearSpinnerTips2();
|
|
8132
8299
|
} else {
|
|
@@ -8143,14 +8310,16 @@ async function run15() {
|
|
|
8143
8310
|
process.exit(1);
|
|
8144
8311
|
}
|
|
8145
8312
|
}
|
|
8146
|
-
var __dirname3,
|
|
8313
|
+
var __dirname3, TERMINALHIRE_DIR11, INDEX_CACHE_FILE4, API_URL6;
|
|
8147
8314
|
var init_jpi_refresh = __esm({
|
|
8148
8315
|
"bin/jpi-refresh.js"() {
|
|
8149
8316
|
"use strict";
|
|
8317
|
+
init_directory2();
|
|
8318
|
+
init_config();
|
|
8150
8319
|
__dirname3 = fileURLToPath4(new URL(".", import.meta.url));
|
|
8151
|
-
|
|
8152
|
-
INDEX_CACHE_FILE4 =
|
|
8153
|
-
|
|
8320
|
+
TERMINALHIRE_DIR11 = join18(homedir16(), ".terminalhire");
|
|
8321
|
+
INDEX_CACHE_FILE4 = join18(TERMINALHIRE_DIR11, "index-cache.json");
|
|
8322
|
+
API_URL6 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
8154
8323
|
}
|
|
8155
8324
|
});
|
|
8156
8325
|
|
|
@@ -8160,8 +8329,8 @@ __export(jpi_save_exports, {
|
|
|
8160
8329
|
run: () => run16
|
|
8161
8330
|
});
|
|
8162
8331
|
import { readFileSync as readFileSync17, existsSync as existsSync13 } from "fs";
|
|
8163
|
-
import { join as
|
|
8164
|
-
import { homedir as
|
|
8332
|
+
import { join as join19 } from "path";
|
|
8333
|
+
import { homedir as homedir17 } from "os";
|
|
8165
8334
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
8166
8335
|
function findJobInCache(jobId) {
|
|
8167
8336
|
try {
|
|
@@ -8254,27 +8423,27 @@ async function run16() {
|
|
|
8254
8423
|
process.exit(1);
|
|
8255
8424
|
}
|
|
8256
8425
|
}
|
|
8257
|
-
var __dirname4,
|
|
8426
|
+
var __dirname4, TERMINALHIRE_DIR12, INDEX_CACHE_FILE5;
|
|
8258
8427
|
var init_jpi_save = __esm({
|
|
8259
8428
|
"bin/jpi-save.js"() {
|
|
8260
8429
|
"use strict";
|
|
8261
8430
|
__dirname4 = fileURLToPath5(new URL(".", import.meta.url));
|
|
8262
|
-
|
|
8263
|
-
INDEX_CACHE_FILE5 =
|
|
8431
|
+
TERMINALHIRE_DIR12 = join19(homedir17(), ".terminalhire");
|
|
8432
|
+
INDEX_CACHE_FILE5 = join19(TERMINALHIRE_DIR12, "index-cache.json");
|
|
8264
8433
|
}
|
|
8265
8434
|
});
|
|
8266
8435
|
|
|
8267
8436
|
// bin/jpi-dispatch.js
|
|
8268
8437
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
8269
|
-
import { join as
|
|
8438
|
+
import { join as join20, dirname as dirname2 } from "path";
|
|
8270
8439
|
import { existsSync as existsSync14, readFileSync as readFileSync18 } from "fs";
|
|
8271
8440
|
import { createRequire } from "module";
|
|
8272
8441
|
var __dirname5 = fileURLToPath6(new URL(".", import.meta.url));
|
|
8273
8442
|
function readPackageVersion() {
|
|
8274
8443
|
try {
|
|
8275
8444
|
const candidates = [
|
|
8276
|
-
|
|
8277
|
-
|
|
8445
|
+
join20(__dirname5, "..", "..", "package.json"),
|
|
8446
|
+
join20(__dirname5, "..", "package.json")
|
|
8278
8447
|
];
|
|
8279
8448
|
for (const p of candidates) {
|
|
8280
8449
|
if (existsSync14(p)) {
|
|
@@ -8289,7 +8458,7 @@ function readPackageVersion() {
|
|
|
8289
8458
|
var firstArg = process.argv[2];
|
|
8290
8459
|
if (!firstArg && !process.stdin.isTTY) {
|
|
8291
8460
|
const { default: childProcess } = await import("child_process");
|
|
8292
|
-
const nudgeScript =
|
|
8461
|
+
const nudgeScript = join20(__dirname5, "jpi.js");
|
|
8293
8462
|
const child = childProcess.spawnSync(process.execPath, [nudgeScript], {
|
|
8294
8463
|
stdio: ["inherit", "inherit", "inherit"]
|
|
8295
8464
|
});
|
|
@@ -8327,6 +8496,7 @@ if (!firstArg || firstArg === "help" || firstArg === "--help" || firstArg === "-
|
|
|
8327
8496
|
console.log(" terminalhire config --nudge session Nudge at most once per session (default)");
|
|
8328
8497
|
console.log(" terminalhire config --nudge always Nudge every statusLine render");
|
|
8329
8498
|
console.log(" terminalhire config --nudge every:N Nudge every Nth render");
|
|
8499
|
+
console.log(" terminalhire config --connect on|off Opt in/out of ambient peer & founder surfacing (default off)");
|
|
8330
8500
|
console.log(" terminalhire config --show Print current config");
|
|
8331
8501
|
console.log(" terminalhire spinner --show Job matches in the spinner line while Claude works");
|
|
8332
8502
|
console.log(" terminalhire spinner --off Turn the spinner job surface off (restores your spinner)");
|