terminalhire 0.10.4 → 0.10.5
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 +22 -1
- package/dist/bin/jpi-chat.js +25 -4
- package/dist/bin/jpi-dispatch.js +51 -11
- package/dist/bin/jpi-refresh.js +20 -1
- package/dist/bin/jpi.js +18 -2
- package/package.json +1 -1
|
@@ -4290,6 +4290,22 @@ function writeReadCursor(login, iso, deps = {}) {
|
|
|
4290
4290
|
mkdirSync6(TERMINALHIRE_DIR5, { recursive: true });
|
|
4291
4291
|
writeFileSync6(READS_FILE, JSON.stringify(cursors, null, 2), { mode: 384, encoding: "utf8" });
|
|
4292
4292
|
}
|
|
4293
|
+
async function postReadCursor(peerLogin, lastReadAt, deps = {}) {
|
|
4294
|
+
const readCookie = deps.readCookie ?? readWebSessionCookie;
|
|
4295
|
+
const cookie = readCookie();
|
|
4296
|
+
if (!cookie) return;
|
|
4297
|
+
try {
|
|
4298
|
+
await fetch(`${CHAT_BASE3}/api/chat/read-cursor`, {
|
|
4299
|
+
method: "POST",
|
|
4300
|
+
headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
|
|
4301
|
+
body: JSON.stringify({ peerLogin, lastReadAt }),
|
|
4302
|
+
// Best-effort cross-device sync — not latency-sensitive, so a short bound
|
|
4303
|
+
// keeps a cold/unreachable server from stalling the reader's exit.
|
|
4304
|
+
signal: AbortSignal.timeout(2500)
|
|
4305
|
+
});
|
|
4306
|
+
} catch {
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4293
4309
|
function formatClock(iso) {
|
|
4294
4310
|
const d = new Date(iso);
|
|
4295
4311
|
if (Number.isNaN(d.getTime())) return "--:--";
|
|
@@ -4469,6 +4485,7 @@ async function runReadThread(opts = {}) {
|
|
|
4469
4485
|
client = createChatClient(),
|
|
4470
4486
|
resolveConnection = defaultResolveConnection,
|
|
4471
4487
|
writeCursor = writeReadCursor,
|
|
4488
|
+
syncCursor = postReadCursor,
|
|
4472
4489
|
ensureDisclosure = ensureChatDisclosure
|
|
4473
4490
|
} = opts;
|
|
4474
4491
|
const target = String(login ?? "").replace(/^@/, "").trim();
|
|
@@ -4514,6 +4531,7 @@ async function runReadThread(opts = {}) {
|
|
|
4514
4531
|
writeCursor(peerLogin, newest.createdAt);
|
|
4515
4532
|
} catch {
|
|
4516
4533
|
}
|
|
4534
|
+
await syncCursor(peerLogin, newest.createdAt);
|
|
4517
4535
|
}
|
|
4518
4536
|
}
|
|
4519
4537
|
return { ok: true, shown: shownMessages.length, total };
|
|
@@ -4561,12 +4579,14 @@ async function runSend(opts = {}) {
|
|
|
4561
4579
|
);
|
|
4562
4580
|
return { ok: true };
|
|
4563
4581
|
}
|
|
4564
|
-
var CHAT_BASE3, TERMINALHIRE_DIR5, READS_FILE;
|
|
4582
|
+
var CHAT_BASE3, GH_SESSION_COOKIE3, TERMINALHIRE_DIR5, READS_FILE;
|
|
4565
4583
|
var init_jpi_chat_read = __esm({
|
|
4566
4584
|
"bin/jpi-chat-read.js"() {
|
|
4567
4585
|
init_chat_client();
|
|
4586
|
+
init_web_session();
|
|
4568
4587
|
init_jpi_chat();
|
|
4569
4588
|
CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
4589
|
+
GH_SESSION_COOKIE3 = "__jpi_gh_session";
|
|
4570
4590
|
TERMINALHIRE_DIR5 = join7(homedir6(), ".terminalhire");
|
|
4571
4591
|
READS_FILE = join7(TERMINALHIRE_DIR5, "chat-reads.json");
|
|
4572
4592
|
}
|
|
@@ -4575,6 +4595,7 @@ init_jpi_chat_read();
|
|
|
4575
4595
|
export {
|
|
4576
4596
|
formatClock,
|
|
4577
4597
|
formatStamp,
|
|
4598
|
+
postReadCursor,
|
|
4578
4599
|
readReadCursors,
|
|
4579
4600
|
renderInbox,
|
|
4580
4601
|
renderThread,
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -4167,6 +4167,7 @@ var jpi_chat_read_exports = {};
|
|
|
4167
4167
|
__export(jpi_chat_read_exports, {
|
|
4168
4168
|
formatClock: () => formatClock,
|
|
4169
4169
|
formatStamp: () => formatStamp,
|
|
4170
|
+
postReadCursor: () => postReadCursor,
|
|
4170
4171
|
readReadCursors: () => readReadCursors,
|
|
4171
4172
|
renderInbox: () => renderInbox,
|
|
4172
4173
|
renderThread: () => renderThread,
|
|
@@ -4199,6 +4200,22 @@ function writeReadCursor(login, iso, deps = {}) {
|
|
|
4199
4200
|
mkdirSync6(TERMINALHIRE_DIR5, { recursive: true });
|
|
4200
4201
|
writeFileSync6(READS_FILE, JSON.stringify(cursors, null, 2), { mode: 384, encoding: "utf8" });
|
|
4201
4202
|
}
|
|
4203
|
+
async function postReadCursor(peerLogin, lastReadAt, deps = {}) {
|
|
4204
|
+
const readCookie = deps.readCookie ?? readWebSessionCookie;
|
|
4205
|
+
const cookie = readCookie();
|
|
4206
|
+
if (!cookie) return;
|
|
4207
|
+
try {
|
|
4208
|
+
await fetch(`${CHAT_BASE2}/api/chat/read-cursor`, {
|
|
4209
|
+
method: "POST",
|
|
4210
|
+
headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE2}=${cookie}` },
|
|
4211
|
+
body: JSON.stringify({ peerLogin, lastReadAt }),
|
|
4212
|
+
// Best-effort cross-device sync — not latency-sensitive, so a short bound
|
|
4213
|
+
// keeps a cold/unreachable server from stalling the reader's exit.
|
|
4214
|
+
signal: AbortSignal.timeout(2500)
|
|
4215
|
+
});
|
|
4216
|
+
} catch {
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4202
4219
|
function formatClock(iso) {
|
|
4203
4220
|
const d = new Date(iso);
|
|
4204
4221
|
if (Number.isNaN(d.getTime())) return "--:--";
|
|
@@ -4378,6 +4395,7 @@ async function runReadThread(opts = {}) {
|
|
|
4378
4395
|
client = createChatClient(),
|
|
4379
4396
|
resolveConnection = defaultResolveConnection,
|
|
4380
4397
|
writeCursor = writeReadCursor,
|
|
4398
|
+
syncCursor = postReadCursor,
|
|
4381
4399
|
ensureDisclosure = ensureChatDisclosure
|
|
4382
4400
|
} = opts;
|
|
4383
4401
|
const target = String(login ?? "").replace(/^@/, "").trim();
|
|
@@ -4423,6 +4441,7 @@ async function runReadThread(opts = {}) {
|
|
|
4423
4441
|
writeCursor(peerLogin, newest.createdAt);
|
|
4424
4442
|
} catch {
|
|
4425
4443
|
}
|
|
4444
|
+
await syncCursor(peerLogin, newest.createdAt);
|
|
4426
4445
|
}
|
|
4427
4446
|
}
|
|
4428
4447
|
return { ok: true, shown: shownMessages.length, total };
|
|
@@ -4470,13 +4489,15 @@ async function runSend(opts = {}) {
|
|
|
4470
4489
|
);
|
|
4471
4490
|
return { ok: true };
|
|
4472
4491
|
}
|
|
4473
|
-
var CHAT_BASE2, TERMINALHIRE_DIR5, READS_FILE;
|
|
4492
|
+
var CHAT_BASE2, GH_SESSION_COOKIE2, TERMINALHIRE_DIR5, READS_FILE;
|
|
4474
4493
|
var init_jpi_chat_read = __esm({
|
|
4475
4494
|
"bin/jpi-chat-read.js"() {
|
|
4476
4495
|
"use strict";
|
|
4477
4496
|
init_chat_client();
|
|
4497
|
+
init_web_session();
|
|
4478
4498
|
init_jpi_chat();
|
|
4479
4499
|
CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
4500
|
+
GH_SESSION_COOKIE2 = "__jpi_gh_session";
|
|
4480
4501
|
TERMINALHIRE_DIR5 = join7(homedir6(), ".terminalhire");
|
|
4481
4502
|
READS_FILE = join7(TERMINALHIRE_DIR5, "chat-reads.json");
|
|
4482
4503
|
}
|
|
@@ -4538,7 +4559,7 @@ async function fetchIntroList(deps = {}) {
|
|
|
4538
4559
|
try {
|
|
4539
4560
|
res = await fetchImpl(`${CHAT_BASE3}/api/intro/list`, {
|
|
4540
4561
|
method: "GET",
|
|
4541
|
-
headers: { Cookie: `${
|
|
4562
|
+
headers: { Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
|
|
4542
4563
|
signal: AbortSignal.timeout(1e4)
|
|
4543
4564
|
});
|
|
4544
4565
|
} catch (err) {
|
|
@@ -5080,14 +5101,14 @@ async function run() {
|
|
|
5080
5101
|
process.exit(1);
|
|
5081
5102
|
}
|
|
5082
5103
|
}
|
|
5083
|
-
var CHAT_BASE3,
|
|
5104
|
+
var CHAT_BASE3, GH_SESSION_COOKIE3, HIDE_CURSOR, SHOW_CURSOR, CLEAR, KEY_CTRL_C, KEY_CTRL_S, KEY_ENTER_A, KEY_ENTER_B, KEY_BACKSPACE_A, KEY_BACKSPACE_B, MAX_INPUT_LEN, ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, DEPOSIT_CTA;
|
|
5084
5105
|
var init_jpi_chat = __esm({
|
|
5085
5106
|
"bin/jpi-chat.js"() {
|
|
5086
5107
|
init_chat_client();
|
|
5087
5108
|
init_config();
|
|
5088
5109
|
init_web_session();
|
|
5089
5110
|
CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
5090
|
-
|
|
5111
|
+
GH_SESSION_COOKIE3 = "__jpi_gh_session";
|
|
5091
5112
|
HIDE_CURSOR = "\x1B[?25l";
|
|
5092
5113
|
SHOW_CURSOR = "\x1B[?25h";
|
|
5093
5114
|
CLEAR = "\x1B[2J\x1B[H";
|
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -10289,6 +10289,7 @@ var jpi_chat_read_exports = {};
|
|
|
10289
10289
|
__export(jpi_chat_read_exports, {
|
|
10290
10290
|
formatClock: () => formatClock,
|
|
10291
10291
|
formatStamp: () => formatStamp,
|
|
10292
|
+
postReadCursor: () => postReadCursor,
|
|
10292
10293
|
readReadCursors: () => readReadCursors,
|
|
10293
10294
|
renderInbox: () => renderInbox,
|
|
10294
10295
|
renderThread: () => renderThread,
|
|
@@ -10321,6 +10322,22 @@ function writeReadCursor(login, iso, deps = {}) {
|
|
|
10321
10322
|
mkdirSync13(TERMINALHIRE_DIR12, { recursive: true });
|
|
10322
10323
|
writeFileSync13(READS_FILE, JSON.stringify(cursors, null, 2), { mode: 384, encoding: "utf8" });
|
|
10323
10324
|
}
|
|
10325
|
+
async function postReadCursor(peerLogin, lastReadAt, deps = {}) {
|
|
10326
|
+
const readCookie = deps.readCookie ?? readWebSessionCookie;
|
|
10327
|
+
const cookie = readCookie();
|
|
10328
|
+
if (!cookie) return;
|
|
10329
|
+
try {
|
|
10330
|
+
await fetch(`${CHAT_BASE2}/api/chat/read-cursor`, {
|
|
10331
|
+
method: "POST",
|
|
10332
|
+
headers: { "Content-Type": "application/json", Cookie: `${GH_SESSION_COOKIE4}=${cookie}` },
|
|
10333
|
+
body: JSON.stringify({ peerLogin, lastReadAt }),
|
|
10334
|
+
// Best-effort cross-device sync — not latency-sensitive, so a short bound
|
|
10335
|
+
// keeps a cold/unreachable server from stalling the reader's exit.
|
|
10336
|
+
signal: AbortSignal.timeout(2500)
|
|
10337
|
+
});
|
|
10338
|
+
} catch {
|
|
10339
|
+
}
|
|
10340
|
+
}
|
|
10324
10341
|
function formatClock(iso) {
|
|
10325
10342
|
const d = new Date(iso);
|
|
10326
10343
|
if (Number.isNaN(d.getTime())) return "--:--";
|
|
@@ -10500,6 +10517,7 @@ async function runReadThread(opts = {}) {
|
|
|
10500
10517
|
client = createChatClient(),
|
|
10501
10518
|
resolveConnection = defaultResolveConnection,
|
|
10502
10519
|
writeCursor = writeReadCursor,
|
|
10520
|
+
syncCursor = postReadCursor,
|
|
10503
10521
|
ensureDisclosure = ensureChatDisclosure
|
|
10504
10522
|
} = opts;
|
|
10505
10523
|
const target = String(login ?? "").replace(/^@/, "").trim();
|
|
@@ -10545,6 +10563,7 @@ async function runReadThread(opts = {}) {
|
|
|
10545
10563
|
writeCursor(peerLogin, newest.createdAt);
|
|
10546
10564
|
} catch {
|
|
10547
10565
|
}
|
|
10566
|
+
await syncCursor(peerLogin, newest.createdAt);
|
|
10548
10567
|
}
|
|
10549
10568
|
}
|
|
10550
10569
|
return { ok: true, shown: shownMessages.length, total };
|
|
@@ -10592,13 +10611,15 @@ async function runSend(opts = {}) {
|
|
|
10592
10611
|
);
|
|
10593
10612
|
return { ok: true };
|
|
10594
10613
|
}
|
|
10595
|
-
var CHAT_BASE2, TERMINALHIRE_DIR12, READS_FILE;
|
|
10614
|
+
var CHAT_BASE2, GH_SESSION_COOKIE4, TERMINALHIRE_DIR12, READS_FILE;
|
|
10596
10615
|
var init_jpi_chat_read = __esm({
|
|
10597
10616
|
"bin/jpi-chat-read.js"() {
|
|
10598
10617
|
"use strict";
|
|
10599
10618
|
init_chat_client();
|
|
10619
|
+
init_web_session();
|
|
10600
10620
|
init_jpi_chat();
|
|
10601
10621
|
CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
10622
|
+
GH_SESSION_COOKIE4 = "__jpi_gh_session";
|
|
10602
10623
|
TERMINALHIRE_DIR12 = join16(homedir15(), ".terminalhire");
|
|
10603
10624
|
READS_FILE = join16(TERMINALHIRE_DIR12, "chat-reads.json");
|
|
10604
10625
|
}
|
|
@@ -10675,7 +10696,7 @@ async function fetchIntroList(deps = {}) {
|
|
|
10675
10696
|
try {
|
|
10676
10697
|
res = await fetchImpl(`${CHAT_BASE3}/api/intro/list`, {
|
|
10677
10698
|
method: "GET",
|
|
10678
|
-
headers: { Cookie: `${
|
|
10699
|
+
headers: { Cookie: `${GH_SESSION_COOKIE5}=${cookie}` },
|
|
10679
10700
|
signal: AbortSignal.timeout(1e4)
|
|
10680
10701
|
});
|
|
10681
10702
|
} catch (err) {
|
|
@@ -11217,7 +11238,7 @@ async function run9() {
|
|
|
11217
11238
|
process.exit(1);
|
|
11218
11239
|
}
|
|
11219
11240
|
}
|
|
11220
|
-
var CHAT_BASE3,
|
|
11241
|
+
var CHAT_BASE3, GH_SESSION_COOKIE5, HIDE_CURSOR, SHOW_CURSOR, CLEAR, KEY_CTRL_C, KEY_CTRL_S, KEY_ENTER_A, KEY_ENTER_B, KEY_BACKSPACE_A, KEY_BACKSPACE_B, MAX_INPUT_LEN, ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, DEPOSIT_CTA;
|
|
11221
11242
|
var init_jpi_chat = __esm({
|
|
11222
11243
|
"bin/jpi-chat.js"() {
|
|
11223
11244
|
"use strict";
|
|
@@ -11225,7 +11246,7 @@ var init_jpi_chat = __esm({
|
|
|
11225
11246
|
init_config();
|
|
11226
11247
|
init_web_session();
|
|
11227
11248
|
CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
11228
|
-
|
|
11249
|
+
GH_SESSION_COOKIE5 = "__jpi_gh_session";
|
|
11229
11250
|
HIDE_CURSOR = "\x1B[?25l";
|
|
11230
11251
|
SHOW_CURSOR = "\x1B[?25h";
|
|
11231
11252
|
CLEAR = "\x1B[2J\x1B[H";
|
|
@@ -11431,7 +11452,7 @@ async function runLinkLogout(overrides) {
|
|
|
11431
11452
|
try {
|
|
11432
11453
|
const res = await deps.fetchImpl(`${LINK_BASE3}/api/auth/session`, {
|
|
11433
11454
|
method: "DELETE",
|
|
11434
|
-
headers: { Cookie: `${
|
|
11455
|
+
headers: { Cookie: `${GH_SESSION_COOKIE6}=${token}` },
|
|
11435
11456
|
signal: AbortSignal.timeout(1e4)
|
|
11436
11457
|
});
|
|
11437
11458
|
revoked = res.ok;
|
|
@@ -11446,14 +11467,14 @@ async function runLinkLogout(overrides) {
|
|
|
11446
11467
|
}
|
|
11447
11468
|
deps.exit(0);
|
|
11448
11469
|
}
|
|
11449
|
-
var LINK_BASE3,
|
|
11470
|
+
var LINK_BASE3, GH_SESSION_COOKIE6, LINK_TIMEOUT_MS, LINKED_HTML, FAILED_HTML;
|
|
11450
11471
|
var init_link = __esm({
|
|
11451
11472
|
"src/link.ts"() {
|
|
11452
11473
|
"use strict";
|
|
11453
11474
|
init_web_session();
|
|
11454
11475
|
init_config();
|
|
11455
11476
|
LINK_BASE3 = "https://www.terminalhire.com";
|
|
11456
|
-
|
|
11477
|
+
GH_SESSION_COOKIE6 = "__jpi_gh_session";
|
|
11457
11478
|
LINK_TIMEOUT_MS = 12e4;
|
|
11458
11479
|
LINKED_HTML = `<!doctype html><html><head><meta charset="utf-8"><title>terminalhire</title></head>
|
|
11459
11480
|
<body style="font-family:system-ui;padding:2rem;background:#0b0d10;color:#e6e6e6">
|
|
@@ -13071,7 +13092,7 @@ async function run18() {
|
|
|
13071
13092
|
if (sessionCookie && !isInboundNudgeMuted()) try {
|
|
13072
13093
|
const res = await fetch(`${API_URL6}/api/intro/list`, {
|
|
13073
13094
|
method: "GET",
|
|
13074
|
-
headers: { Cookie: `${
|
|
13095
|
+
headers: { Cookie: `${GH_SESSION_COOKIE7}=${sessionCookie}` },
|
|
13075
13096
|
signal: AbortSignal.timeout(1e4)
|
|
13076
13097
|
});
|
|
13077
13098
|
if (res.ok) {
|
|
@@ -13082,6 +13103,24 @@ async function run18() {
|
|
|
13082
13103
|
}
|
|
13083
13104
|
} catch {
|
|
13084
13105
|
}
|
|
13106
|
+
let unreadChat = { count: 0 };
|
|
13107
|
+
if (sessionCookie && !isInboundNudgeMuted()) try {
|
|
13108
|
+
const res = await fetch(`${API_URL6}/api/chat/inbox`, {
|
|
13109
|
+
method: "GET",
|
|
13110
|
+
headers: { Cookie: `${GH_SESSION_COOKIE7}=${sessionCookie}` },
|
|
13111
|
+
signal: AbortSignal.timeout(1e4)
|
|
13112
|
+
});
|
|
13113
|
+
if (res.ok) {
|
|
13114
|
+
const body = await res.json();
|
|
13115
|
+
const inbox = Array.isArray(body?.inbox) ? body.inbox : [];
|
|
13116
|
+
const total = inbox.reduce(
|
|
13117
|
+
(sum, it) => sum + (it && typeof it.unreadCount === "number" && it.unreadCount > 0 ? it.unreadCount : 0),
|
|
13118
|
+
0
|
|
13119
|
+
);
|
|
13120
|
+
unreadChat = { count: total };
|
|
13121
|
+
}
|
|
13122
|
+
} catch {
|
|
13123
|
+
}
|
|
13085
13124
|
mkdirSync17(TERMINALHIRE_DIR14, { recursive: true });
|
|
13086
13125
|
const cacheEntry = {
|
|
13087
13126
|
ts: Date.now(),
|
|
@@ -13089,7 +13128,8 @@ async function run18() {
|
|
|
13089
13128
|
matchCount,
|
|
13090
13129
|
topMatches,
|
|
13091
13130
|
topPeers,
|
|
13092
|
-
incomingPending
|
|
13131
|
+
incomingPending,
|
|
13132
|
+
unreadChat
|
|
13093
13133
|
};
|
|
13094
13134
|
writeFileSync17(INDEX_CACHE_FILE5, JSON.stringify(cacheEntry), "utf8");
|
|
13095
13135
|
try {
|
|
@@ -13142,14 +13182,14 @@ async function run18() {
|
|
|
13142
13182
|
process.exit(1);
|
|
13143
13183
|
}
|
|
13144
13184
|
}
|
|
13145
|
-
var
|
|
13185
|
+
var GH_SESSION_COOKIE7, __dirname4, TERMINALHIRE_DIR14, INDEX_CACHE_FILE5, API_URL6;
|
|
13146
13186
|
var init_jpi_refresh = __esm({
|
|
13147
13187
|
"bin/jpi-refresh.js"() {
|
|
13148
13188
|
"use strict";
|
|
13149
13189
|
init_directory2();
|
|
13150
13190
|
init_config();
|
|
13151
13191
|
init_web_session();
|
|
13152
|
-
|
|
13192
|
+
GH_SESSION_COOKIE7 = "__jpi_gh_session";
|
|
13153
13193
|
__dirname4 = fileURLToPath5(new URL(".", import.meta.url));
|
|
13154
13194
|
TERMINALHIRE_DIR14 = join23(homedir21(), ".terminalhire");
|
|
13155
13195
|
INDEX_CACHE_FILE5 = join23(TERMINALHIRE_DIR14, "index-cache.json");
|
package/dist/bin/jpi-refresh.js
CHANGED
|
@@ -7094,6 +7094,24 @@ async function run() {
|
|
|
7094
7094
|
}
|
|
7095
7095
|
} catch {
|
|
7096
7096
|
}
|
|
7097
|
+
let unreadChat = { count: 0 };
|
|
7098
|
+
if (sessionCookie && !isInboundNudgeMuted()) try {
|
|
7099
|
+
const res = await fetch(`${API_URL2}/api/chat/inbox`, {
|
|
7100
|
+
method: "GET",
|
|
7101
|
+
headers: { Cookie: `${GH_SESSION_COOKIE}=${sessionCookie}` },
|
|
7102
|
+
signal: AbortSignal.timeout(1e4)
|
|
7103
|
+
});
|
|
7104
|
+
if (res.ok) {
|
|
7105
|
+
const body = await res.json();
|
|
7106
|
+
const inbox = Array.isArray(body?.inbox) ? body.inbox : [];
|
|
7107
|
+
const total = inbox.reduce(
|
|
7108
|
+
(sum, it) => sum + (it && typeof it.unreadCount === "number" && it.unreadCount > 0 ? it.unreadCount : 0),
|
|
7109
|
+
0
|
|
7110
|
+
);
|
|
7111
|
+
unreadChat = { count: total };
|
|
7112
|
+
}
|
|
7113
|
+
} catch {
|
|
7114
|
+
}
|
|
7097
7115
|
mkdirSync6(TERMINALHIRE_DIR4, { recursive: true });
|
|
7098
7116
|
const cacheEntry = {
|
|
7099
7117
|
ts: Date.now(),
|
|
@@ -7101,7 +7119,8 @@ async function run() {
|
|
|
7101
7119
|
matchCount,
|
|
7102
7120
|
topMatches,
|
|
7103
7121
|
topPeers,
|
|
7104
|
-
incomingPending
|
|
7122
|
+
incomingPending,
|
|
7123
|
+
unreadChat
|
|
7105
7124
|
};
|
|
7106
7125
|
writeFileSync6(INDEX_CACHE_FILE2, JSON.stringify(cacheEntry), "utf8");
|
|
7107
7126
|
try {
|
package/dist/bin/jpi.js
CHANGED
|
@@ -94,6 +94,17 @@ function getCachedIncomingCount() {
|
|
|
94
94
|
return 0;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
+
function getCachedUnreadChatCount() {
|
|
98
|
+
try {
|
|
99
|
+
const raw = readFileSync(INDEX_CACHE_FILE, "utf8");
|
|
100
|
+
const entry = JSON.parse(raw);
|
|
101
|
+
if (Date.now() - entry.ts > INDEX_CACHE_TTL_MS) return 0;
|
|
102
|
+
const n = entry.unreadChat && entry.unreadChat.count;
|
|
103
|
+
return typeof n === "number" && n > 0 ? n : 0;
|
|
104
|
+
} catch {
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
97
108
|
function getNudgeMode() {
|
|
98
109
|
const envVal = process.env["TERMINALHIRE_NUDGE"];
|
|
99
110
|
if (envVal) {
|
|
@@ -166,8 +177,9 @@ try {
|
|
|
166
177
|
}
|
|
167
178
|
const matchCount = getCachedMatchCount();
|
|
168
179
|
const incomingCount = getCachedIncomingCount();
|
|
180
|
+
const unreadChatCount = getCachedUnreadChatCount();
|
|
169
181
|
const haveRoles = matchCount !== null && matchCount > 0;
|
|
170
|
-
if (!haveRoles && incomingCount === 0) process.exit(0);
|
|
182
|
+
if (!haveRoles && incomingCount === 0 && unreadChatCount === 0) process.exit(0);
|
|
171
183
|
const nudgeMode = getNudgeMode();
|
|
172
184
|
if (!shouldNudge(nudgeMode, sessionId)) process.exit(0);
|
|
173
185
|
let line;
|
|
@@ -175,8 +187,12 @@ try {
|
|
|
175
187
|
const plural = matchCount === 1 ? "role" : "roles";
|
|
176
188
|
line = `\u2726 ${matchCount} ${plural} match your current work \u2014 run: terminalhire jobs`;
|
|
177
189
|
if (incomingCount > 0) line += ` \xB7 \u2709 ${incomingCount} waiting to connect`;
|
|
178
|
-
}
|
|
190
|
+
if (unreadChatCount > 0) line += ` \xB7 \u{1F4AC} ${unreadChatCount} unread`;
|
|
191
|
+
} else if (incomingCount > 0) {
|
|
179
192
|
line = `\u2709 ${incomingCount} waiting to connect \u2014 run: terminalhire intro --list`;
|
|
193
|
+
if (unreadChatCount > 0) line += ` \xB7 \u{1F4AC} ${unreadChatCount} unread`;
|
|
194
|
+
} else {
|
|
195
|
+
line = `\u{1F4AC} ${unreadChatCount} unread \u2014 run: terminalhire chat`;
|
|
180
196
|
}
|
|
181
197
|
process.stdout.write(line + "\n");
|
|
182
198
|
if (nudgeMode === "session") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminalhire",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
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",
|