terminalhire 0.10.0 → 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-dispatch.js +57 -12
- package/dist/bin/jpi-intro.js +55 -12
- package/dist/src/intro.js +54 -11
- package/package.json +1 -1
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -9732,11 +9732,21 @@ async function runIntroRequest(args5, overrides) {
|
|
|
9732
9732
|
deps.log(" shared only if they do.\n");
|
|
9733
9733
|
}
|
|
9734
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 ?? [];
|
|
9744
|
+
}
|
|
9735
9745
|
async function runIntroDecision(args5, overrides) {
|
|
9736
9746
|
const deps = { ...defaultIntroDeps(), ...overrides };
|
|
9737
|
-
|
|
9747
|
+
let id = args5.id?.trim() ?? "";
|
|
9738
9748
|
if (!id) {
|
|
9739
|
-
deps.errorLog("\n Usage: terminalhire intro --accept
|
|
9749
|
+
deps.errorLog("\n Usage: terminalhire intro --accept <@handle|id> | --decline <@handle|id>\n");
|
|
9740
9750
|
deps.exit(1);
|
|
9741
9751
|
return;
|
|
9742
9752
|
}
|
|
@@ -9747,19 +9757,51 @@ async function runIntroDecision(args5, overrides) {
|
|
|
9747
9757
|
deps.exit(0);
|
|
9748
9758
|
return;
|
|
9749
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
|
+
}
|
|
9750
9788
|
let contact = "";
|
|
9789
|
+
let shareHandle = false;
|
|
9751
9790
|
if (args5.action === "accept") {
|
|
9752
9791
|
const profile = await deps.readProfileContact();
|
|
9753
9792
|
contact = (args5.contact ?? profile.contactEmail ?? "").trim();
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
deps.
|
|
9758
|
-
|
|
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";
|
|
9759
9798
|
}
|
|
9760
9799
|
deps.log("");
|
|
9761
|
-
deps.log(" Accepting shares
|
|
9762
|
-
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
|
+
}
|
|
9763
9805
|
deps.log(" Nothing else is shared. Declining shares nothing.");
|
|
9764
9806
|
deps.log("");
|
|
9765
9807
|
const answer = await deps.prompt(' Type "yes" to accept and share your contact (anything else cancels): ');
|
|
@@ -9769,7 +9811,7 @@ async function runIntroDecision(args5, overrides) {
|
|
|
9769
9811
|
return;
|
|
9770
9812
|
}
|
|
9771
9813
|
}
|
|
9772
|
-
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" };
|
|
9773
9815
|
let res;
|
|
9774
9816
|
try {
|
|
9775
9817
|
res = await deps.fetchImpl(`${LINK_BASE2}/api/intro/accept`, {
|
|
@@ -9874,12 +9916,12 @@ async function runIntroList(overrides) {
|
|
|
9874
9916
|
if (it.note) deps.log(` note: ${it.note}`);
|
|
9875
9917
|
if (it.contact) deps.log(` contact: ${it.contact}`);
|
|
9876
9918
|
else if (it.role === "incoming" && it.status === "pending") {
|
|
9877
|
-
deps.log(` \u2192 accept: terminalhire intro --accept
|
|
9919
|
+
deps.log(` \u2192 accept: terminalhire intro --accept @${it.counterpartyLogin}`);
|
|
9878
9920
|
}
|
|
9879
9921
|
}
|
|
9880
9922
|
deps.log("");
|
|
9881
9923
|
}
|
|
9882
|
-
var LINK_BASE2, GH_SESSION_COOKIE2;
|
|
9924
|
+
var LINK_BASE2, GH_SESSION_COOKIE2, UUID_RE;
|
|
9883
9925
|
var init_intro2 = __esm({
|
|
9884
9926
|
"src/intro.ts"() {
|
|
9885
9927
|
"use strict";
|
|
@@ -9887,6 +9929,7 @@ var init_intro2 = __esm({
|
|
|
9887
9929
|
init_web_session();
|
|
9888
9930
|
LINK_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
9889
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;
|
|
9890
9933
|
}
|
|
9891
9934
|
});
|
|
9892
9935
|
|
|
@@ -13218,6 +13261,8 @@ if (!firstArg || firstArg === "help" || firstArg === "--help" || firstArg === "-
|
|
|
13218
13261
|
console.log(" terminalhire trajectory --push Opt-in: link your derived trajectory to your dashboard (typed-yes)");
|
|
13219
13262
|
console.log(" terminalhire trajectory --push --delete Unlink (revoke) your trajectory from the dashboard");
|
|
13220
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)");
|
|
13221
13266
|
console.log(" terminalhire chat Inbox: one line per connection (presence \xB7 unread \xB7 last)");
|
|
13222
13267
|
console.log(" terminalhire chat <github-login> --read Read a thread inline (last 8; -n N / --all for depth)");
|
|
13223
13268
|
console.log(' terminalhire chat <github-login> --send "\u2026" Send one line to a connection (E2E encrypted)');
|
package/dist/bin/jpi-intro.js
CHANGED
|
@@ -1258,11 +1258,21 @@ async function runIntroRequest(args, overrides) {
|
|
|
1258
1258
|
deps.log(" shared only if they do.\n");
|
|
1259
1259
|
}
|
|
1260
1260
|
}
|
|
1261
|
+
async function fetchIntros(deps, cookie) {
|
|
1262
|
+
const res = await deps.fetchImpl(`${LINK_BASE}/api/intro/list`, {
|
|
1263
|
+
method: "GET",
|
|
1264
|
+
headers: { Cookie: `${GH_SESSION_COOKIE}=${cookie}` },
|
|
1265
|
+
signal: AbortSignal.timeout(1e4)
|
|
1266
|
+
});
|
|
1267
|
+
if (!res.ok) throw new Error(`/api/intro/list returned ${res.status}`);
|
|
1268
|
+
const data = await res.json().catch(() => ({}));
|
|
1269
|
+
return data.intros ?? [];
|
|
1270
|
+
}
|
|
1261
1271
|
async function runIntroDecision(args, overrides) {
|
|
1262
1272
|
const deps = { ...defaultIntroDeps(), ...overrides };
|
|
1263
|
-
|
|
1273
|
+
let id = args.id?.trim() ?? "";
|
|
1264
1274
|
if (!id) {
|
|
1265
|
-
deps.errorLog("\n Usage: terminalhire intro --accept
|
|
1275
|
+
deps.errorLog("\n Usage: terminalhire intro --accept <@handle|id> | --decline <@handle|id>\n");
|
|
1266
1276
|
deps.exit(1);
|
|
1267
1277
|
return;
|
|
1268
1278
|
}
|
|
@@ -1273,19 +1283,51 @@ async function runIntroDecision(args, overrides) {
|
|
|
1273
1283
|
deps.exit(0);
|
|
1274
1284
|
return;
|
|
1275
1285
|
}
|
|
1286
|
+
if (!UUID_RE.test(id)) {
|
|
1287
|
+
const handle = id.replace(/^@/, "").toLowerCase();
|
|
1288
|
+
let intros;
|
|
1289
|
+
try {
|
|
1290
|
+
intros = await fetchIntros(deps, cookie);
|
|
1291
|
+
} catch (err) {
|
|
1292
|
+
deps.errorLog(`
|
|
1293
|
+
Could not look up the request: ${err instanceof Error ? err.message : String(err)}
|
|
1294
|
+
`);
|
|
1295
|
+
deps.exit(1);
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
const matches = intros.filter(
|
|
1299
|
+
(it) => it.role === "incoming" && it.status === "pending" && it.counterpartyLogin.toLowerCase() === handle
|
|
1300
|
+
);
|
|
1301
|
+
if (matches.length === 0) {
|
|
1302
|
+
deps.errorLog(`
|
|
1303
|
+
No pending connection request from @${handle}.`);
|
|
1304
|
+
deps.errorLog(" See your requests with `terminalhire intro --list`.\n");
|
|
1305
|
+
deps.exit(1);
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
if (matches.length > 1) {
|
|
1309
|
+
deps.errorLog(`
|
|
1310
|
+
${matches.length} pending requests from @${handle} \u2014 ${args.action === "accept" ? "accepting" : "declining"} one (the rest are redundant duplicates).`);
|
|
1311
|
+
}
|
|
1312
|
+
id = matches[0].id;
|
|
1313
|
+
}
|
|
1276
1314
|
let contact = "";
|
|
1315
|
+
let shareHandle = false;
|
|
1277
1316
|
if (args.action === "accept") {
|
|
1278
1317
|
const profile = await deps.readProfileContact();
|
|
1279
1318
|
contact = (args.contact ?? profile.contactEmail ?? "").trim();
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
deps.
|
|
1284
|
-
|
|
1319
|
+
shareHandle = contact.length === 0;
|
|
1320
|
+
let shareLabel = contact;
|
|
1321
|
+
if (shareHandle) {
|
|
1322
|
+
const login = await deps.readGithubLogin().catch(() => null);
|
|
1323
|
+
shareLabel = login ? `your GitHub handle (@${login})` : "your GitHub handle";
|
|
1285
1324
|
}
|
|
1286
1325
|
deps.log("");
|
|
1287
|
-
deps.log(" Accepting shares
|
|
1288
|
-
deps.log(` Your contact : ${
|
|
1326
|
+
deps.log(" Accepting shares a contact with the requester so they can reach you:");
|
|
1327
|
+
deps.log(` Your contact : ${shareLabel}`);
|
|
1328
|
+
if (shareHandle) {
|
|
1329
|
+
deps.log(" (share an email/handle instead with `--contact <email-or-handle>`)");
|
|
1330
|
+
}
|
|
1289
1331
|
deps.log(" Nothing else is shared. Declining shares nothing.");
|
|
1290
1332
|
deps.log("");
|
|
1291
1333
|
const answer = await deps.prompt(' Type "yes" to accept and share your contact (anything else cancels): ');
|
|
@@ -1295,7 +1337,7 @@ async function runIntroDecision(args, overrides) {
|
|
|
1295
1337
|
return;
|
|
1296
1338
|
}
|
|
1297
1339
|
}
|
|
1298
|
-
const body = args.action === "accept" ? { introId: id, action: "accept", targetContact: contact } : { introId: id, action: "decline" };
|
|
1340
|
+
const body = args.action === "accept" ? shareHandle ? { introId: id, action: "accept" } : { introId: id, action: "accept", targetContact: contact } : { introId: id, action: "decline" };
|
|
1299
1341
|
let res;
|
|
1300
1342
|
try {
|
|
1301
1343
|
res = await deps.fetchImpl(`${LINK_BASE}/api/intro/accept`, {
|
|
@@ -1400,12 +1442,12 @@ async function runIntroList(overrides) {
|
|
|
1400
1442
|
if (it.note) deps.log(` note: ${it.note}`);
|
|
1401
1443
|
if (it.contact) deps.log(` contact: ${it.contact}`);
|
|
1402
1444
|
else if (it.role === "incoming" && it.status === "pending") {
|
|
1403
|
-
deps.log(` \u2192 accept: terminalhire intro --accept
|
|
1445
|
+
deps.log(` \u2192 accept: terminalhire intro --accept @${it.counterpartyLogin}`);
|
|
1404
1446
|
}
|
|
1405
1447
|
}
|
|
1406
1448
|
deps.log("");
|
|
1407
1449
|
}
|
|
1408
|
-
var LINK_BASE, GH_SESSION_COOKIE;
|
|
1450
|
+
var LINK_BASE, GH_SESSION_COOKIE, UUID_RE;
|
|
1409
1451
|
var init_intro2 = __esm({
|
|
1410
1452
|
"src/intro.ts"() {
|
|
1411
1453
|
"use strict";
|
|
@@ -1413,6 +1455,7 @@ var init_intro2 = __esm({
|
|
|
1413
1455
|
init_web_session();
|
|
1414
1456
|
LINK_BASE = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
1415
1457
|
GH_SESSION_COOKIE = "__jpi_gh_session";
|
|
1458
|
+
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1416
1459
|
}
|
|
1417
1460
|
});
|
|
1418
1461
|
|
package/dist/src/intro.js
CHANGED
|
@@ -1251,11 +1251,22 @@ async function runIntroRequest(args, overrides) {
|
|
|
1251
1251
|
deps.log(" shared only if they do.\n");
|
|
1252
1252
|
}
|
|
1253
1253
|
}
|
|
1254
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1255
|
+
async function fetchIntros(deps, cookie) {
|
|
1256
|
+
const res = await deps.fetchImpl(`${LINK_BASE}/api/intro/list`, {
|
|
1257
|
+
method: "GET",
|
|
1258
|
+
headers: { Cookie: `${GH_SESSION_COOKIE}=${cookie}` },
|
|
1259
|
+
signal: AbortSignal.timeout(1e4)
|
|
1260
|
+
});
|
|
1261
|
+
if (!res.ok) throw new Error(`/api/intro/list returned ${res.status}`);
|
|
1262
|
+
const data = await res.json().catch(() => ({}));
|
|
1263
|
+
return data.intros ?? [];
|
|
1264
|
+
}
|
|
1254
1265
|
async function runIntroDecision(args, overrides) {
|
|
1255
1266
|
const deps = { ...defaultIntroDeps(), ...overrides };
|
|
1256
|
-
|
|
1267
|
+
let id = args.id?.trim() ?? "";
|
|
1257
1268
|
if (!id) {
|
|
1258
|
-
deps.errorLog("\n Usage: terminalhire intro --accept
|
|
1269
|
+
deps.errorLog("\n Usage: terminalhire intro --accept <@handle|id> | --decline <@handle|id>\n");
|
|
1259
1270
|
deps.exit(1);
|
|
1260
1271
|
return;
|
|
1261
1272
|
}
|
|
@@ -1266,19 +1277,51 @@ async function runIntroDecision(args, overrides) {
|
|
|
1266
1277
|
deps.exit(0);
|
|
1267
1278
|
return;
|
|
1268
1279
|
}
|
|
1280
|
+
if (!UUID_RE.test(id)) {
|
|
1281
|
+
const handle = id.replace(/^@/, "").toLowerCase();
|
|
1282
|
+
let intros;
|
|
1283
|
+
try {
|
|
1284
|
+
intros = await fetchIntros(deps, cookie);
|
|
1285
|
+
} catch (err) {
|
|
1286
|
+
deps.errorLog(`
|
|
1287
|
+
Could not look up the request: ${err instanceof Error ? err.message : String(err)}
|
|
1288
|
+
`);
|
|
1289
|
+
deps.exit(1);
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
const matches = intros.filter(
|
|
1293
|
+
(it) => it.role === "incoming" && it.status === "pending" && it.counterpartyLogin.toLowerCase() === handle
|
|
1294
|
+
);
|
|
1295
|
+
if (matches.length === 0) {
|
|
1296
|
+
deps.errorLog(`
|
|
1297
|
+
No pending connection request from @${handle}.`);
|
|
1298
|
+
deps.errorLog(" See your requests with `terminalhire intro --list`.\n");
|
|
1299
|
+
deps.exit(1);
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
if (matches.length > 1) {
|
|
1303
|
+
deps.errorLog(`
|
|
1304
|
+
${matches.length} pending requests from @${handle} \u2014 ${args.action === "accept" ? "accepting" : "declining"} one (the rest are redundant duplicates).`);
|
|
1305
|
+
}
|
|
1306
|
+
id = matches[0].id;
|
|
1307
|
+
}
|
|
1269
1308
|
let contact = "";
|
|
1309
|
+
let shareHandle = false;
|
|
1270
1310
|
if (args.action === "accept") {
|
|
1271
1311
|
const profile = await deps.readProfileContact();
|
|
1272
1312
|
contact = (args.contact ?? profile.contactEmail ?? "").trim();
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
deps.
|
|
1277
|
-
|
|
1313
|
+
shareHandle = contact.length === 0;
|
|
1314
|
+
let shareLabel = contact;
|
|
1315
|
+
if (shareHandle) {
|
|
1316
|
+
const login = await deps.readGithubLogin().catch(() => null);
|
|
1317
|
+
shareLabel = login ? `your GitHub handle (@${login})` : "your GitHub handle";
|
|
1278
1318
|
}
|
|
1279
1319
|
deps.log("");
|
|
1280
|
-
deps.log(" Accepting shares
|
|
1281
|
-
deps.log(` Your contact : ${
|
|
1320
|
+
deps.log(" Accepting shares a contact with the requester so they can reach you:");
|
|
1321
|
+
deps.log(` Your contact : ${shareLabel}`);
|
|
1322
|
+
if (shareHandle) {
|
|
1323
|
+
deps.log(" (share an email/handle instead with `--contact <email-or-handle>`)");
|
|
1324
|
+
}
|
|
1282
1325
|
deps.log(" Nothing else is shared. Declining shares nothing.");
|
|
1283
1326
|
deps.log("");
|
|
1284
1327
|
const answer = await deps.prompt(' Type "yes" to accept and share your contact (anything else cancels): ');
|
|
@@ -1288,7 +1331,7 @@ async function runIntroDecision(args, overrides) {
|
|
|
1288
1331
|
return;
|
|
1289
1332
|
}
|
|
1290
1333
|
}
|
|
1291
|
-
const body = args.action === "accept" ? { introId: id, action: "accept", targetContact: contact } : { introId: id, action: "decline" };
|
|
1334
|
+
const body = args.action === "accept" ? shareHandle ? { introId: id, action: "accept" } : { introId: id, action: "accept", targetContact: contact } : { introId: id, action: "decline" };
|
|
1292
1335
|
let res;
|
|
1293
1336
|
try {
|
|
1294
1337
|
res = await deps.fetchImpl(`${LINK_BASE}/api/intro/accept`, {
|
|
@@ -1393,7 +1436,7 @@ async function runIntroList(overrides) {
|
|
|
1393
1436
|
if (it.note) deps.log(` note: ${it.note}`);
|
|
1394
1437
|
if (it.contact) deps.log(` contact: ${it.contact}`);
|
|
1395
1438
|
else if (it.role === "incoming" && it.status === "pending") {
|
|
1396
|
-
deps.log(` \u2192 accept: terminalhire intro --accept
|
|
1439
|
+
deps.log(` \u2192 accept: terminalhire intro --accept @${it.counterpartyLogin}`);
|
|
1397
1440
|
}
|
|
1398
1441
|
}
|
|
1399
1442
|
deps.log("");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminalhire",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Local-first job matching for developers — ambient job matches in the Claude Code spinner. Matching runs on your machine; your profile never leaves it.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|