terminalhire 0.9.2 → 0.10.1
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-chat-read.js +2 -1
- package/dist/bin/jpi-chat.js +2 -1
- package/dist/bin/jpi-config.js +2 -1
- package/dist/bin/jpi-dispatch.js +493 -264
- package/dist/bin/jpi-intro.js +72 -14
- package/dist/bin/jpi-link.js +2 -0
- package/dist/bin/jpi-login.js +2 -1
- package/dist/bin/jpi-refresh.js +203 -63
- package/dist/bin/jpi-spinner.js +11 -2
- package/dist/bin/jpi.js +23 -4
- package/dist/bin/peer-connect-prompt.js +2 -1
- package/dist/bin/spinner.js +12 -2
- package/dist/bin/version-nudge.js +65 -0
- package/dist/src/config.js +6 -1
- package/dist/src/intro.js +71 -13
- package/dist/src/link.js +2 -0
- package/package.json +1 -1
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -9,6 +9,79 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// bin/version-nudge.js
|
|
13
|
+
var version_nudge_exports = {};
|
|
14
|
+
__export(version_nudge_exports, {
|
|
15
|
+
buildStaleNudge: () => buildStaleNudge,
|
|
16
|
+
cachedStaleNudge: () => cachedStaleNudge,
|
|
17
|
+
compareVersions: () => compareVersions,
|
|
18
|
+
parseVersion: () => parseVersion,
|
|
19
|
+
readLatestVersionFromCache: () => readLatestVersionFromCache,
|
|
20
|
+
readLocalVersion: () => readLocalVersion
|
|
21
|
+
});
|
|
22
|
+
import { readFileSync, existsSync } from "fs";
|
|
23
|
+
import { join } from "path";
|
|
24
|
+
import { homedir } from "os";
|
|
25
|
+
import { fileURLToPath } from "url";
|
|
26
|
+
function parseVersion(v) {
|
|
27
|
+
if (typeof v !== "string") return null;
|
|
28
|
+
const m = v.trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
29
|
+
if (!m) return null;
|
|
30
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
31
|
+
}
|
|
32
|
+
function compareVersions(a, b) {
|
|
33
|
+
const pa = parseVersion(a);
|
|
34
|
+
const pb = parseVersion(b);
|
|
35
|
+
if (!pa || !pb) return null;
|
|
36
|
+
for (let i = 0; i < 3; i++) {
|
|
37
|
+
if (pa[i] < pb[i]) return -1;
|
|
38
|
+
if (pa[i] > pb[i]) return 1;
|
|
39
|
+
}
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
function buildStaleNudge(local, latest) {
|
|
43
|
+
if (compareVersions(local, latest) !== -1) return null;
|
|
44
|
+
return `your terminalhire CLI is behind (${local} \u2192 ${latest}) \u2014 npm i -g terminalhire@latest`;
|
|
45
|
+
}
|
|
46
|
+
function readLocalVersion() {
|
|
47
|
+
try {
|
|
48
|
+
const candidates = [
|
|
49
|
+
join(__dirname, "..", "..", "package.json"),
|
|
50
|
+
join(__dirname, "..", "package.json")
|
|
51
|
+
];
|
|
52
|
+
for (const p of candidates) {
|
|
53
|
+
if (existsSync(p)) {
|
|
54
|
+
const pkg = JSON.parse(readFileSync(p, "utf8"));
|
|
55
|
+
if (pkg.version) return pkg.version;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
function readLatestVersionFromCache() {
|
|
63
|
+
try {
|
|
64
|
+
const cache = JSON.parse(readFileSync(INDEX_CACHE_FILE, "utf8"));
|
|
65
|
+
const v = cache?.index?.cliVersion;
|
|
66
|
+
return typeof v === "string" ? v : null;
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function cachedStaleNudge(localVersion) {
|
|
72
|
+
const local = localVersion ?? readLocalVersion();
|
|
73
|
+
if (!local) return null;
|
|
74
|
+
return buildStaleNudge(local, readLatestVersionFromCache());
|
|
75
|
+
}
|
|
76
|
+
var __dirname, INDEX_CACHE_FILE;
|
|
77
|
+
var init_version_nudge = __esm({
|
|
78
|
+
"bin/version-nudge.js"() {
|
|
79
|
+
"use strict";
|
|
80
|
+
__dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
81
|
+
INDEX_CACHE_FILE = join(homedir(), ".terminalhire", "index-cache.json");
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
12
85
|
// src/open-url.js
|
|
13
86
|
var open_url_exports = {};
|
|
14
87
|
__export(open_url_exports, {
|
|
@@ -62,14 +135,14 @@ import {
|
|
|
62
135
|
randomBytes
|
|
63
136
|
} from "crypto";
|
|
64
137
|
import {
|
|
65
|
-
readFileSync,
|
|
138
|
+
readFileSync as readFileSync2,
|
|
66
139
|
writeFileSync,
|
|
67
140
|
mkdirSync,
|
|
68
|
-
existsSync,
|
|
141
|
+
existsSync as existsSync2,
|
|
69
142
|
rmSync
|
|
70
143
|
} from "fs";
|
|
71
|
-
import { join } from "path";
|
|
72
|
-
import { homedir } from "os";
|
|
144
|
+
import { join as join2 } from "path";
|
|
145
|
+
import { homedir as homedir2 } from "os";
|
|
73
146
|
async function loadKey() {
|
|
74
147
|
try {
|
|
75
148
|
const kt = await import("keytar");
|
|
@@ -81,8 +154,8 @@ async function loadKey() {
|
|
|
81
154
|
} catch {
|
|
82
155
|
}
|
|
83
156
|
mkdirSync(TERMINALHIRE_DIR, { recursive: true });
|
|
84
|
-
if (
|
|
85
|
-
return Buffer.from(
|
|
157
|
+
if (existsSync2(KEY_FILE)) {
|
|
158
|
+
return Buffer.from(readFileSync2(KEY_FILE, "utf8").trim(), "hex");
|
|
86
159
|
}
|
|
87
160
|
const key = randomBytes(KEY_BYTES);
|
|
88
161
|
writeFileSync(KEY_FILE, key.toString("hex"), { mode: 384, encoding: "utf8" });
|
|
@@ -105,10 +178,10 @@ function decrypt(blob, key) {
|
|
|
105
178
|
return plain.toString("utf8");
|
|
106
179
|
}
|
|
107
180
|
async function readGitHubToken() {
|
|
108
|
-
if (!
|
|
181
|
+
if (!existsSync2(TOKEN_FILE)) return void 0;
|
|
109
182
|
try {
|
|
110
183
|
const key = await loadKey();
|
|
111
|
-
const raw =
|
|
184
|
+
const raw = readFileSync2(TOKEN_FILE, "utf8");
|
|
112
185
|
const blob = JSON.parse(raw);
|
|
113
186
|
return decrypt(blob, key);
|
|
114
187
|
} catch {
|
|
@@ -128,7 +201,7 @@ async function deleteGitHubToken() {
|
|
|
128
201
|
}
|
|
129
202
|
}
|
|
130
203
|
async function hasGitHubToken() {
|
|
131
|
-
return
|
|
204
|
+
return existsSync2(TOKEN_FILE);
|
|
132
205
|
}
|
|
133
206
|
async function runDeviceFlow() {
|
|
134
207
|
if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
|
|
@@ -244,9 +317,9 @@ var TERMINALHIRE_DIR, TOKEN_FILE, KEY_FILE, ALGO, KEY_BYTES, IV_BYTES, GITHUB_SC
|
|
|
244
317
|
var init_github_auth = __esm({
|
|
245
318
|
"src/github-auth.ts"() {
|
|
246
319
|
"use strict";
|
|
247
|
-
TERMINALHIRE_DIR =
|
|
248
|
-
TOKEN_FILE =
|
|
249
|
-
KEY_FILE =
|
|
320
|
+
TERMINALHIRE_DIR = join2(homedir2(), ".terminalhire");
|
|
321
|
+
TOKEN_FILE = join2(TERMINALHIRE_DIR, "github-token.enc");
|
|
322
|
+
KEY_FILE = join2(TERMINALHIRE_DIR, "key");
|
|
250
323
|
ALGO = "aes-256-gcm";
|
|
251
324
|
KEY_BYTES = 32;
|
|
252
325
|
IV_BYTES = 12;
|
|
@@ -1943,14 +2016,14 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
1943
2016
|
if (items.length === 0) return results;
|
|
1944
2017
|
const workers = Math.max(1, Math.min(Math.floor(limit) || 1, items.length));
|
|
1945
2018
|
let next = 0;
|
|
1946
|
-
async function
|
|
2019
|
+
async function run20() {
|
|
1947
2020
|
for (; ; ) {
|
|
1948
2021
|
const i = next++;
|
|
1949
2022
|
if (i >= items.length) return;
|
|
1950
2023
|
results[i] = await fn(items[i], i);
|
|
1951
2024
|
}
|
|
1952
2025
|
}
|
|
1953
|
-
await Promise.all(Array.from({ length: workers },
|
|
2026
|
+
await Promise.all(Array.from({ length: workers }, run20));
|
|
1954
2027
|
return results;
|
|
1955
2028
|
}
|
|
1956
2029
|
var init_concurrency = __esm({
|
|
@@ -2793,21 +2866,21 @@ var init_feeds = __esm({
|
|
|
2793
2866
|
});
|
|
2794
2867
|
|
|
2795
2868
|
// ../../packages/core/src/partners.ts
|
|
2796
|
-
import { readFileSync as
|
|
2797
|
-
import { join as
|
|
2798
|
-
import { fileURLToPath } from "url";
|
|
2869
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
2870
|
+
import { join as join3 } from "path";
|
|
2871
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2799
2872
|
function resolveDataPath() {
|
|
2800
2873
|
try {
|
|
2801
|
-
const dir =
|
|
2802
|
-
return
|
|
2874
|
+
const dir = fileURLToPath2(new URL("../../../data", import.meta.url));
|
|
2875
|
+
return join3(dir, "partner-roles.json");
|
|
2803
2876
|
} catch {
|
|
2804
|
-
return
|
|
2877
|
+
return join3(process.cwd(), "data", "partner-roles.json");
|
|
2805
2878
|
}
|
|
2806
2879
|
}
|
|
2807
2880
|
function loadPartnerRoles() {
|
|
2808
2881
|
const filePath = resolveDataPath();
|
|
2809
2882
|
try {
|
|
2810
|
-
const raw =
|
|
2883
|
+
const raw = readFileSync3(filePath, "utf-8");
|
|
2811
2884
|
const parsed = JSON.parse(raw);
|
|
2812
2885
|
if (!Array.isArray(parsed)) {
|
|
2813
2886
|
console.warn("[partners] partner-roles.json is not an array \u2014 skipping");
|
|
@@ -6208,13 +6281,13 @@ import {
|
|
|
6208
6281
|
randomBytes as randomBytes4
|
|
6209
6282
|
} from "crypto";
|
|
6210
6283
|
import {
|
|
6211
|
-
readFileSync as
|
|
6284
|
+
readFileSync as readFileSync4,
|
|
6212
6285
|
writeFileSync as writeFileSync2,
|
|
6213
6286
|
mkdirSync as mkdirSync2,
|
|
6214
|
-
existsSync as
|
|
6287
|
+
existsSync as existsSync3
|
|
6215
6288
|
} from "fs";
|
|
6216
|
-
import { join as
|
|
6217
|
-
import { homedir as
|
|
6289
|
+
import { join as join4 } from "path";
|
|
6290
|
+
import { homedir as homedir3 } from "os";
|
|
6218
6291
|
async function loadKey2() {
|
|
6219
6292
|
try {
|
|
6220
6293
|
const kt = await import("keytar");
|
|
@@ -6228,8 +6301,8 @@ async function loadKey2() {
|
|
|
6228
6301
|
} catch {
|
|
6229
6302
|
}
|
|
6230
6303
|
mkdirSync2(TERMINALHIRE_DIR2, { recursive: true });
|
|
6231
|
-
if (
|
|
6232
|
-
return Buffer.from(
|
|
6304
|
+
if (existsSync3(KEY_FILE2)) {
|
|
6305
|
+
return Buffer.from(readFileSync4(KEY_FILE2, "utf8").trim(), "hex");
|
|
6233
6306
|
}
|
|
6234
6307
|
const key = randomBytes4(KEY_BYTES2);
|
|
6235
6308
|
writeFileSync2(KEY_FILE2, key.toString("hex"), { mode: 384, encoding: "utf8" });
|
|
@@ -6290,10 +6363,10 @@ function migrateTagWeights(profile) {
|
|
|
6290
6363
|
}
|
|
6291
6364
|
}
|
|
6292
6365
|
async function readProfile() {
|
|
6293
|
-
if (!
|
|
6366
|
+
if (!existsSync3(PROFILE_FILE)) return blankProfile();
|
|
6294
6367
|
try {
|
|
6295
6368
|
const key = await loadKey2();
|
|
6296
|
-
const raw =
|
|
6369
|
+
const raw = readFileSync4(PROFILE_FILE, "utf8");
|
|
6297
6370
|
const blob = JSON.parse(raw);
|
|
6298
6371
|
const plaintext = decrypt2(blob, key);
|
|
6299
6372
|
const parsed = JSON.parse(plaintext);
|
|
@@ -6398,9 +6471,9 @@ var init_profile = __esm({
|
|
|
6398
6471
|
"src/profile.ts"() {
|
|
6399
6472
|
"use strict";
|
|
6400
6473
|
init_src();
|
|
6401
|
-
TERMINALHIRE_DIR2 =
|
|
6402
|
-
PROFILE_FILE =
|
|
6403
|
-
KEY_FILE2 =
|
|
6474
|
+
TERMINALHIRE_DIR2 = join4(homedir3(), ".terminalhire");
|
|
6475
|
+
PROFILE_FILE = join4(TERMINALHIRE_DIR2, "profile.enc");
|
|
6476
|
+
KEY_FILE2 = join4(TERMINALHIRE_DIR2, "key");
|
|
6404
6477
|
ALGO2 = "aes-256-gcm";
|
|
6405
6478
|
KEY_BYTES2 = 32;
|
|
6406
6479
|
IV_BYTES2 = 12;
|
|
@@ -6429,13 +6502,13 @@ var init_profile = __esm({
|
|
|
6429
6502
|
});
|
|
6430
6503
|
|
|
6431
6504
|
// src/config.ts
|
|
6432
|
-
import { readFileSync as
|
|
6433
|
-
import { join as
|
|
6434
|
-
import { homedir as
|
|
6505
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
|
|
6506
|
+
import { join as join5 } from "path";
|
|
6507
|
+
import { homedir as homedir4 } from "os";
|
|
6435
6508
|
function readConfig() {
|
|
6436
6509
|
try {
|
|
6437
|
-
if (!
|
|
6438
|
-
const raw =
|
|
6510
|
+
if (!existsSync4(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
|
|
6511
|
+
const raw = readFileSync5(CONFIG_FILE, "utf8");
|
|
6439
6512
|
const parsed = JSON.parse(raw);
|
|
6440
6513
|
return { ...DEFAULT_CONFIG, ...parsed };
|
|
6441
6514
|
} catch {
|
|
@@ -6451,18 +6524,22 @@ function writeConfig(config) {
|
|
|
6451
6524
|
function isPeerConnectEnabled() {
|
|
6452
6525
|
return readConfig().peerConnect === true;
|
|
6453
6526
|
}
|
|
6527
|
+
function isInboundNudgeMuted() {
|
|
6528
|
+
return readConfig().inboundNudgeMuted === true;
|
|
6529
|
+
}
|
|
6454
6530
|
var TERMINALHIRE_DIR3, CONFIG_FILE, DEFAULT_CONFIG;
|
|
6455
6531
|
var init_config = __esm({
|
|
6456
6532
|
"src/config.ts"() {
|
|
6457
6533
|
"use strict";
|
|
6458
|
-
TERMINALHIRE_DIR3 =
|
|
6459
|
-
CONFIG_FILE =
|
|
6534
|
+
TERMINALHIRE_DIR3 = join5(homedir4(), ".terminalhire");
|
|
6535
|
+
CONFIG_FILE = join5(TERMINALHIRE_DIR3, "config.json");
|
|
6460
6536
|
DEFAULT_CONFIG = {
|
|
6461
6537
|
nudge: "session",
|
|
6462
6538
|
peerConnect: false,
|
|
6463
6539
|
peerConnectPrompted: false,
|
|
6464
6540
|
resumePublishPrompted: false,
|
|
6465
|
-
chatDisclosureAck: false
|
|
6541
|
+
chatDisclosureAck: false,
|
|
6542
|
+
inboundNudgeMuted: false
|
|
6466
6543
|
};
|
|
6467
6544
|
}
|
|
6468
6545
|
});
|
|
@@ -6612,12 +6689,12 @@ async function runLogin() {
|
|
|
6612
6689
|
let ghProfile;
|
|
6613
6690
|
if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
|
|
6614
6691
|
const { createRequire: createRequire2 } = await import("module");
|
|
6615
|
-
const { fileURLToPath:
|
|
6616
|
-
const { join:
|
|
6617
|
-
const
|
|
6618
|
-
const fixturePath =
|
|
6619
|
-
const { readFileSync:
|
|
6620
|
-
ghProfile = JSON.parse(
|
|
6692
|
+
const { fileURLToPath: fileURLToPath8 } = await import("url");
|
|
6693
|
+
const { join: join26, dirname: dirname3 } = await import("path");
|
|
6694
|
+
const __dirname7 = fileURLToPath8(new URL(".", import.meta.url));
|
|
6695
|
+
const fixturePath = join26(__dirname7, "../../fixtures/github-sample.json");
|
|
6696
|
+
const { readFileSync: readFileSync24 } = await import("fs");
|
|
6697
|
+
ghProfile = JSON.parse(readFileSync24(fixturePath, "utf8"));
|
|
6621
6698
|
} else {
|
|
6622
6699
|
ghProfile = await fetchGitHubProfile2(login, token);
|
|
6623
6700
|
}
|
|
@@ -6739,14 +6816,14 @@ var jpi_jobs_exports = {};
|
|
|
6739
6816
|
__export(jpi_jobs_exports, {
|
|
6740
6817
|
run: () => run2
|
|
6741
6818
|
});
|
|
6742
|
-
import { readFileSync as
|
|
6743
|
-
import { join as
|
|
6744
|
-
import { homedir as
|
|
6819
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
|
|
6820
|
+
import { join as join6 } from "path";
|
|
6821
|
+
import { homedir as homedir5 } from "os";
|
|
6745
6822
|
import { createInterface as createInterface2 } from "readline";
|
|
6746
|
-
import { fileURLToPath as
|
|
6823
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6747
6824
|
function readIndexCache() {
|
|
6748
6825
|
try {
|
|
6749
|
-
const raw =
|
|
6826
|
+
const raw = readFileSync6(INDEX_CACHE_FILE2, "utf8");
|
|
6750
6827
|
const entry = JSON.parse(raw);
|
|
6751
6828
|
if (Date.now() - entry.ts < INDEX_TTL_MS) return entry.index;
|
|
6752
6829
|
return null;
|
|
@@ -6756,7 +6833,7 @@ function readIndexCache() {
|
|
|
6756
6833
|
}
|
|
6757
6834
|
function writeIndexCache(index) {
|
|
6758
6835
|
mkdirSync4(TERMINALHIRE_DIR4, { recursive: true });
|
|
6759
|
-
writeFileSync4(
|
|
6836
|
+
writeFileSync4(INDEX_CACHE_FILE2, JSON.stringify({ ts: Date.now(), index }), "utf8");
|
|
6760
6837
|
}
|
|
6761
6838
|
async function fetchIndex() {
|
|
6762
6839
|
const cached = readIndexCache();
|
|
@@ -6921,10 +6998,10 @@ async function run2() {
|
|
|
6921
6998
|
acceptance: profile.acceptance
|
|
6922
6999
|
});
|
|
6923
7000
|
try {
|
|
6924
|
-
const cacheRaw =
|
|
7001
|
+
const cacheRaw = readFileSync6(INDEX_CACHE_FILE2, "utf8");
|
|
6925
7002
|
const cacheEntry = JSON.parse(cacheRaw);
|
|
6926
7003
|
cacheEntry.matchCount = results.length;
|
|
6927
|
-
writeFileSync4(
|
|
7004
|
+
writeFileSync4(INDEX_CACHE_FILE2, JSON.stringify(cacheEntry), "utf8");
|
|
6928
7005
|
} catch {
|
|
6929
7006
|
}
|
|
6930
7007
|
if (results.length === 0) {
|
|
@@ -6969,13 +7046,13 @@ Open this URL to apply directly (no data shared):
|
|
|
6969
7046
|
process.exit(1);
|
|
6970
7047
|
}
|
|
6971
7048
|
}
|
|
6972
|
-
var
|
|
7049
|
+
var __dirname2, TERMINALHIRE_DIR4, INDEX_CACHE_FILE2, INDEX_TTL_MS, API_URL, DEFAULT_LIMIT, args, limitArg, LIMIT, REMOTE_ONLY, SHOW_ALL;
|
|
6973
7050
|
var init_jpi_jobs = __esm({
|
|
6974
7051
|
"bin/jpi-jobs.js"() {
|
|
6975
7052
|
"use strict";
|
|
6976
|
-
|
|
6977
|
-
TERMINALHIRE_DIR4 =
|
|
6978
|
-
|
|
7053
|
+
__dirname2 = fileURLToPath3(new URL(".", import.meta.url));
|
|
7054
|
+
TERMINALHIRE_DIR4 = join6(homedir5(), ".terminalhire");
|
|
7055
|
+
INDEX_CACHE_FILE2 = join6(TERMINALHIRE_DIR4, "index-cache.json");
|
|
6979
7056
|
INDEX_TTL_MS = 15 * 60 * 1e3;
|
|
6980
7057
|
API_URL = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
6981
7058
|
DEFAULT_LIMIT = 10;
|
|
@@ -6988,12 +7065,12 @@ var init_jpi_jobs = __esm({
|
|
|
6988
7065
|
});
|
|
6989
7066
|
|
|
6990
7067
|
// bin/directory.js
|
|
6991
|
-
import { readFileSync as
|
|
6992
|
-
import { join as
|
|
6993
|
-
import { homedir as
|
|
7068
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
7069
|
+
import { join as join7 } from "path";
|
|
7070
|
+
import { homedir as homedir6 } from "os";
|
|
6994
7071
|
function readDirectoryCache() {
|
|
6995
7072
|
try {
|
|
6996
|
-
const entry = JSON.parse(
|
|
7073
|
+
const entry = JSON.parse(readFileSync7(DIRECTORY_CACHE_FILE, "utf8"));
|
|
6997
7074
|
if (typeof entry.ts === "number" && Number.isFinite(entry.ts) && Date.now() - entry.ts < INDEX_TTL_MS2) {
|
|
6998
7075
|
return { index: entry.index, ts: entry.ts };
|
|
6999
7076
|
}
|
|
@@ -7008,7 +7085,7 @@ function writeDirectoryCache(index) {
|
|
|
7008
7085
|
}
|
|
7009
7086
|
function readProject() {
|
|
7010
7087
|
try {
|
|
7011
|
-
return JSON.parse(
|
|
7088
|
+
return JSON.parse(readFileSync7(PROJECT_FILE, "utf8"));
|
|
7012
7089
|
} catch {
|
|
7013
7090
|
return null;
|
|
7014
7091
|
}
|
|
@@ -7056,9 +7133,9 @@ var TERMINALHIRE_DIR5, DIRECTORY_CACHE_FILE, PROJECT_FILE, INDEX_TTL_MS2, API_UR
|
|
|
7056
7133
|
var init_directory2 = __esm({
|
|
7057
7134
|
"bin/directory.js"() {
|
|
7058
7135
|
"use strict";
|
|
7059
|
-
TERMINALHIRE_DIR5 =
|
|
7060
|
-
DIRECTORY_CACHE_FILE =
|
|
7061
|
-
PROJECT_FILE =
|
|
7136
|
+
TERMINALHIRE_DIR5 = join7(homedir6(), ".terminalhire");
|
|
7137
|
+
DIRECTORY_CACHE_FILE = join7(TERMINALHIRE_DIR5, "directory-cache.json");
|
|
7138
|
+
PROJECT_FILE = join7(TERMINALHIRE_DIR5, "project.json");
|
|
7062
7139
|
INDEX_TTL_MS2 = 15 * 60 * 1e3;
|
|
7063
7140
|
API_URL2 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
7064
7141
|
}
|
|
@@ -7187,13 +7264,13 @@ var jpi_project_exports = {};
|
|
|
7187
7264
|
__export(jpi_project_exports, {
|
|
7188
7265
|
run: () => run4
|
|
7189
7266
|
});
|
|
7190
|
-
import { readFileSync as
|
|
7191
|
-
import { join as
|
|
7192
|
-
import { homedir as
|
|
7267
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
7268
|
+
import { join as join8 } from "path";
|
|
7269
|
+
import { homedir as homedir7 } from "os";
|
|
7193
7270
|
import { createInterface as createInterface4 } from "readline";
|
|
7194
7271
|
function readProject2() {
|
|
7195
7272
|
try {
|
|
7196
|
-
return JSON.parse(
|
|
7273
|
+
return JSON.parse(readFileSync8(PROJECT_FILE2, "utf8"));
|
|
7197
7274
|
} catch {
|
|
7198
7275
|
return null;
|
|
7199
7276
|
}
|
|
@@ -7285,8 +7362,8 @@ var TERMINALHIRE_DIR6, PROJECT_FILE2, args3, SHOW, declarationArg;
|
|
|
7285
7362
|
var init_jpi_project = __esm({
|
|
7286
7363
|
"bin/jpi-project.js"() {
|
|
7287
7364
|
"use strict";
|
|
7288
|
-
TERMINALHIRE_DIR6 =
|
|
7289
|
-
PROJECT_FILE2 =
|
|
7365
|
+
TERMINALHIRE_DIR6 = join8(homedir7(), ".terminalhire");
|
|
7366
|
+
PROJECT_FILE2 = join8(TERMINALHIRE_DIR6, "project.json");
|
|
7290
7367
|
args3 = process.argv.slice(2);
|
|
7291
7368
|
SHOW = args3.includes("--show");
|
|
7292
7369
|
declarationArg = args3.filter((a) => !a.startsWith("--")).join(" ").trim();
|
|
@@ -7298,13 +7375,13 @@ var jpi_bounties_exports = {};
|
|
|
7298
7375
|
__export(jpi_bounties_exports, {
|
|
7299
7376
|
run: () => run5
|
|
7300
7377
|
});
|
|
7301
|
-
import { readFileSync as
|
|
7302
|
-
import { join as
|
|
7303
|
-
import { homedir as
|
|
7378
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
|
|
7379
|
+
import { join as join9 } from "path";
|
|
7380
|
+
import { homedir as homedir8 } from "os";
|
|
7304
7381
|
import { createInterface as createInterface5 } from "readline";
|
|
7305
7382
|
function readIndexCache2() {
|
|
7306
7383
|
try {
|
|
7307
|
-
const entry = JSON.parse(
|
|
7384
|
+
const entry = JSON.parse(readFileSync9(INDEX_CACHE_FILE3, "utf8"));
|
|
7308
7385
|
if (Date.now() - entry.ts < INDEX_TTL_MS3) return entry.index;
|
|
7309
7386
|
return null;
|
|
7310
7387
|
} catch {
|
|
@@ -7313,7 +7390,7 @@ function readIndexCache2() {
|
|
|
7313
7390
|
}
|
|
7314
7391
|
function writeIndexCache2(index) {
|
|
7315
7392
|
mkdirSync7(TERMINALHIRE_DIR7, { recursive: true });
|
|
7316
|
-
writeFileSync7(
|
|
7393
|
+
writeFileSync7(INDEX_CACHE_FILE3, JSON.stringify({ ts: Date.now(), index }), "utf8");
|
|
7317
7394
|
}
|
|
7318
7395
|
async function fetchIndex2() {
|
|
7319
7396
|
const cached = readIndexCache2();
|
|
@@ -7417,12 +7494,12 @@ Open this to claim/work the bounty (you go straight to the source \u2014 we neve
|
|
|
7417
7494
|
process.exit(1);
|
|
7418
7495
|
}
|
|
7419
7496
|
}
|
|
7420
|
-
var TERMINALHIRE_DIR7,
|
|
7497
|
+
var TERMINALHIRE_DIR7, INDEX_CACHE_FILE3, INDEX_TTL_MS3, API_URL4, DEFAULT_LIMIT3, args4, limitArg3, LIMIT3, PRICED_ONLY, SHOW_ALL3, WINNABLE_ONLY, EFFORT_LABEL;
|
|
7421
7498
|
var init_jpi_bounties = __esm({
|
|
7422
7499
|
"bin/jpi-bounties.js"() {
|
|
7423
7500
|
"use strict";
|
|
7424
|
-
TERMINALHIRE_DIR7 =
|
|
7425
|
-
|
|
7501
|
+
TERMINALHIRE_DIR7 = join9(homedir8(), ".terminalhire");
|
|
7502
|
+
INDEX_CACHE_FILE3 = join9(TERMINALHIRE_DIR7, "index-cache.json");
|
|
7426
7503
|
INDEX_TTL_MS3 = 15 * 60 * 1e3;
|
|
7427
7504
|
API_URL4 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
7428
7505
|
DEFAULT_LIMIT3 = 15;
|
|
@@ -7447,16 +7524,16 @@ __export(claims_exports, {
|
|
|
7447
7524
|
removeClaim: () => removeClaim,
|
|
7448
7525
|
updateClaim: () => updateClaim
|
|
7449
7526
|
});
|
|
7450
|
-
import { readFileSync as
|
|
7451
|
-
import { join as
|
|
7452
|
-
import { homedir as
|
|
7527
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, renameSync, existsSync as existsSync6 } from "fs";
|
|
7528
|
+
import { join as join10 } from "path";
|
|
7529
|
+
import { homedir as homedir9 } from "os";
|
|
7453
7530
|
function nowISO() {
|
|
7454
7531
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
7455
7532
|
}
|
|
7456
7533
|
function readClaims() {
|
|
7457
7534
|
try {
|
|
7458
|
-
if (!
|
|
7459
|
-
const data = JSON.parse(
|
|
7535
|
+
if (!existsSync6(CLAIMS_FILE)) return [];
|
|
7536
|
+
const data = JSON.parse(readFileSync10(CLAIMS_FILE, "utf8"));
|
|
7460
7537
|
return Array.isArray(data?.claims) ? data.claims : [];
|
|
7461
7538
|
} catch {
|
|
7462
7539
|
return [];
|
|
@@ -7523,8 +7600,8 @@ var TERMINALHIRE_DIR8, CLAIMS_FILE, TERMINAL_STATES;
|
|
|
7523
7600
|
var init_claims = __esm({
|
|
7524
7601
|
"src/claims.ts"() {
|
|
7525
7602
|
"use strict";
|
|
7526
|
-
TERMINALHIRE_DIR8 =
|
|
7527
|
-
CLAIMS_FILE =
|
|
7603
|
+
TERMINALHIRE_DIR8 = join10(homedir9(), ".terminalhire");
|
|
7604
|
+
CLAIMS_FILE = join10(TERMINALHIRE_DIR8, "claims.json");
|
|
7528
7605
|
TERMINAL_STATES = /* @__PURE__ */ new Set(["merged", "abandoned"]);
|
|
7529
7606
|
}
|
|
7530
7607
|
});
|
|
@@ -7534,9 +7611,9 @@ var jpi_claim_exports = {};
|
|
|
7534
7611
|
__export(jpi_claim_exports, {
|
|
7535
7612
|
run: () => run6
|
|
7536
7613
|
});
|
|
7537
|
-
import { readFileSync as
|
|
7538
|
-
import { join as
|
|
7539
|
-
import { homedir as
|
|
7614
|
+
import { readFileSync as readFileSync11, existsSync as existsSync7 } from "fs";
|
|
7615
|
+
import { join as join11 } from "path";
|
|
7616
|
+
import { homedir as homedir10 } from "os";
|
|
7540
7617
|
import { execFile } from "child_process";
|
|
7541
7618
|
import { promisify } from "util";
|
|
7542
7619
|
import { createInterface as createInterface6 } from "readline";
|
|
@@ -7583,8 +7660,8 @@ function parseRepoFromRemote(url) {
|
|
|
7583
7660
|
}
|
|
7584
7661
|
function findBountyInCache(bountyId) {
|
|
7585
7662
|
try {
|
|
7586
|
-
if (!
|
|
7587
|
-
const entry = JSON.parse(
|
|
7663
|
+
if (!existsSync7(INDEX_CACHE_FILE4)) return null;
|
|
7664
|
+
const entry = JSON.parse(readFileSync11(INDEX_CACHE_FILE4, "utf8"));
|
|
7588
7665
|
const jobs = entry?.index?.jobs ?? [];
|
|
7589
7666
|
const job = jobs.find((j) => j.id === bountyId && j.source === "bounty");
|
|
7590
7667
|
return job ?? null;
|
|
@@ -8088,12 +8165,12 @@ async function run6() {
|
|
|
8088
8165
|
process.exit(1);
|
|
8089
8166
|
}
|
|
8090
8167
|
}
|
|
8091
|
-
var TERMINALHIRE_DIR9,
|
|
8168
|
+
var TERMINALHIRE_DIR9, INDEX_CACHE_FILE4, GH_API, GH_HEADERS, pExecFile, VALUE_FLAGS;
|
|
8092
8169
|
var init_jpi_claim = __esm({
|
|
8093
8170
|
"bin/jpi-claim.js"() {
|
|
8094
8171
|
"use strict";
|
|
8095
|
-
TERMINALHIRE_DIR9 =
|
|
8096
|
-
|
|
8172
|
+
TERMINALHIRE_DIR9 = join11(homedir10(), ".terminalhire");
|
|
8173
|
+
INDEX_CACHE_FILE4 = join11(TERMINALHIRE_DIR9, "index-cache.json");
|
|
8097
8174
|
GH_API = "https://api.github.com";
|
|
8098
8175
|
GH_HEADERS = { "User-Agent": "terminalhire-claim", Accept: "application/vnd.github+json" };
|
|
8099
8176
|
pExecFile = promisify(execFile);
|
|
@@ -8377,7 +8454,7 @@ function finalize(build) {
|
|
|
8377
8454
|
};
|
|
8378
8455
|
}
|
|
8379
8456
|
function reconstruct(files, opts = {}) {
|
|
8380
|
-
const
|
|
8457
|
+
const join26 = opts.joinSidechains !== false;
|
|
8381
8458
|
const mains = [];
|
|
8382
8459
|
const sidechains = [];
|
|
8383
8460
|
for (const file of files) {
|
|
@@ -8402,7 +8479,7 @@ function reconstruct(files, opts = {}) {
|
|
|
8402
8479
|
}
|
|
8403
8480
|
const orphanedSidechainPaths = [];
|
|
8404
8481
|
const joinedPaths = /* @__PURE__ */ new Set();
|
|
8405
|
-
if (
|
|
8482
|
+
if (join26) {
|
|
8406
8483
|
const sidechainsBySession = /* @__PURE__ */ new Map();
|
|
8407
8484
|
for (const sc of sidechains) {
|
|
8408
8485
|
const acc = sidechainsBySession.get(sc.sessionId) ?? [];
|
|
@@ -8889,12 +8966,12 @@ function deriveRecoveryDepth(episodes, nodesByUuid) {
|
|
|
8889
8966
|
continue;
|
|
8890
8967
|
}
|
|
8891
8968
|
spansConsidered++;
|
|
8892
|
-
let
|
|
8969
|
+
let run20 = 0;
|
|
8893
8970
|
const closeChain = () => {
|
|
8894
|
-
if (
|
|
8971
|
+
if (run20 > 0) {
|
|
8895
8972
|
recoveryChains++;
|
|
8896
|
-
totalDepth +=
|
|
8897
|
-
|
|
8973
|
+
totalDepth += run20;
|
|
8974
|
+
run20 = 0;
|
|
8898
8975
|
}
|
|
8899
8976
|
};
|
|
8900
8977
|
for (const uuid of episode.mainNodeUuids) {
|
|
@@ -8903,9 +8980,9 @@ function deriveRecoveryDepth(episodes, nodesByUuid) {
|
|
|
8903
8980
|
continue;
|
|
8904
8981
|
}
|
|
8905
8982
|
if (node.kind === "tool_result" /* ToolResult */ && node.isError) {
|
|
8906
|
-
|
|
8907
|
-
if (
|
|
8908
|
-
maxConsecutiveErrors =
|
|
8983
|
+
run20++;
|
|
8984
|
+
if (run20 > maxConsecutiveErrors) {
|
|
8985
|
+
maxConsecutiveErrors = run20;
|
|
8909
8986
|
}
|
|
8910
8987
|
} else if (node.kind === "tool_result" /* ToolResult */ && !node.isError) {
|
|
8911
8988
|
closeChain();
|
|
@@ -8950,25 +9027,25 @@ var init_episodes = __esm({
|
|
|
8950
9027
|
// src/web-session.ts
|
|
8951
9028
|
import {
|
|
8952
9029
|
chmodSync as chmodSync2,
|
|
8953
|
-
existsSync as
|
|
9030
|
+
existsSync as existsSync8,
|
|
8954
9031
|
mkdirSync as mkdirSync9,
|
|
8955
|
-
readFileSync as
|
|
9032
|
+
readFileSync as readFileSync12,
|
|
8956
9033
|
rmSync as rmSync2,
|
|
8957
9034
|
writeFileSync as writeFileSync9
|
|
8958
9035
|
} from "fs";
|
|
8959
|
-
import { homedir as
|
|
8960
|
-
import { join as
|
|
9036
|
+
import { homedir as homedir11 } from "os";
|
|
9037
|
+
import { join as join12 } from "path";
|
|
8961
9038
|
function terminalhireDir() {
|
|
8962
|
-
return
|
|
9039
|
+
return join12(homedir11(), ".terminalhire");
|
|
8963
9040
|
}
|
|
8964
9041
|
function webSessionFilePath() {
|
|
8965
|
-
return
|
|
9042
|
+
return join12(terminalhireDir(), "web-session");
|
|
8966
9043
|
}
|
|
8967
9044
|
function readWebSessionFile() {
|
|
8968
9045
|
try {
|
|
8969
9046
|
const path = webSessionFilePath();
|
|
8970
|
-
if (!
|
|
8971
|
-
const v =
|
|
9047
|
+
if (!existsSync8(path)) return null;
|
|
9048
|
+
const v = readFileSync12(path, "utf8").trim();
|
|
8972
9049
|
return v.length > 0 ? v : null;
|
|
8973
9050
|
} catch {
|
|
8974
9051
|
return null;
|
|
@@ -9010,14 +9087,14 @@ __export(trajectory_exports, {
|
|
|
9010
9087
|
runTrajectoryPush: () => runTrajectoryPush
|
|
9011
9088
|
});
|
|
9012
9089
|
import {
|
|
9013
|
-
existsSync as
|
|
9090
|
+
existsSync as existsSync9,
|
|
9014
9091
|
mkdirSync as mkdirSync10,
|
|
9015
|
-
readFileSync as
|
|
9092
|
+
readFileSync as readFileSync13,
|
|
9016
9093
|
readdirSync,
|
|
9017
9094
|
writeFileSync as writeFileSync10
|
|
9018
9095
|
} from "fs";
|
|
9019
|
-
import { homedir as
|
|
9020
|
-
import { join as
|
|
9096
|
+
import { homedir as homedir12 } from "os";
|
|
9097
|
+
import { join as join13 } from "path";
|
|
9021
9098
|
function isRecord4(value) {
|
|
9022
9099
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9023
9100
|
}
|
|
@@ -9049,7 +9126,7 @@ function findJsonlFiles(dir) {
|
|
|
9049
9126
|
return out;
|
|
9050
9127
|
}
|
|
9051
9128
|
for (const entry of entries) {
|
|
9052
|
-
const full =
|
|
9129
|
+
const full = join13(dir, entry.name);
|
|
9053
9130
|
if (entry.isDirectory()) {
|
|
9054
9131
|
out.push(...findJsonlFiles(full));
|
|
9055
9132
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -9063,7 +9140,7 @@ function loadCorpus(paths) {
|
|
|
9063
9140
|
for (const path of paths) {
|
|
9064
9141
|
let text;
|
|
9065
9142
|
try {
|
|
9066
|
-
text =
|
|
9143
|
+
text = readFileSync13(path, "utf8");
|
|
9067
9144
|
} catch {
|
|
9068
9145
|
continue;
|
|
9069
9146
|
}
|
|
@@ -9162,10 +9239,10 @@ function renderMarkdown(view) {
|
|
|
9162
9239
|
return lines.join("\n");
|
|
9163
9240
|
}
|
|
9164
9241
|
function writeExportArtifacts(score, markdown) {
|
|
9165
|
-
const dir =
|
|
9242
|
+
const dir = join13(homedir12(), ".terminalhire");
|
|
9166
9243
|
mkdirSync10(dir, { recursive: true });
|
|
9167
|
-
const jsonPath =
|
|
9168
|
-
const mdPath =
|
|
9244
|
+
const jsonPath = join13(dir, "trajectory-export.json");
|
|
9245
|
+
const mdPath = join13(dir, "trajectory-export.md");
|
|
9169
9246
|
writeFileSync10(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
|
|
9170
9247
|
writeFileSync10(mdPath, markdown, "utf8");
|
|
9171
9248
|
return { jsonPath, mdPath };
|
|
@@ -9186,8 +9263,8 @@ function renderInward(allNodes, view, files) {
|
|
|
9186
9263
|
console.log("");
|
|
9187
9264
|
}
|
|
9188
9265
|
function buildTrajectory() {
|
|
9189
|
-
const projectsDir =
|
|
9190
|
-
if (!
|
|
9266
|
+
const projectsDir = join13(homedir12(), ".claude", "projects");
|
|
9267
|
+
if (!existsSync9(projectsDir)) return null;
|
|
9191
9268
|
const paths = findJsonlFiles(projectsDir);
|
|
9192
9269
|
if (paths.length === 0) return null;
|
|
9193
9270
|
const files = loadCorpus(paths);
|
|
@@ -9636,15 +9713,40 @@ async function runIntroRequest(args5, overrides) {
|
|
|
9636
9713
|
deps.exit(1);
|
|
9637
9714
|
return;
|
|
9638
9715
|
}
|
|
9639
|
-
|
|
9716
|
+
let notified = false;
|
|
9717
|
+
try {
|
|
9718
|
+
const data = await res.json();
|
|
9719
|
+
notified = data.notified === true;
|
|
9720
|
+
} catch {
|
|
9721
|
+
}
|
|
9722
|
+
if (notified) {
|
|
9723
|
+
deps.log(`
|
|
9640
9724
|
Intro request sent to @${targetLogin}. They will see only your public login`);
|
|
9641
|
-
|
|
9725
|
+
deps.log(" until they accept; your contact is shared only if they do.\n");
|
|
9726
|
+
} else {
|
|
9727
|
+
deps.log(`
|
|
9728
|
+
Intro request recorded for @${targetLogin} \u2014 but we couldn't email them`);
|
|
9729
|
+
deps.log(" automatically (no public email on file). Send it to them yourself: they can run");
|
|
9730
|
+
deps.log(" `terminalhire intro --list` (or open their dashboard) to see and accept it.");
|
|
9731
|
+
deps.log(" They will see only your public login until they accept; your contact is");
|
|
9732
|
+
deps.log(" shared only if they do.\n");
|
|
9733
|
+
}
|
|
9734
|
+
}
|
|
9735
|
+
async function fetchIntros(deps, cookie) {
|
|
9736
|
+
const res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/list`, {
|
|
9737
|
+
method: "GET",
|
|
9738
|
+
headers: { Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
|
|
9739
|
+
signal: AbortSignal.timeout(1e4)
|
|
9740
|
+
});
|
|
9741
|
+
if (!res.ok) throw new Error(`/api/intro/list returned ${res.status}`);
|
|
9742
|
+
const data = await res.json().catch(() => ({}));
|
|
9743
|
+
return data.intros ?? [];
|
|
9642
9744
|
}
|
|
9643
9745
|
async function runIntroDecision(args5, overrides) {
|
|
9644
9746
|
const deps = { ...defaultIntroDeps(), ...overrides };
|
|
9645
|
-
|
|
9747
|
+
let id = args5.id?.trim() ?? "";
|
|
9646
9748
|
if (!id) {
|
|
9647
|
-
deps.errorLog("\n Usage: terminalhire intro --accept
|
|
9749
|
+
deps.errorLog("\n Usage: terminalhire intro --accept <@handle|id> | --decline <@handle|id>\n");
|
|
9648
9750
|
deps.exit(1);
|
|
9649
9751
|
return;
|
|
9650
9752
|
}
|
|
@@ -9655,19 +9757,51 @@ async function runIntroDecision(args5, overrides) {
|
|
|
9655
9757
|
deps.exit(0);
|
|
9656
9758
|
return;
|
|
9657
9759
|
}
|
|
9760
|
+
if (!UUID_RE.test(id)) {
|
|
9761
|
+
const handle = id.replace(/^@/, "").toLowerCase();
|
|
9762
|
+
let intros;
|
|
9763
|
+
try {
|
|
9764
|
+
intros = await fetchIntros(deps, cookie);
|
|
9765
|
+
} catch (err) {
|
|
9766
|
+
deps.errorLog(`
|
|
9767
|
+
Could not look up the request: ${err instanceof Error ? err.message : String(err)}
|
|
9768
|
+
`);
|
|
9769
|
+
deps.exit(1);
|
|
9770
|
+
return;
|
|
9771
|
+
}
|
|
9772
|
+
const matches = intros.filter(
|
|
9773
|
+
(it) => it.role === "incoming" && it.status === "pending" && it.counterpartyLogin.toLowerCase() === handle
|
|
9774
|
+
);
|
|
9775
|
+
if (matches.length === 0) {
|
|
9776
|
+
deps.errorLog(`
|
|
9777
|
+
No pending connection request from @${handle}.`);
|
|
9778
|
+
deps.errorLog(" See your requests with `terminalhire intro --list`.\n");
|
|
9779
|
+
deps.exit(1);
|
|
9780
|
+
return;
|
|
9781
|
+
}
|
|
9782
|
+
if (matches.length > 1) {
|
|
9783
|
+
deps.errorLog(`
|
|
9784
|
+
${matches.length} pending requests from @${handle} \u2014 ${args5.action === "accept" ? "accepting" : "declining"} one (the rest are redundant duplicates).`);
|
|
9785
|
+
}
|
|
9786
|
+
id = matches[0].id;
|
|
9787
|
+
}
|
|
9658
9788
|
let contact = "";
|
|
9789
|
+
let shareHandle = false;
|
|
9659
9790
|
if (args5.action === "accept") {
|
|
9660
9791
|
const profile = await deps.readProfileContact();
|
|
9661
9792
|
contact = (args5.contact ?? profile.contactEmail ?? "").trim();
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
deps.
|
|
9666
|
-
|
|
9793
|
+
shareHandle = contact.length === 0;
|
|
9794
|
+
let shareLabel = contact;
|
|
9795
|
+
if (shareHandle) {
|
|
9796
|
+
const login = await deps.readGithubLogin().catch(() => null);
|
|
9797
|
+
shareLabel = login ? `your GitHub handle (@${login})` : "your GitHub handle";
|
|
9667
9798
|
}
|
|
9668
9799
|
deps.log("");
|
|
9669
|
-
deps.log(" Accepting shares
|
|
9670
|
-
deps.log(` Your contact : ${
|
|
9800
|
+
deps.log(" Accepting shares a contact with the requester so they can reach you:");
|
|
9801
|
+
deps.log(` Your contact : ${shareLabel}`);
|
|
9802
|
+
if (shareHandle) {
|
|
9803
|
+
deps.log(" (share an email/handle instead with `--contact <email-or-handle>`)");
|
|
9804
|
+
}
|
|
9671
9805
|
deps.log(" Nothing else is shared. Declining shares nothing.");
|
|
9672
9806
|
deps.log("");
|
|
9673
9807
|
const answer = await deps.prompt(' Type "yes" to accept and share your contact (anything else cancels): ');
|
|
@@ -9677,7 +9811,7 @@ async function runIntroDecision(args5, overrides) {
|
|
|
9677
9811
|
return;
|
|
9678
9812
|
}
|
|
9679
9813
|
}
|
|
9680
|
-
const body = args5.action === "accept" ? { introId: id, action: "accept", targetContact: contact } : { introId: id, action: "decline" };
|
|
9814
|
+
const body = args5.action === "accept" ? shareHandle ? { introId: id, action: "accept" } : { introId: id, action: "accept", targetContact: contact } : { introId: id, action: "decline" };
|
|
9681
9815
|
let res;
|
|
9682
9816
|
try {
|
|
9683
9817
|
res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/accept`, {
|
|
@@ -9782,12 +9916,12 @@ async function runIntroList(overrides) {
|
|
|
9782
9916
|
if (it.note) deps.log(` note: ${it.note}`);
|
|
9783
9917
|
if (it.contact) deps.log(` contact: ${it.contact}`);
|
|
9784
9918
|
else if (it.role === "incoming" && it.status === "pending") {
|
|
9785
|
-
deps.log(` \u2192 accept: terminalhire intro --accept
|
|
9919
|
+
deps.log(` \u2192 accept: terminalhire intro --accept @${it.counterpartyLogin}`);
|
|
9786
9920
|
}
|
|
9787
9921
|
}
|
|
9788
9922
|
deps.log("");
|
|
9789
9923
|
}
|
|
9790
|
-
var LINK_BASE2, GH_SESSION_COOKIE2;
|
|
9924
|
+
var LINK_BASE2, GH_SESSION_COOKIE2, UUID_RE;
|
|
9791
9925
|
var init_intro2 = __esm({
|
|
9792
9926
|
"src/intro.ts"() {
|
|
9793
9927
|
"use strict";
|
|
@@ -9795,6 +9929,7 @@ var init_intro2 = __esm({
|
|
|
9795
9929
|
init_web_session();
|
|
9796
9930
|
LINK_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
9797
9931
|
GH_SESSION_COOKIE2 = "__jpi_gh_session";
|
|
9932
|
+
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9798
9933
|
}
|
|
9799
9934
|
});
|
|
9800
9935
|
|
|
@@ -9849,13 +9984,13 @@ var init_jpi_intro = __esm({
|
|
|
9849
9984
|
});
|
|
9850
9985
|
|
|
9851
9986
|
// src/chat-keystore.ts
|
|
9852
|
-
import { existsSync as
|
|
9853
|
-
import { homedir as
|
|
9854
|
-
import { join as
|
|
9987
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11, rmSync as rmSync3 } from "fs";
|
|
9988
|
+
import { homedir as homedir13 } from "os";
|
|
9989
|
+
import { join as join14 } from "path";
|
|
9855
9990
|
async function loadOrCreateIdentity() {
|
|
9856
9991
|
const key = await loadKey();
|
|
9857
|
-
if (
|
|
9858
|
-
const blob2 = JSON.parse(
|
|
9992
|
+
if (existsSync10(IDENTITY_FILE)) {
|
|
9993
|
+
const blob2 = JSON.parse(readFileSync14(IDENTITY_FILE, "utf8"));
|
|
9859
9994
|
return JSON.parse(decrypt(blob2, key));
|
|
9860
9995
|
}
|
|
9861
9996
|
const keypair = generateIdentityKeypair();
|
|
@@ -9870,19 +10005,19 @@ var init_chat_keystore = __esm({
|
|
|
9870
10005
|
"use strict";
|
|
9871
10006
|
init_src();
|
|
9872
10007
|
init_github_auth();
|
|
9873
|
-
TERMINALHIRE_DIR10 =
|
|
9874
|
-
IDENTITY_FILE =
|
|
10008
|
+
TERMINALHIRE_DIR10 = join14(homedir13(), ".terminalhire");
|
|
10009
|
+
IDENTITY_FILE = join14(TERMINALHIRE_DIR10, "chat-identity.enc");
|
|
9875
10010
|
}
|
|
9876
10011
|
});
|
|
9877
10012
|
|
|
9878
10013
|
// src/chat-client.ts
|
|
9879
|
-
import { existsSync as
|
|
9880
|
-
import { homedir as
|
|
9881
|
-
import { join as
|
|
10014
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
10015
|
+
import { homedir as homedir14 } from "os";
|
|
10016
|
+
import { join as join15 } from "path";
|
|
9882
10017
|
function defaultReadPeerPins() {
|
|
9883
10018
|
try {
|
|
9884
|
-
if (!
|
|
9885
|
-
const parsed = JSON.parse(
|
|
10019
|
+
if (!existsSync11(PEERS_FILE)) return {};
|
|
10020
|
+
const parsed = JSON.parse(readFileSync15(PEERS_FILE, "utf8"));
|
|
9886
10021
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
9887
10022
|
const out = {};
|
|
9888
10023
|
for (const [login, key] of Object.entries(parsed)) {
|
|
@@ -10058,8 +10193,8 @@ var init_chat_client = __esm({
|
|
|
10058
10193
|
init_web_session();
|
|
10059
10194
|
CHAT_BASE = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
10060
10195
|
GH_SESSION_COOKIE3 = "__jpi_gh_session";
|
|
10061
|
-
TERMINALHIRE_DIR11 =
|
|
10062
|
-
PEERS_FILE =
|
|
10196
|
+
TERMINALHIRE_DIR11 = join15(homedir14(), ".terminalhire");
|
|
10197
|
+
PEERS_FILE = join15(TERMINALHIRE_DIR11, "chat-peers.json");
|
|
10063
10198
|
REQUEST_TIMEOUT_MS = 1e4;
|
|
10064
10199
|
ChatNotLinkedError = class extends Error {
|
|
10065
10200
|
constructor() {
|
|
@@ -10113,13 +10248,13 @@ __export(jpi_chat_read_exports, {
|
|
|
10113
10248
|
runSend: () => runSend,
|
|
10114
10249
|
writeReadCursor: () => writeReadCursor
|
|
10115
10250
|
});
|
|
10116
|
-
import { existsSync as
|
|
10117
|
-
import { homedir as
|
|
10118
|
-
import { join as
|
|
10251
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync13, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "fs";
|
|
10252
|
+
import { homedir as homedir15 } from "os";
|
|
10253
|
+
import { join as join16 } from "path";
|
|
10119
10254
|
function readReadCursors() {
|
|
10120
10255
|
try {
|
|
10121
|
-
if (!
|
|
10122
|
-
const parsed = JSON.parse(
|
|
10256
|
+
if (!existsSync12(READS_FILE)) return {};
|
|
10257
|
+
const parsed = JSON.parse(readFileSync16(READS_FILE, "utf8"));
|
|
10123
10258
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
10124
10259
|
const out = {};
|
|
10125
10260
|
for (const [login, iso] of Object.entries(parsed)) {
|
|
@@ -10415,8 +10550,8 @@ var init_jpi_chat_read = __esm({
|
|
|
10415
10550
|
init_chat_client();
|
|
10416
10551
|
init_jpi_chat();
|
|
10417
10552
|
CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
10418
|
-
TERMINALHIRE_DIR12 =
|
|
10419
|
-
READS_FILE =
|
|
10553
|
+
TERMINALHIRE_DIR12 = join16(homedir15(), ".terminalhire");
|
|
10554
|
+
READS_FILE = join16(TERMINALHIRE_DIR12, "chat-reads.json");
|
|
10420
10555
|
}
|
|
10421
10556
|
});
|
|
10422
10557
|
|
|
@@ -11064,6 +11199,44 @@ var init_jpi_chat = __esm({
|
|
|
11064
11199
|
}
|
|
11065
11200
|
});
|
|
11066
11201
|
|
|
11202
|
+
// bin/jpi-connect.js
|
|
11203
|
+
var jpi_connect_exports = {};
|
|
11204
|
+
__export(jpi_connect_exports, {
|
|
11205
|
+
run: () => run10
|
|
11206
|
+
});
|
|
11207
|
+
async function run10() {
|
|
11208
|
+
const args5 = process.argv.slice(2).filter((a) => a !== "connect");
|
|
11209
|
+
if (args5.includes("--mute")) {
|
|
11210
|
+
writeConfig({ inboundNudgeMuted: true });
|
|
11211
|
+
console.log("\n Muted: your spinner will no longer surface incoming connection requests.");
|
|
11212
|
+
console.log(" Pending intros are still there \u2014 see them any time with `terminalhire intro --list`.");
|
|
11213
|
+
console.log(" Re-enable with `terminalhire connect --unmute`.\n");
|
|
11214
|
+
return;
|
|
11215
|
+
}
|
|
11216
|
+
if (args5.includes("--unmute")) {
|
|
11217
|
+
writeConfig({ inboundNudgeMuted: false });
|
|
11218
|
+
console.log("\n Unmuted: incoming connection requests will surface in your spinner again.");
|
|
11219
|
+
console.log(" (Requires a linked terminal \u2014 run `terminalhire link` if you have not.)\n");
|
|
11220
|
+
return;
|
|
11221
|
+
}
|
|
11222
|
+
const muted = isInboundNudgeMuted();
|
|
11223
|
+
console.log("\n terminalhire connect \u2014 find and reach other developers, locally matched:");
|
|
11224
|
+
console.log(" terminalhire devs Rank opted-in builders & projects for you");
|
|
11225
|
+
console.log(' terminalhire project "<title>: <skills>" Declare a project to staff');
|
|
11226
|
+
console.log(" terminalhire intro <github-login> Request a consented intro (double opt-in)");
|
|
11227
|
+
console.log(" terminalhire intro --list See intros you have sent + received");
|
|
11228
|
+
console.log(" terminalhire chat Message your accepted connections");
|
|
11229
|
+
console.log("");
|
|
11230
|
+
console.log(` Ambient inbound nudge: ${muted ? "muted" : "on"} (toggle: terminalhire connect --${muted ? "unmute" : "mute"})`);
|
|
11231
|
+
console.log("");
|
|
11232
|
+
}
|
|
11233
|
+
var init_jpi_connect = __esm({
|
|
11234
|
+
"bin/jpi-connect.js"() {
|
|
11235
|
+
"use strict";
|
|
11236
|
+
init_config();
|
|
11237
|
+
}
|
|
11238
|
+
});
|
|
11239
|
+
|
|
11067
11240
|
// src/link.ts
|
|
11068
11241
|
var link_exports = {};
|
|
11069
11242
|
__export(link_exports, {
|
|
@@ -11176,6 +11349,8 @@ async function runLink(overrides) {
|
|
|
11176
11349
|
deps.persistToken(outcome.token);
|
|
11177
11350
|
deps.log("\n This terminal is now linked to your terminalhire account.");
|
|
11178
11351
|
deps.log(" Try `terminalhire intro <login>`, `terminalhire chat`, or `terminalhire trajectory --push`.");
|
|
11352
|
+
deps.log(" Your spinner will quietly surface incoming connection requests.");
|
|
11353
|
+
deps.log(" Turn that off any time with `terminalhire connect --mute`.");
|
|
11179
11354
|
deps.log(" Unlink any time with `terminalhire link --logout`.\n");
|
|
11180
11355
|
deps.exit(0);
|
|
11181
11356
|
}
|
|
@@ -11241,9 +11416,9 @@ var init_link = __esm({
|
|
|
11241
11416
|
// bin/jpi-link.js
|
|
11242
11417
|
var jpi_link_exports = {};
|
|
11243
11418
|
__export(jpi_link_exports, {
|
|
11244
|
-
run: () =>
|
|
11419
|
+
run: () => run11
|
|
11245
11420
|
});
|
|
11246
|
-
async function
|
|
11421
|
+
async function run11() {
|
|
11247
11422
|
try {
|
|
11248
11423
|
const args5 = process.argv.slice(2);
|
|
11249
11424
|
if (args5.includes("--logout")) {
|
|
@@ -11267,7 +11442,7 @@ var init_jpi_link = __esm({
|
|
|
11267
11442
|
// bin/jpi-profile.js
|
|
11268
11443
|
var jpi_profile_exports = {};
|
|
11269
11444
|
__export(jpi_profile_exports, {
|
|
11270
|
-
run: () =>
|
|
11445
|
+
run: () => run12
|
|
11271
11446
|
});
|
|
11272
11447
|
import { createInterface as createInterface8 } from "readline";
|
|
11273
11448
|
function prompt4(question) {
|
|
@@ -11279,7 +11454,7 @@ function prompt4(question) {
|
|
|
11279
11454
|
});
|
|
11280
11455
|
});
|
|
11281
11456
|
}
|
|
11282
|
-
async function
|
|
11457
|
+
async function run12() {
|
|
11283
11458
|
const { readProfile: readProfile2, writeProfile: writeProfile2, deleteProfile: deleteProfile2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
|
|
11284
11459
|
const args5 = process.argv.slice(2);
|
|
11285
11460
|
if (args5.includes("--show")) {
|
|
@@ -11352,9 +11527,9 @@ var signal_exports = {};
|
|
|
11352
11527
|
__export(signal_exports, {
|
|
11353
11528
|
extractFingerprint: () => extractFingerprint
|
|
11354
11529
|
});
|
|
11355
|
-
import { readFileSync as
|
|
11530
|
+
import { readFileSync as readFileSync17, readdirSync as readdirSync2 } from "fs";
|
|
11356
11531
|
import { execFileSync } from "child_process";
|
|
11357
|
-
import { join as
|
|
11532
|
+
import { join as join17 } from "path";
|
|
11358
11533
|
function safeGit(args5, cwd) {
|
|
11359
11534
|
try {
|
|
11360
11535
|
return execFileSync("git", ["-C", cwd, ...args5], {
|
|
@@ -11382,20 +11557,20 @@ function isEmployerContext(cwd) {
|
|
|
11382
11557
|
}
|
|
11383
11558
|
function readJsonSafe(path) {
|
|
11384
11559
|
try {
|
|
11385
|
-
return JSON.parse(
|
|
11560
|
+
return JSON.parse(readFileSync17(path, "utf8"));
|
|
11386
11561
|
} catch {
|
|
11387
11562
|
return null;
|
|
11388
11563
|
}
|
|
11389
11564
|
}
|
|
11390
11565
|
function readFileSafe(path) {
|
|
11391
11566
|
try {
|
|
11392
|
-
return
|
|
11567
|
+
return readFileSync17(path, "utf8");
|
|
11393
11568
|
} catch {
|
|
11394
11569
|
return "";
|
|
11395
11570
|
}
|
|
11396
11571
|
}
|
|
11397
11572
|
function tokensFromPackageJson(cwd) {
|
|
11398
|
-
const pkg = readJsonSafe(
|
|
11573
|
+
const pkg = readJsonSafe(join17(cwd, "package.json"));
|
|
11399
11574
|
if (!pkg || typeof pkg !== "object") return [];
|
|
11400
11575
|
const p = pkg;
|
|
11401
11576
|
const deps = {
|
|
@@ -11409,9 +11584,9 @@ function workspaceMemberDirs(cwd) {
|
|
|
11409
11584
|
const dirs = [cwd];
|
|
11410
11585
|
for (const group of ["apps", "packages"]) {
|
|
11411
11586
|
try {
|
|
11412
|
-
const groupDir =
|
|
11587
|
+
const groupDir = join17(cwd, group);
|
|
11413
11588
|
for (const e of readdirSync2(groupDir, { withFileTypes: true })) {
|
|
11414
|
-
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(
|
|
11589
|
+
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join17(groupDir, e.name));
|
|
11415
11590
|
}
|
|
11416
11591
|
} catch {
|
|
11417
11592
|
}
|
|
@@ -11419,18 +11594,18 @@ function workspaceMemberDirs(cwd) {
|
|
|
11419
11594
|
return dirs;
|
|
11420
11595
|
}
|
|
11421
11596
|
function tokensFromRequirementsTxt(cwd) {
|
|
11422
|
-
const content = readFileSafe(
|
|
11597
|
+
const content = readFileSafe(join17(cwd, "requirements.txt"));
|
|
11423
11598
|
if (!content) return [];
|
|
11424
11599
|
return content.split("\n").map((l) => l.trim().split(/[>=<!\[;]/)[0].trim().toLowerCase()).filter(Boolean);
|
|
11425
11600
|
}
|
|
11426
11601
|
function tokensFromGoMod(cwd) {
|
|
11427
|
-
const content = readFileSafe(
|
|
11602
|
+
const content = readFileSafe(join17(cwd, "go.mod"));
|
|
11428
11603
|
if (!content) return [];
|
|
11429
11604
|
const requires = Array.from(content.matchAll(/^\s+([^\s]+)\s+v/gm)).map((m) => m[1].split("/").pop() ?? "").filter(Boolean);
|
|
11430
11605
|
return ["go", ...requires];
|
|
11431
11606
|
}
|
|
11432
11607
|
function tokensFromCargoToml(cwd) {
|
|
11433
|
-
const content = readFileSafe(
|
|
11608
|
+
const content = readFileSafe(join17(cwd, "Cargo.toml"));
|
|
11434
11609
|
if (!content) return [];
|
|
11435
11610
|
const deps = [];
|
|
11436
11611
|
let inDeps = false;
|
|
@@ -11451,7 +11626,7 @@ function tokensFromFileExtensions(cwd) {
|
|
|
11451
11626
|
const tokens = [];
|
|
11452
11627
|
const scanDirs = [cwd];
|
|
11453
11628
|
try {
|
|
11454
|
-
const srcDir =
|
|
11629
|
+
const srcDir = join17(cwd, "src");
|
|
11455
11630
|
readdirSync2(srcDir);
|
|
11456
11631
|
scanDirs.push(srcDir);
|
|
11457
11632
|
} catch {
|
|
@@ -11612,9 +11787,9 @@ var init_signal = __esm({
|
|
|
11612
11787
|
// bin/jpi-learn.js
|
|
11613
11788
|
var jpi_learn_exports = {};
|
|
11614
11789
|
__export(jpi_learn_exports, {
|
|
11615
|
-
run: () =>
|
|
11790
|
+
run: () => run13
|
|
11616
11791
|
});
|
|
11617
|
-
async function
|
|
11792
|
+
async function run13() {
|
|
11618
11793
|
try {
|
|
11619
11794
|
const args5 = process.argv.slice(2);
|
|
11620
11795
|
const cwdIdx = args5.indexOf("--cwd");
|
|
@@ -11641,7 +11816,7 @@ var init_jpi_learn = __esm({
|
|
|
11641
11816
|
"use strict";
|
|
11642
11817
|
isMain = process.argv[1]?.endsWith("jpi-learn.js") || process.argv[1]?.endsWith("jpi-learn");
|
|
11643
11818
|
if (isMain) {
|
|
11644
|
-
|
|
11819
|
+
run13();
|
|
11645
11820
|
}
|
|
11646
11821
|
}
|
|
11647
11822
|
});
|
|
@@ -11649,17 +11824,17 @@ var init_jpi_learn = __esm({
|
|
|
11649
11824
|
// bin/jpi-config.js
|
|
11650
11825
|
var jpi_config_exports = {};
|
|
11651
11826
|
__export(jpi_config_exports, {
|
|
11652
|
-
run: () =>
|
|
11827
|
+
run: () => run14
|
|
11653
11828
|
});
|
|
11654
|
-
import { join as
|
|
11655
|
-
import { homedir as
|
|
11829
|
+
import { join as join18 } from "path";
|
|
11830
|
+
import { homedir as homedir16 } from "os";
|
|
11656
11831
|
function parseNudgeMode(raw) {
|
|
11657
11832
|
if (raw === "session" || raw === "always") return raw;
|
|
11658
11833
|
const m = /^every:(\d+)$/.exec(raw);
|
|
11659
11834
|
if (m && parseInt(m[1], 10) >= 1) return raw;
|
|
11660
11835
|
return null;
|
|
11661
11836
|
}
|
|
11662
|
-
async function
|
|
11837
|
+
async function run14() {
|
|
11663
11838
|
const args5 = process.argv.slice(2);
|
|
11664
11839
|
const filtered = args5[0] === "config" ? args5.slice(1) : args5;
|
|
11665
11840
|
if (filtered.includes("--show") || filtered.length === 0) {
|
|
@@ -11725,8 +11900,8 @@ var init_jpi_config = __esm({
|
|
|
11725
11900
|
"bin/jpi-config.js"() {
|
|
11726
11901
|
"use strict";
|
|
11727
11902
|
init_config();
|
|
11728
|
-
TERMINALHIRE_DIR13 =
|
|
11729
|
-
CONFIG_FILE2 =
|
|
11903
|
+
TERMINALHIRE_DIR13 = join18(homedir16(), ".terminalhire");
|
|
11904
|
+
CONFIG_FILE2 = join18(TERMINALHIRE_DIR13, "config.json");
|
|
11730
11905
|
}
|
|
11731
11906
|
});
|
|
11732
11907
|
|
|
@@ -11737,6 +11912,7 @@ __export(spinner_exports, {
|
|
|
11737
11912
|
applySpinnerTips: () => applySpinnerTips,
|
|
11738
11913
|
applySpinnerVerbs: () => applySpinnerVerbs,
|
|
11739
11914
|
buildContextVerbs: () => buildContextVerbs,
|
|
11915
|
+
buildIncomingIntroLine: () => buildIncomingIntroLine,
|
|
11740
11916
|
buildPeerLine: () => buildPeerLine,
|
|
11741
11917
|
buildSpinnerPool: () => buildSpinnerPool,
|
|
11742
11918
|
buildTips: () => buildTips,
|
|
@@ -11749,17 +11925,17 @@ __export(spinner_exports, {
|
|
|
11749
11925
|
readSpinnerConfig: () => readSpinnerConfig
|
|
11750
11926
|
});
|
|
11751
11927
|
import {
|
|
11752
|
-
readFileSync as
|
|
11928
|
+
readFileSync as readFileSync18,
|
|
11753
11929
|
writeFileSync as writeFileSync14,
|
|
11754
|
-
existsSync as
|
|
11930
|
+
existsSync as existsSync13,
|
|
11755
11931
|
mkdirSync as mkdirSync14,
|
|
11756
11932
|
renameSync as renameSync2
|
|
11757
11933
|
} from "fs";
|
|
11758
|
-
import { join as
|
|
11759
|
-
import { homedir as
|
|
11934
|
+
import { join as join19, dirname } from "path";
|
|
11935
|
+
import { homedir as homedir17 } from "os";
|
|
11760
11936
|
function readJson(path, fallback) {
|
|
11761
11937
|
try {
|
|
11762
|
-
return
|
|
11938
|
+
return existsSync13(path) ? JSON.parse(readFileSync18(path, "utf8")) : fallback;
|
|
11763
11939
|
} catch {
|
|
11764
11940
|
return fallback;
|
|
11765
11941
|
}
|
|
@@ -11859,16 +12035,25 @@ function buildPeerLine(topPeers) {
|
|
|
11859
12035
|
if (n < 1) return null;
|
|
11860
12036
|
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`;
|
|
11861
12037
|
}
|
|
12038
|
+
function buildIncomingIntroLine(incomingPending) {
|
|
12039
|
+
const n = incomingPending && typeof incomingPending.count === "number" ? incomingPending.count : 0;
|
|
12040
|
+
if (n < 1) return null;
|
|
12041
|
+
return n === 1 ? `\u2198 someone wants to connect \xB7 terminalhire intro --list` : `\u2198 ${n} people want to connect \xB7 terminalhire intro --list`;
|
|
12042
|
+
}
|
|
11862
12043
|
function buildSpinnerPool(topMatches, max = 6, opts = {}) {
|
|
11863
|
-
const { sessionTags, frequency = "always", topPeers } = opts;
|
|
12044
|
+
const { sessionTags, frequency = "always", topPeers, incomingPending } = opts;
|
|
12045
|
+
const introLine = buildIncomingIntroLine(incomingPending);
|
|
11864
12046
|
const ranked = rankBySessionTags(topMatches, sessionTags);
|
|
11865
12047
|
if (!Array.isArray(ranked) || ranked.length === 0) {
|
|
12048
|
+
if (introLine) return [introLine];
|
|
11866
12049
|
const peerLine = buildPeerLine(topPeers);
|
|
11867
12050
|
return peerLine ? [peerLine] : [];
|
|
11868
12051
|
}
|
|
11869
12052
|
const headers = buildContextVerbs(ranked, sessionTags);
|
|
11870
12053
|
const cap = Math.max(1, verbCountForFrequency(frequency, headers.length));
|
|
11871
|
-
|
|
12054
|
+
const pool = [...headers.slice(0, cap), ctaVerb()];
|
|
12055
|
+
if (introLine) pool.push(introLine);
|
|
12056
|
+
return pool;
|
|
11872
12057
|
}
|
|
11873
12058
|
function readState() {
|
|
11874
12059
|
return readJson(SPINNER_STATE_FILE, { verbs: [], mode: "replace" });
|
|
@@ -12027,10 +12212,10 @@ var TH_DIR, CLAUDE_SETTINGS, CONFIG_FILE3, SPINNER_STATE_FILE, SPINNER_DEFAULTS,
|
|
|
12027
12212
|
var init_spinner = __esm({
|
|
12028
12213
|
"bin/spinner.js"() {
|
|
12029
12214
|
"use strict";
|
|
12030
|
-
TH_DIR = process.env["TERMINALHIRE_DIR"] ||
|
|
12031
|
-
CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
12032
|
-
CONFIG_FILE3 =
|
|
12033
|
-
SPINNER_STATE_FILE =
|
|
12215
|
+
TH_DIR = process.env["TERMINALHIRE_DIR"] || join19(homedir17(), ".terminalhire");
|
|
12216
|
+
CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join19(homedir17(), ".claude", "settings.json");
|
|
12217
|
+
CONFIG_FILE3 = join19(TH_DIR, "config.json");
|
|
12218
|
+
SPINNER_STATE_FILE = join19(TH_DIR, "spinner-state.json");
|
|
12034
12219
|
SPINNER_DEFAULTS = { enabled: false, mode: "append", max: 6, frequency: "sometimes" };
|
|
12035
12220
|
VERB_INTROS = ["Matched:", "You\u2019d fit:", "Worth a look:", "On your radar:", "Fits your stack:"];
|
|
12036
12221
|
}
|
|
@@ -12039,21 +12224,21 @@ var init_spinner = __esm({
|
|
|
12039
12224
|
// bin/jpi-spinner.js
|
|
12040
12225
|
var jpi_spinner_exports = {};
|
|
12041
12226
|
__export(jpi_spinner_exports, {
|
|
12042
|
-
run: () =>
|
|
12227
|
+
run: () => run15
|
|
12043
12228
|
});
|
|
12044
12229
|
import {
|
|
12045
|
-
readFileSync as
|
|
12230
|
+
readFileSync as readFileSync19,
|
|
12046
12231
|
writeFileSync as writeFileSync15,
|
|
12047
12232
|
copyFileSync,
|
|
12048
|
-
existsSync as
|
|
12233
|
+
existsSync as existsSync14,
|
|
12049
12234
|
mkdirSync as mkdirSync15
|
|
12050
12235
|
} from "fs";
|
|
12051
|
-
import { join as
|
|
12052
|
-
import { homedir as
|
|
12236
|
+
import { join as join20 } from "path";
|
|
12237
|
+
import { homedir as homedir18 } from "os";
|
|
12053
12238
|
import { createInterface as createInterface9 } from "readline";
|
|
12054
12239
|
function readConfig2() {
|
|
12055
12240
|
try {
|
|
12056
|
-
return
|
|
12241
|
+
return existsSync14(CONFIG_FILE4) ? JSON.parse(readFileSync19(CONFIG_FILE4, "utf8")) : {};
|
|
12057
12242
|
} catch {
|
|
12058
12243
|
return {};
|
|
12059
12244
|
}
|
|
@@ -12064,7 +12249,7 @@ function writeConfig2(patch) {
|
|
|
12064
12249
|
writeFileSync15(CONFIG_FILE4, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
12065
12250
|
}
|
|
12066
12251
|
function backupSettings() {
|
|
12067
|
-
if (!
|
|
12252
|
+
if (!existsSync14(SETTINGS_PATH)) return null;
|
|
12068
12253
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
12069
12254
|
const backupPath = `${SETTINGS_PATH}.terminalhire-backup-${ts}`;
|
|
12070
12255
|
copyFileSync(SETTINGS_PATH, backupPath);
|
|
@@ -12081,13 +12266,13 @@ function ask(question) {
|
|
|
12081
12266
|
}
|
|
12082
12267
|
function readTopMatches() {
|
|
12083
12268
|
try {
|
|
12084
|
-
const c = JSON.parse(
|
|
12269
|
+
const c = JSON.parse(readFileSync19(CACHE_FILE, "utf8"));
|
|
12085
12270
|
return Array.isArray(c.topMatches) ? c.topMatches : [];
|
|
12086
12271
|
} catch {
|
|
12087
12272
|
return [];
|
|
12088
12273
|
}
|
|
12089
12274
|
}
|
|
12090
|
-
async function
|
|
12275
|
+
async function run15() {
|
|
12091
12276
|
const args5 = process.argv.slice(2).filter((a) => a !== "spinner");
|
|
12092
12277
|
const has = (f) => args5.includes(f);
|
|
12093
12278
|
const val = (f) => {
|
|
@@ -12224,21 +12409,21 @@ var init_jpi_spinner = __esm({
|
|
|
12224
12409
|
"bin/jpi-spinner.js"() {
|
|
12225
12410
|
"use strict";
|
|
12226
12411
|
init_spinner();
|
|
12227
|
-
TH_DIR2 = process.env["TERMINALHIRE_DIR"] ||
|
|
12228
|
-
CONFIG_FILE4 =
|
|
12229
|
-
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
12230
|
-
CACHE_FILE =
|
|
12412
|
+
TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join20(homedir18(), ".terminalhire");
|
|
12413
|
+
CONFIG_FILE4 = join20(TH_DIR2, "config.json");
|
|
12414
|
+
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join20(homedir18(), ".claude", "settings.json");
|
|
12415
|
+
CACHE_FILE = join20(TH_DIR2, "index-cache.json");
|
|
12231
12416
|
}
|
|
12232
12417
|
});
|
|
12233
12418
|
|
|
12234
12419
|
// bin/jpi-sync.js
|
|
12235
12420
|
var jpi_sync_exports = {};
|
|
12236
12421
|
__export(jpi_sync_exports, {
|
|
12237
|
-
run: () =>
|
|
12422
|
+
run: () => run16
|
|
12238
12423
|
});
|
|
12239
|
-
import { readFileSync as
|
|
12240
|
-
import { join as
|
|
12241
|
-
import { homedir as
|
|
12424
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync16, mkdirSync as mkdirSync16, existsSync as existsSync15, rmSync as rmSync4 } from "fs";
|
|
12425
|
+
import { join as join21 } from "path";
|
|
12426
|
+
import { homedir as homedir19, hostname as osHostname } from "os";
|
|
12242
12427
|
import { createInterface as createInterface10 } from "readline";
|
|
12243
12428
|
function ask2(question) {
|
|
12244
12429
|
const rl = createInterface10({ input: process.stdin, output: process.stdout });
|
|
@@ -12251,7 +12436,7 @@ function ask2(question) {
|
|
|
12251
12436
|
}
|
|
12252
12437
|
function readMarker() {
|
|
12253
12438
|
try {
|
|
12254
|
-
return
|
|
12439
|
+
return existsSync15(TIER1_MARKER) ? JSON.parse(readFileSync20(TIER1_MARKER, "utf8")) : null;
|
|
12255
12440
|
} catch {
|
|
12256
12441
|
return null;
|
|
12257
12442
|
}
|
|
@@ -12546,7 +12731,7 @@ async function runDelete() {
|
|
|
12546
12731
|
clearMarker();
|
|
12547
12732
|
console.log("\n Synced profile deleted and local marker cleared.\n");
|
|
12548
12733
|
}
|
|
12549
|
-
async function
|
|
12734
|
+
async function run16() {
|
|
12550
12735
|
const args5 = process.argv.slice(2).filter((a) => a !== "sync");
|
|
12551
12736
|
const has = (f) => args5.includes(f);
|
|
12552
12737
|
if (has("--push") || has("--enable")) {
|
|
@@ -12577,8 +12762,8 @@ var init_jpi_sync = __esm({
|
|
|
12577
12762
|
"bin/jpi-sync.js"() {
|
|
12578
12763
|
"use strict";
|
|
12579
12764
|
init_open_url();
|
|
12580
|
-
TH_DIR3 = process.env["TERMINALHIRE_DIR"] ||
|
|
12581
|
-
TIER1_MARKER =
|
|
12765
|
+
TH_DIR3 = process.env["TERMINALHIRE_DIR"] || join21(homedir19(), ".terminalhire");
|
|
12766
|
+
TIER1_MARKER = join21(TH_DIR3, "tier1.json");
|
|
12582
12767
|
API_URL5 = process.env["TERMINALHIRE_API_URL"] || process.env["JPI_API_URL"] || "https://terminalhire.com";
|
|
12583
12768
|
SYNC_BASE = "https://www.terminalhire.com";
|
|
12584
12769
|
POLL_INTERVAL_MS = 2e3;
|
|
@@ -12590,14 +12775,14 @@ var init_jpi_sync = __esm({
|
|
|
12590
12775
|
// bin/jpi-init.js
|
|
12591
12776
|
var jpi_init_exports = {};
|
|
12592
12777
|
__export(jpi_init_exports, {
|
|
12593
|
-
run: () =>
|
|
12778
|
+
run: () => run17
|
|
12594
12779
|
});
|
|
12595
|
-
import { existsSync as
|
|
12596
|
-
import { join as
|
|
12597
|
-
import { fileURLToPath as
|
|
12780
|
+
import { existsSync as existsSync16 } from "fs";
|
|
12781
|
+
import { join as join22, resolve } from "path";
|
|
12782
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12598
12783
|
import { createInterface as createInterface11 } from "readline";
|
|
12599
12784
|
import { spawnSync, spawn as spawn2 } from "child_process";
|
|
12600
|
-
import { homedir as
|
|
12785
|
+
import { homedir as homedir20 } from "os";
|
|
12601
12786
|
function ask3(question) {
|
|
12602
12787
|
const rl = createInterface11({ input: process.stdin, output: process.stdout });
|
|
12603
12788
|
return new Promise((resolve2) => {
|
|
@@ -12608,18 +12793,18 @@ function ask3(question) {
|
|
|
12608
12793
|
});
|
|
12609
12794
|
}
|
|
12610
12795
|
function resolveScript(name) {
|
|
12611
|
-
const distPath = resolve(
|
|
12612
|
-
const legacyPath = resolve(
|
|
12613
|
-
return
|
|
12796
|
+
const distPath = resolve(join22(__dirname3, "..", "..", "dist", "bin", `${name}.js`));
|
|
12797
|
+
const legacyPath = resolve(join22(__dirname3, `${name}.js`));
|
|
12798
|
+
return existsSync16(distPath) ? distPath : legacyPath;
|
|
12614
12799
|
}
|
|
12615
12800
|
function resolveInstallJs() {
|
|
12616
|
-
const fromDist = resolve(
|
|
12617
|
-
const fromBin = resolve(
|
|
12618
|
-
if (
|
|
12619
|
-
if (
|
|
12801
|
+
const fromDist = resolve(join22(__dirname3, "..", "..", "install.js"));
|
|
12802
|
+
const fromBin = resolve(join22(__dirname3, "..", "install.js"));
|
|
12803
|
+
if (existsSync16(fromDist)) return fromDist;
|
|
12804
|
+
if (existsSync16(fromBin)) return fromBin;
|
|
12620
12805
|
return fromBin;
|
|
12621
12806
|
}
|
|
12622
|
-
async function
|
|
12807
|
+
async function run17() {
|
|
12623
12808
|
console.log("");
|
|
12624
12809
|
console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
12625
12810
|
console.log("\u2502 terminalhire init \u2014 one-command onboarding \u2502");
|
|
@@ -12711,24 +12896,24 @@ async function run16() {
|
|
|
12711
12896
|
console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
12712
12897
|
console.log("");
|
|
12713
12898
|
}
|
|
12714
|
-
var
|
|
12899
|
+
var __dirname3;
|
|
12715
12900
|
var init_jpi_init = __esm({
|
|
12716
12901
|
"bin/jpi-init.js"() {
|
|
12717
12902
|
"use strict";
|
|
12718
|
-
|
|
12903
|
+
__dirname3 = fileURLToPath4(new URL(".", import.meta.url));
|
|
12719
12904
|
}
|
|
12720
12905
|
});
|
|
12721
12906
|
|
|
12722
12907
|
// bin/jpi-refresh.js
|
|
12723
12908
|
var jpi_refresh_exports = {};
|
|
12724
12909
|
__export(jpi_refresh_exports, {
|
|
12725
|
-
run: () =>
|
|
12910
|
+
run: () => run18
|
|
12726
12911
|
});
|
|
12727
|
-
import { readFileSync as
|
|
12728
|
-
import { join as
|
|
12729
|
-
import { homedir as
|
|
12730
|
-
import { fileURLToPath as
|
|
12731
|
-
async function
|
|
12912
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, existsSync as existsSync17, mkdirSync as mkdirSync17 } from "fs";
|
|
12913
|
+
import { join as join23 } from "path";
|
|
12914
|
+
import { homedir as homedir21 } from "os";
|
|
12915
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
12916
|
+
async function run18() {
|
|
12732
12917
|
try {
|
|
12733
12918
|
let index;
|
|
12734
12919
|
try {
|
|
@@ -12818,15 +13003,32 @@ async function run17() {
|
|
|
12818
13003
|
}
|
|
12819
13004
|
} catch {
|
|
12820
13005
|
}
|
|
13006
|
+
let incomingPending = { count: 0 };
|
|
13007
|
+
const sessionCookie = readWebSessionFile();
|
|
13008
|
+
if (sessionCookie && !isInboundNudgeMuted()) try {
|
|
13009
|
+
const res = await fetch(`${API_URL6}/api/intro/list`, {
|
|
13010
|
+
method: "GET",
|
|
13011
|
+
headers: { Cookie: `${GH_SESSION_COOKIE6}=${sessionCookie}` },
|
|
13012
|
+
signal: AbortSignal.timeout(1e4)
|
|
13013
|
+
});
|
|
13014
|
+
if (res.ok) {
|
|
13015
|
+
const body = await res.json();
|
|
13016
|
+
const intros = Array.isArray(body?.intros) ? body.intros : [];
|
|
13017
|
+
const incoming = intros.filter((it) => it && it.role === "incoming" && it.status === "pending");
|
|
13018
|
+
incomingPending = { count: incoming.length };
|
|
13019
|
+
}
|
|
13020
|
+
} catch {
|
|
13021
|
+
}
|
|
12821
13022
|
mkdirSync17(TERMINALHIRE_DIR14, { recursive: true });
|
|
12822
13023
|
const cacheEntry = {
|
|
12823
13024
|
ts: Date.now(),
|
|
12824
13025
|
index,
|
|
12825
13026
|
matchCount,
|
|
12826
13027
|
topMatches,
|
|
12827
|
-
topPeers
|
|
13028
|
+
topPeers,
|
|
13029
|
+
incomingPending
|
|
12828
13030
|
};
|
|
12829
|
-
writeFileSync17(
|
|
13031
|
+
writeFileSync17(INDEX_CACHE_FILE5, JSON.stringify(cacheEntry), "utf8");
|
|
12830
13032
|
try {
|
|
12831
13033
|
const {
|
|
12832
13034
|
readSpinnerConfig: readSpinnerConfig2,
|
|
@@ -12850,7 +13052,7 @@ async function run17() {
|
|
|
12850
13052
|
} catch {
|
|
12851
13053
|
}
|
|
12852
13054
|
const ranked = rankBySessionTags2(topMatches, sessionTags);
|
|
12853
|
-
const verbs = buildSpinnerPool2(ranked, sc.max, { sessionTags, frequency: sc.frequency, topPeers });
|
|
13055
|
+
const verbs = buildSpinnerPool2(ranked, sc.max, { sessionTags, frequency: sc.frequency, topPeers, incomingPending });
|
|
12854
13056
|
if (verbs.length > 0) applySpinnerVerbs2(verbs, sc.mode);
|
|
12855
13057
|
else clearSpinnerVerbs2();
|
|
12856
13058
|
const tips = buildTips2(ranked, API_URL6, 8);
|
|
@@ -12862,6 +13064,13 @@ async function run17() {
|
|
|
12862
13064
|
}
|
|
12863
13065
|
} catch {
|
|
12864
13066
|
}
|
|
13067
|
+
try {
|
|
13068
|
+
const { readLocalVersion: readLocalVersion2, buildStaleNudge: buildStaleNudge2 } = await Promise.resolve().then(() => (init_version_nudge(), version_nudge_exports));
|
|
13069
|
+
const nudge = buildStaleNudge2(readLocalVersion2(), index?.cliVersion);
|
|
13070
|
+
if (nudge) process.stderr.write(`${nudge}
|
|
13071
|
+
`);
|
|
13072
|
+
} catch {
|
|
13073
|
+
}
|
|
12865
13074
|
process.exit(0);
|
|
12866
13075
|
} catch (err) {
|
|
12867
13076
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -12870,15 +13079,17 @@ async function run17() {
|
|
|
12870
13079
|
process.exit(1);
|
|
12871
13080
|
}
|
|
12872
13081
|
}
|
|
12873
|
-
var
|
|
13082
|
+
var GH_SESSION_COOKIE6, __dirname4, TERMINALHIRE_DIR14, INDEX_CACHE_FILE5, API_URL6;
|
|
12874
13083
|
var init_jpi_refresh = __esm({
|
|
12875
13084
|
"bin/jpi-refresh.js"() {
|
|
12876
13085
|
"use strict";
|
|
12877
13086
|
init_directory2();
|
|
12878
13087
|
init_config();
|
|
12879
|
-
|
|
12880
|
-
|
|
12881
|
-
|
|
13088
|
+
init_web_session();
|
|
13089
|
+
GH_SESSION_COOKIE6 = "__jpi_gh_session";
|
|
13090
|
+
__dirname4 = fileURLToPath5(new URL(".", import.meta.url));
|
|
13091
|
+
TERMINALHIRE_DIR14 = join23(homedir21(), ".terminalhire");
|
|
13092
|
+
INDEX_CACHE_FILE5 = join23(TERMINALHIRE_DIR14, "index-cache.json");
|
|
12882
13093
|
API_URL6 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
12883
13094
|
}
|
|
12884
13095
|
});
|
|
@@ -12886,16 +13097,16 @@ var init_jpi_refresh = __esm({
|
|
|
12886
13097
|
// bin/jpi-save.js
|
|
12887
13098
|
var jpi_save_exports = {};
|
|
12888
13099
|
__export(jpi_save_exports, {
|
|
12889
|
-
run: () =>
|
|
13100
|
+
run: () => run19
|
|
12890
13101
|
});
|
|
12891
|
-
import { readFileSync as
|
|
12892
|
-
import { join as
|
|
12893
|
-
import { homedir as
|
|
12894
|
-
import { fileURLToPath as
|
|
13102
|
+
import { readFileSync as readFileSync22, existsSync as existsSync18 } from "fs";
|
|
13103
|
+
import { join as join24 } from "path";
|
|
13104
|
+
import { homedir as homedir22 } from "os";
|
|
13105
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
12895
13106
|
function findJobInCache(jobId) {
|
|
12896
13107
|
try {
|
|
12897
|
-
if (!
|
|
12898
|
-
const raw =
|
|
13108
|
+
if (!existsSync18(INDEX_CACHE_FILE6)) return null;
|
|
13109
|
+
const raw = readFileSync22(INDEX_CACHE_FILE6, "utf8");
|
|
12899
13110
|
const entry = JSON.parse(raw);
|
|
12900
13111
|
const jobs = entry?.index?.jobs ?? [];
|
|
12901
13112
|
return jobs.find((j) => j.id === jobId) ?? null;
|
|
@@ -12964,7 +13175,7 @@ async function cmdUnsave(jobId) {
|
|
|
12964
13175
|
process.exit(1);
|
|
12965
13176
|
}
|
|
12966
13177
|
}
|
|
12967
|
-
async function
|
|
13178
|
+
async function run19() {
|
|
12968
13179
|
const verb = process.argv[2];
|
|
12969
13180
|
const jobId = process.argv[3];
|
|
12970
13181
|
try {
|
|
@@ -12983,31 +13194,31 @@ async function run18() {
|
|
|
12983
13194
|
process.exit(1);
|
|
12984
13195
|
}
|
|
12985
13196
|
}
|
|
12986
|
-
var
|
|
13197
|
+
var __dirname5, TERMINALHIRE_DIR15, INDEX_CACHE_FILE6;
|
|
12987
13198
|
var init_jpi_save = __esm({
|
|
12988
13199
|
"bin/jpi-save.js"() {
|
|
12989
13200
|
"use strict";
|
|
12990
|
-
|
|
12991
|
-
TERMINALHIRE_DIR15 =
|
|
12992
|
-
|
|
13201
|
+
__dirname5 = fileURLToPath6(new URL(".", import.meta.url));
|
|
13202
|
+
TERMINALHIRE_DIR15 = join24(homedir22(), ".terminalhire");
|
|
13203
|
+
INDEX_CACHE_FILE6 = join24(TERMINALHIRE_DIR15, "index-cache.json");
|
|
12993
13204
|
}
|
|
12994
13205
|
});
|
|
12995
13206
|
|
|
12996
13207
|
// bin/jpi-dispatch.js
|
|
12997
|
-
import { fileURLToPath as
|
|
12998
|
-
import { join as
|
|
12999
|
-
import { existsSync as
|
|
13208
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
13209
|
+
import { join as join25, dirname as dirname2 } from "path";
|
|
13210
|
+
import { existsSync as existsSync19, readFileSync as readFileSync23 } from "fs";
|
|
13000
13211
|
import { createRequire } from "module";
|
|
13001
|
-
var
|
|
13212
|
+
var __dirname6 = fileURLToPath7(new URL(".", import.meta.url));
|
|
13002
13213
|
function readPackageVersion() {
|
|
13003
13214
|
try {
|
|
13004
13215
|
const candidates = [
|
|
13005
|
-
|
|
13006
|
-
|
|
13216
|
+
join25(__dirname6, "..", "..", "package.json"),
|
|
13217
|
+
join25(__dirname6, "..", "package.json")
|
|
13007
13218
|
];
|
|
13008
13219
|
for (const p of candidates) {
|
|
13009
|
-
if (
|
|
13010
|
-
const pkg = JSON.parse(
|
|
13220
|
+
if (existsSync19(p)) {
|
|
13221
|
+
const pkg = JSON.parse(readFileSync23(p, "utf8"));
|
|
13011
13222
|
if (pkg.version) return pkg.version;
|
|
13012
13223
|
}
|
|
13013
13224
|
}
|
|
@@ -13018,7 +13229,7 @@ function readPackageVersion() {
|
|
|
13018
13229
|
var firstArg = process.argv[2];
|
|
13019
13230
|
if (!firstArg && !process.stdin.isTTY) {
|
|
13020
13231
|
const { default: childProcess } = await import("child_process");
|
|
13021
|
-
const nudgeScript =
|
|
13232
|
+
const nudgeScript = join25(__dirname6, "jpi.js");
|
|
13022
13233
|
const child = childProcess.spawnSync(process.execPath, [nudgeScript], {
|
|
13023
13234
|
stdio: ["inherit", "inherit", "inherit"]
|
|
13024
13235
|
});
|
|
@@ -13050,10 +13261,15 @@ if (!firstArg || firstArg === "help" || firstArg === "--help" || firstArg === "-
|
|
|
13050
13261
|
console.log(" terminalhire trajectory --push Opt-in: link your derived trajectory to your dashboard (typed-yes)");
|
|
13051
13262
|
console.log(" terminalhire trajectory --push --delete Unlink (revoke) your trajectory from the dashboard");
|
|
13052
13263
|
console.log(" terminalhire intro <github-login> Request a consented intro to another developer (typed-yes)");
|
|
13264
|
+
console.log(" terminalhire intro --list See your sent + received intros");
|
|
13265
|
+
console.log(" terminalhire intro --accept @<login> Accept a pending request by handle (or --decline)");
|
|
13053
13266
|
console.log(" terminalhire chat Inbox: one line per connection (presence \xB7 unread \xB7 last)");
|
|
13054
13267
|
console.log(" terminalhire chat <github-login> --read Read a thread inline (last 8; -n N / --all for depth)");
|
|
13055
13268
|
console.log(' terminalhire chat <github-login> --send "\u2026" Send one line to a connection (E2E encrypted)');
|
|
13056
13269
|
console.log(" terminalhire chat <github-login> Open the live E2E chat pane with an accepted connection");
|
|
13270
|
+
console.log(" terminalhire connect Connect family overview + inbound-nudge state");
|
|
13271
|
+
console.log(" terminalhire connect --mute Stop surfacing incoming connection requests in the spinner");
|
|
13272
|
+
console.log(" terminalhire connect --unmute Resume surfacing incoming connection requests");
|
|
13057
13273
|
console.log(" terminalhire link Connect this terminal to your terminalhire account");
|
|
13058
13274
|
console.log(" terminalhire link --logout Revoke + remove this terminal's linked session");
|
|
13059
13275
|
console.log(" terminalhire profile --show Display your encrypted local profile");
|
|
@@ -13089,7 +13305,15 @@ if (!firstArg || firstArg === "help" || firstArg === "--help" || firstArg === "-
|
|
|
13089
13305
|
process.exit(0);
|
|
13090
13306
|
}
|
|
13091
13307
|
if (firstArg === "--version" || firstArg === "-v") {
|
|
13092
|
-
|
|
13308
|
+
const local = readPackageVersion();
|
|
13309
|
+
console.log(`terminalhire v${local}`);
|
|
13310
|
+
try {
|
|
13311
|
+
const { cachedStaleNudge: cachedStaleNudge2 } = await Promise.resolve().then(() => (init_version_nudge(), version_nudge_exports));
|
|
13312
|
+
const nudge = cachedStaleNudge2(local);
|
|
13313
|
+
if (nudge) process.stderr.write(`${nudge}
|
|
13314
|
+
`);
|
|
13315
|
+
} catch {
|
|
13316
|
+
}
|
|
13093
13317
|
process.exit(0);
|
|
13094
13318
|
}
|
|
13095
13319
|
if (firstArg === "login" || firstArg === "logout") {
|
|
@@ -13145,6 +13369,11 @@ if (firstArg === "chat") {
|
|
|
13145
13369
|
await mod2.run();
|
|
13146
13370
|
process.exit(0);
|
|
13147
13371
|
}
|
|
13372
|
+
if (firstArg === "connect") {
|
|
13373
|
+
const mod2 = await Promise.resolve().then(() => (init_jpi_connect(), jpi_connect_exports));
|
|
13374
|
+
await mod2.run();
|
|
13375
|
+
process.exit(0);
|
|
13376
|
+
}
|
|
13148
13377
|
if (firstArg === "link") {
|
|
13149
13378
|
process.argv.splice(2, 1);
|
|
13150
13379
|
const mod2 = await Promise.resolve().then(() => (init_jpi_link(), jpi_link_exports));
|