terminalhire 0.11.0 → 0.11.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 +37 -27
- package/dist/bin/jpi-chat.js +8 -27
- package/dist/bin/jpi-dispatch.js +8 -27
- package/package.json +1 -1
|
@@ -4278,6 +4278,35 @@ async function defaultListPendingInvites(deps = {}) {
|
|
|
4278
4278
|
const invites = listed.intros.filter((it) => it && it.role === "incoming" && it.status === "pending" && it.counterpartyLogin).map((it) => ({ login: it.counterpartyLogin }));
|
|
4279
4279
|
return { status: "ok", invites };
|
|
4280
4280
|
}
|
|
4281
|
+
function relativeTime(then, now = /* @__PURE__ */ new Date()) {
|
|
4282
|
+
const t = new Date(then).getTime();
|
|
4283
|
+
if (Number.isNaN(t)) return "";
|
|
4284
|
+
const deltaMs = Math.max(0, now.getTime() - t);
|
|
4285
|
+
const sec = Math.floor(deltaMs / 1e3);
|
|
4286
|
+
if (sec < 60) return "just now";
|
|
4287
|
+
const min = Math.floor(sec / 60);
|
|
4288
|
+
if (min < 60) return `${Math.max(1, min)}m ago`;
|
|
4289
|
+
const hr = Math.floor(min / 60);
|
|
4290
|
+
if (hr < 24) return `${hr}h ago`;
|
|
4291
|
+
const day = Math.floor(hr / 24);
|
|
4292
|
+
if (day < 7) return `${day}d ago`;
|
|
4293
|
+
const wk = Math.floor(day / 7);
|
|
4294
|
+
if (wk < 5) return `${wk}w ago`;
|
|
4295
|
+
return "a while ago";
|
|
4296
|
+
}
|
|
4297
|
+
function formatPresence(presence, now = /* @__PURE__ */ new Date()) {
|
|
4298
|
+
if (!presence) return "\u25CB not on chat yet";
|
|
4299
|
+
const share = presence.shareActivity === true;
|
|
4300
|
+
const seenMs = share && presence.lastSeen ? new Date(presence.lastSeen).getTime() : NaN;
|
|
4301
|
+
const hasSeen = !Number.isNaN(seenMs);
|
|
4302
|
+
const fresh = hasSeen && now.getTime() - seenMs <= ACTIVE_WINDOW_MS;
|
|
4303
|
+
if (share && presence.optin === true && fresh) return "\u25CF active now";
|
|
4304
|
+
if (share && hasSeen) {
|
|
4305
|
+
const rel = relativeTime(presence.lastSeen, now);
|
|
4306
|
+
return rel ? `\u25D0 reachable \xB7 seen ${rel}` : "\u25D0 reachable";
|
|
4307
|
+
}
|
|
4308
|
+
return "\u25D0 reachable";
|
|
4309
|
+
}
|
|
4281
4310
|
var CHAT_BASE2, GH_SESSION_COOKIE2, ANSI_CSI, ANSI_OSC, ANSI_OTHER, C0_C1_DEL, CHAT_DISCLOSURE, CHAT_AT_REST, CHAT_CODE_OF_CONDUCT, CHAT_MIN_AGE, ACTIVE_WINDOW_MS;
|
|
4282
4311
|
var init_jpi_chat = __esm({
|
|
4283
4312
|
"bin/jpi-chat.js"() {
|
|
@@ -4404,7 +4433,7 @@ function renderInbox(items, invites = []) {
|
|
|
4404
4433
|
lines.push(" (no accepted connections yet \u2014 request one: terminalhire intro <login>)");
|
|
4405
4434
|
} else {
|
|
4406
4435
|
for (const it of items) {
|
|
4407
|
-
const dot = it.
|
|
4436
|
+
const dot = formatPresence(it.presence).charAt(0);
|
|
4408
4437
|
const unread = it.unread > 0 ? `\u2709 ${it.unread}` : "\u2014";
|
|
4409
4438
|
const login = `@${sanitizeLine(it.login)}`;
|
|
4410
4439
|
const stamp = sanitizeLine(it.lastStamp || "");
|
|
@@ -4419,13 +4448,12 @@ function renderInbox(items, invites = []) {
|
|
|
4419
4448
|
return lines.join("\n") + "\n";
|
|
4420
4449
|
}
|
|
4421
4450
|
function renderThread(state) {
|
|
4422
|
-
const { peerLogin,
|
|
4451
|
+
const { peerLogin, presence, safety, messages, total } = state;
|
|
4423
4452
|
const safePeer = sanitizeLine(peerLogin);
|
|
4424
|
-
const
|
|
4425
|
-
const presence = online ? "online" : "offline";
|
|
4453
|
+
const status = formatPresence(presence);
|
|
4426
4454
|
const lines = [];
|
|
4427
4455
|
lines.push(
|
|
4428
|
-
` @${safePeer} ${
|
|
4456
|
+
` @${safePeer} ${status}` + (safety ? ` \xB7 safety# ${sanitizeLine(safety)}` : "")
|
|
4429
4457
|
);
|
|
4430
4458
|
lines.push(" " + "\u2500".repeat(64));
|
|
4431
4459
|
if (!messages || messages.length === 0) {
|
|
@@ -4475,21 +4503,6 @@ function writeProblem(output, result, target) {
|
|
|
4475
4503
|
return "error";
|
|
4476
4504
|
}
|
|
4477
4505
|
}
|
|
4478
|
-
async function readPresence(client, peerLogin) {
|
|
4479
|
-
if (typeof client.getPeerPresence !== "function") return false;
|
|
4480
|
-
try {
|
|
4481
|
-
return await client.getPeerPresence(peerLogin) != null;
|
|
4482
|
-
} catch {
|
|
4483
|
-
return false;
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
async function clearPresence(client) {
|
|
4487
|
-
if (typeof client.heartbeat !== "function") return;
|
|
4488
|
-
try {
|
|
4489
|
-
await client.heartbeat(false);
|
|
4490
|
-
} catch {
|
|
4491
|
-
}
|
|
4492
|
-
}
|
|
4493
4506
|
async function gateDisclosure(ensureDisclosure, input, output) {
|
|
4494
4507
|
const ack = await ensureDisclosure({ input, output });
|
|
4495
4508
|
if (!ack.acknowledged) {
|
|
@@ -4537,16 +4550,14 @@ async function runInbox(opts = {}) {
|
|
|
4537
4550
|
(m) => m.senderLogin === conn.peerLogin && (!cursor || m.createdAt > cursor)
|
|
4538
4551
|
).length;
|
|
4539
4552
|
const last = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
4540
|
-
const online = await readPresence(client, conn.peerLogin);
|
|
4541
4553
|
items.push({
|
|
4542
4554
|
login: conn.peerLogin,
|
|
4543
|
-
|
|
4555
|
+
presence: REACHABLE_DISPLAY,
|
|
4544
4556
|
unread,
|
|
4545
4557
|
lastStamp: last ? formatStamp(last.createdAt) : "",
|
|
4546
4558
|
preview: last ? last.plaintext : ""
|
|
4547
4559
|
});
|
|
4548
4560
|
}
|
|
4549
|
-
await clearPresence(client);
|
|
4550
4561
|
output.write(renderInbox(items, invites));
|
|
4551
4562
|
return { ok: true, count: items.length, invites: invites.length };
|
|
4552
4563
|
}
|
|
@@ -4589,7 +4600,6 @@ async function runReadThread(opts = {}) {
|
|
|
4589
4600
|
}
|
|
4590
4601
|
const total = messages.length;
|
|
4591
4602
|
const shownMessages = all ? messages : messages.slice(Math.max(0, total - limit));
|
|
4592
|
-
const online = await readPresence(client, peerLogin);
|
|
4593
4603
|
let safety = "";
|
|
4594
4604
|
if (typeof client.getSafetyNumber === "function") {
|
|
4595
4605
|
try {
|
|
@@ -4598,8 +4608,7 @@ async function runReadThread(opts = {}) {
|
|
|
4598
4608
|
safety = "";
|
|
4599
4609
|
}
|
|
4600
4610
|
}
|
|
4601
|
-
|
|
4602
|
-
output.write(renderThread({ peerLogin, online, safety, messages: shownMessages, total }));
|
|
4611
|
+
output.write(renderThread({ peerLogin, presence: REACHABLE_DISPLAY, safety, messages: shownMessages, total }));
|
|
4603
4612
|
if (total > 0) {
|
|
4604
4613
|
const newest = messages[total - 1];
|
|
4605
4614
|
if (newest && newest.createdAt) {
|
|
@@ -4672,7 +4681,7 @@ async function runSend(opts = {}) {
|
|
|
4672
4681
|
);
|
|
4673
4682
|
return { ok: true };
|
|
4674
4683
|
}
|
|
4675
|
-
var CHAT_BASE3, GH_SESSION_COOKIE3, TERMINALHIRE_DIR5, READS_FILE, INDEX_CACHE_FILE;
|
|
4684
|
+
var CHAT_BASE3, GH_SESSION_COOKIE3, TERMINALHIRE_DIR5, READS_FILE, INDEX_CACHE_FILE, REACHABLE_DISPLAY;
|
|
4676
4685
|
var init_jpi_chat_read = __esm({
|
|
4677
4686
|
"bin/jpi-chat-read.js"() {
|
|
4678
4687
|
init_chat_client();
|
|
@@ -4683,6 +4692,7 @@ var init_jpi_chat_read = __esm({
|
|
|
4683
4692
|
TERMINALHIRE_DIR5 = join8(homedir7(), ".terminalhire");
|
|
4684
4693
|
READS_FILE = join8(TERMINALHIRE_DIR5, "chat-reads.json");
|
|
4685
4694
|
INDEX_CACHE_FILE = join8(TERMINALHIRE_DIR5, "index-cache.json");
|
|
4695
|
+
REACHABLE_DISPLAY = { shareActivity: false, optin: false, lastSeen: null };
|
|
4686
4696
|
}
|
|
4687
4697
|
});
|
|
4688
4698
|
init_jpi_chat_read();
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -4558,7 +4558,7 @@ function renderInbox(items, invites = []) {
|
|
|
4558
4558
|
lines.push(" (no accepted connections yet \u2014 request one: terminalhire intro <login>)");
|
|
4559
4559
|
} else {
|
|
4560
4560
|
for (const it of items) {
|
|
4561
|
-
const dot = it.
|
|
4561
|
+
const dot = formatPresence(it.presence).charAt(0);
|
|
4562
4562
|
const unread = it.unread > 0 ? `\u2709 ${it.unread}` : "\u2014";
|
|
4563
4563
|
const login = `@${sanitizeLine(it.login)}`;
|
|
4564
4564
|
const stamp = sanitizeLine(it.lastStamp || "");
|
|
@@ -4573,13 +4573,12 @@ function renderInbox(items, invites = []) {
|
|
|
4573
4573
|
return lines.join("\n") + "\n";
|
|
4574
4574
|
}
|
|
4575
4575
|
function renderThread(state) {
|
|
4576
|
-
const { peerLogin,
|
|
4576
|
+
const { peerLogin, presence, safety, messages, total } = state;
|
|
4577
4577
|
const safePeer = sanitizeLine(peerLogin);
|
|
4578
|
-
const
|
|
4579
|
-
const presence = online ? "online" : "offline";
|
|
4578
|
+
const status = formatPresence(presence);
|
|
4580
4579
|
const lines = [];
|
|
4581
4580
|
lines.push(
|
|
4582
|
-
` @${safePeer} ${
|
|
4581
|
+
` @${safePeer} ${status}` + (safety ? ` \xB7 safety# ${sanitizeLine(safety)}` : "")
|
|
4583
4582
|
);
|
|
4584
4583
|
lines.push(" " + "\u2500".repeat(64));
|
|
4585
4584
|
if (!messages || messages.length === 0) {
|
|
@@ -4629,21 +4628,6 @@ function writeProblem(output, result, target) {
|
|
|
4629
4628
|
return "error";
|
|
4630
4629
|
}
|
|
4631
4630
|
}
|
|
4632
|
-
async function readPresence(client, peerLogin) {
|
|
4633
|
-
if (typeof client.getPeerPresence !== "function") return false;
|
|
4634
|
-
try {
|
|
4635
|
-
return await client.getPeerPresence(peerLogin) != null;
|
|
4636
|
-
} catch {
|
|
4637
|
-
return false;
|
|
4638
|
-
}
|
|
4639
|
-
}
|
|
4640
|
-
async function clearPresence(client) {
|
|
4641
|
-
if (typeof client.heartbeat !== "function") return;
|
|
4642
|
-
try {
|
|
4643
|
-
await client.heartbeat(false);
|
|
4644
|
-
} catch {
|
|
4645
|
-
}
|
|
4646
|
-
}
|
|
4647
4631
|
async function gateDisclosure(ensureDisclosure, input, output) {
|
|
4648
4632
|
const ack = await ensureDisclosure({ input, output });
|
|
4649
4633
|
if (!ack.acknowledged) {
|
|
@@ -4691,16 +4675,14 @@ async function runInbox(opts = {}) {
|
|
|
4691
4675
|
(m) => m.senderLogin === conn.peerLogin && (!cursor || m.createdAt > cursor)
|
|
4692
4676
|
).length;
|
|
4693
4677
|
const last = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
4694
|
-
const online = await readPresence(client, conn.peerLogin);
|
|
4695
4678
|
items.push({
|
|
4696
4679
|
login: conn.peerLogin,
|
|
4697
|
-
|
|
4680
|
+
presence: REACHABLE_DISPLAY,
|
|
4698
4681
|
unread,
|
|
4699
4682
|
lastStamp: last ? formatStamp(last.createdAt) : "",
|
|
4700
4683
|
preview: last ? last.plaintext : ""
|
|
4701
4684
|
});
|
|
4702
4685
|
}
|
|
4703
|
-
await clearPresence(client);
|
|
4704
4686
|
output.write(renderInbox(items, invites));
|
|
4705
4687
|
return { ok: true, count: items.length, invites: invites.length };
|
|
4706
4688
|
}
|
|
@@ -4743,7 +4725,6 @@ async function runReadThread(opts = {}) {
|
|
|
4743
4725
|
}
|
|
4744
4726
|
const total = messages.length;
|
|
4745
4727
|
const shownMessages = all ? messages : messages.slice(Math.max(0, total - limit));
|
|
4746
|
-
const online = await readPresence(client, peerLogin);
|
|
4747
4728
|
let safety = "";
|
|
4748
4729
|
if (typeof client.getSafetyNumber === "function") {
|
|
4749
4730
|
try {
|
|
@@ -4752,8 +4733,7 @@ async function runReadThread(opts = {}) {
|
|
|
4752
4733
|
safety = "";
|
|
4753
4734
|
}
|
|
4754
4735
|
}
|
|
4755
|
-
|
|
4756
|
-
output.write(renderThread({ peerLogin, online, safety, messages: shownMessages, total }));
|
|
4736
|
+
output.write(renderThread({ peerLogin, presence: REACHABLE_DISPLAY, safety, messages: shownMessages, total }));
|
|
4757
4737
|
if (total > 0) {
|
|
4758
4738
|
const newest = messages[total - 1];
|
|
4759
4739
|
if (newest && newest.createdAt) {
|
|
@@ -4826,7 +4806,7 @@ async function runSend(opts = {}) {
|
|
|
4826
4806
|
);
|
|
4827
4807
|
return { ok: true };
|
|
4828
4808
|
}
|
|
4829
|
-
var CHAT_BASE2, GH_SESSION_COOKIE2, TERMINALHIRE_DIR6, READS_FILE, INDEX_CACHE_FILE;
|
|
4809
|
+
var CHAT_BASE2, GH_SESSION_COOKIE2, TERMINALHIRE_DIR6, READS_FILE, INDEX_CACHE_FILE, REACHABLE_DISPLAY;
|
|
4830
4810
|
var init_jpi_chat_read = __esm({
|
|
4831
4811
|
"bin/jpi-chat-read.js"() {
|
|
4832
4812
|
"use strict";
|
|
@@ -4838,6 +4818,7 @@ var init_jpi_chat_read = __esm({
|
|
|
4838
4818
|
TERMINALHIRE_DIR6 = join8(homedir7(), ".terminalhire");
|
|
4839
4819
|
READS_FILE = join8(TERMINALHIRE_DIR6, "chat-reads.json");
|
|
4840
4820
|
INDEX_CACHE_FILE = join8(TERMINALHIRE_DIR6, "index-cache.json");
|
|
4821
|
+
REACHABLE_DISPLAY = { shareActivity: false, optin: false, lastSeen: null };
|
|
4841
4822
|
}
|
|
4842
4823
|
});
|
|
4843
4824
|
|
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -10689,7 +10689,7 @@ function renderInbox(items, invites = []) {
|
|
|
10689
10689
|
lines.push(" (no accepted connections yet \u2014 request one: terminalhire intro <login>)");
|
|
10690
10690
|
} else {
|
|
10691
10691
|
for (const it of items) {
|
|
10692
|
-
const dot = it.
|
|
10692
|
+
const dot = formatPresence(it.presence).charAt(0);
|
|
10693
10693
|
const unread = it.unread > 0 ? `\u2709 ${it.unread}` : "\u2014";
|
|
10694
10694
|
const login = `@${sanitizeLine(it.login)}`;
|
|
10695
10695
|
const stamp = sanitizeLine(it.lastStamp || "");
|
|
@@ -10704,13 +10704,12 @@ function renderInbox(items, invites = []) {
|
|
|
10704
10704
|
return lines.join("\n") + "\n";
|
|
10705
10705
|
}
|
|
10706
10706
|
function renderThread(state) {
|
|
10707
|
-
const { peerLogin,
|
|
10707
|
+
const { peerLogin, presence, safety, messages, total } = state;
|
|
10708
10708
|
const safePeer = sanitizeLine(peerLogin);
|
|
10709
|
-
const
|
|
10710
|
-
const presence = online ? "online" : "offline";
|
|
10709
|
+
const status = formatPresence(presence);
|
|
10711
10710
|
const lines = [];
|
|
10712
10711
|
lines.push(
|
|
10713
|
-
` @${safePeer} ${
|
|
10712
|
+
` @${safePeer} ${status}` + (safety ? ` \xB7 safety# ${sanitizeLine(safety)}` : "")
|
|
10714
10713
|
);
|
|
10715
10714
|
lines.push(" " + "\u2500".repeat(64));
|
|
10716
10715
|
if (!messages || messages.length === 0) {
|
|
@@ -10760,21 +10759,6 @@ function writeProblem(output, result, target) {
|
|
|
10760
10759
|
return "error";
|
|
10761
10760
|
}
|
|
10762
10761
|
}
|
|
10763
|
-
async function readPresence(client, peerLogin) {
|
|
10764
|
-
if (typeof client.getPeerPresence !== "function") return false;
|
|
10765
|
-
try {
|
|
10766
|
-
return await client.getPeerPresence(peerLogin) != null;
|
|
10767
|
-
} catch {
|
|
10768
|
-
return false;
|
|
10769
|
-
}
|
|
10770
|
-
}
|
|
10771
|
-
async function clearPresence(client) {
|
|
10772
|
-
if (typeof client.heartbeat !== "function") return;
|
|
10773
|
-
try {
|
|
10774
|
-
await client.heartbeat(false);
|
|
10775
|
-
} catch {
|
|
10776
|
-
}
|
|
10777
|
-
}
|
|
10778
10762
|
async function gateDisclosure(ensureDisclosure, input, output) {
|
|
10779
10763
|
const ack = await ensureDisclosure({ input, output });
|
|
10780
10764
|
if (!ack.acknowledged) {
|
|
@@ -10822,16 +10806,14 @@ async function runInbox(opts = {}) {
|
|
|
10822
10806
|
(m) => m.senderLogin === conn.peerLogin && (!cursor || m.createdAt > cursor)
|
|
10823
10807
|
).length;
|
|
10824
10808
|
const last = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
10825
|
-
const online = await readPresence(client, conn.peerLogin);
|
|
10826
10809
|
items.push({
|
|
10827
10810
|
login: conn.peerLogin,
|
|
10828
|
-
|
|
10811
|
+
presence: REACHABLE_DISPLAY,
|
|
10829
10812
|
unread,
|
|
10830
10813
|
lastStamp: last ? formatStamp(last.createdAt) : "",
|
|
10831
10814
|
preview: last ? last.plaintext : ""
|
|
10832
10815
|
});
|
|
10833
10816
|
}
|
|
10834
|
-
await clearPresence(client);
|
|
10835
10817
|
output.write(renderInbox(items, invites));
|
|
10836
10818
|
return { ok: true, count: items.length, invites: invites.length };
|
|
10837
10819
|
}
|
|
@@ -10874,7 +10856,6 @@ async function runReadThread(opts = {}) {
|
|
|
10874
10856
|
}
|
|
10875
10857
|
const total = messages.length;
|
|
10876
10858
|
const shownMessages = all ? messages : messages.slice(Math.max(0, total - limit));
|
|
10877
|
-
const online = await readPresence(client, peerLogin);
|
|
10878
10859
|
let safety = "";
|
|
10879
10860
|
if (typeof client.getSafetyNumber === "function") {
|
|
10880
10861
|
try {
|
|
@@ -10883,8 +10864,7 @@ async function runReadThread(opts = {}) {
|
|
|
10883
10864
|
safety = "";
|
|
10884
10865
|
}
|
|
10885
10866
|
}
|
|
10886
|
-
|
|
10887
|
-
output.write(renderThread({ peerLogin, online, safety, messages: shownMessages, total }));
|
|
10867
|
+
output.write(renderThread({ peerLogin, presence: REACHABLE_DISPLAY, safety, messages: shownMessages, total }));
|
|
10888
10868
|
if (total > 0) {
|
|
10889
10869
|
const newest = messages[total - 1];
|
|
10890
10870
|
if (newest && newest.createdAt) {
|
|
@@ -10957,7 +10937,7 @@ async function runSend(opts = {}) {
|
|
|
10957
10937
|
);
|
|
10958
10938
|
return { ok: true };
|
|
10959
10939
|
}
|
|
10960
|
-
var CHAT_BASE2, GH_SESSION_COOKIE4, TERMINALHIRE_DIR13, READS_FILE, INDEX_CACHE_FILE5;
|
|
10940
|
+
var CHAT_BASE2, GH_SESSION_COOKIE4, TERMINALHIRE_DIR13, READS_FILE, INDEX_CACHE_FILE5, REACHABLE_DISPLAY;
|
|
10961
10941
|
var init_jpi_chat_read = __esm({
|
|
10962
10942
|
"bin/jpi-chat-read.js"() {
|
|
10963
10943
|
"use strict";
|
|
@@ -10969,6 +10949,7 @@ var init_jpi_chat_read = __esm({
|
|
|
10969
10949
|
TERMINALHIRE_DIR13 = join17(homedir16(), ".terminalhire");
|
|
10970
10950
|
READS_FILE = join17(TERMINALHIRE_DIR13, "chat-reads.json");
|
|
10971
10951
|
INDEX_CACHE_FILE5 = join17(TERMINALHIRE_DIR13, "index-cache.json");
|
|
10952
|
+
REACHABLE_DISPLAY = { shareActivity: false, optin: false, lastSeen: null };
|
|
10972
10953
|
}
|
|
10973
10954
|
});
|
|
10974
10955
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminalhire",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.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",
|