terminalhire 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2953,11 +2953,14 @@ You control whether this connects \u2014 no contact details are shared unless yo
2953
2953
  return { subject, text };
2954
2954
  }
2955
2955
  function introActorRole(intro, actorLogin) {
2956
- const a = actorLogin.trim().toLowerCase();
2957
- if (a && a === intro.targetLogin.trim().toLowerCase()) return "target";
2958
- if (a && a === intro.requesterLogin.trim().toLowerCase()) return "requester";
2956
+ if (sameLogin(actorLogin, intro.targetLogin)) return "target";
2957
+ if (sameLogin(actorLogin, intro.requesterLogin)) return "requester";
2959
2958
  return "other";
2960
2959
  }
2960
+ function sameLogin(a, b) {
2961
+ const an = a.trim().toLowerCase();
2962
+ return an.length > 0 && an === b.trim().toLowerCase();
2963
+ }
2961
2964
  function authorizeIntroDecision(intro, actorLogin) {
2962
2965
  const role = introActorRole(intro, actorLogin);
2963
2966
  if (role === "target") return { ok: true };
@@ -6399,6 +6402,7 @@ __export(src_exports, {
6399
6402
  rejectExtraIntroFields: () => rejectExtraIntroFields,
6400
6403
  revealIntroContacts: () => revealIntroContacts,
6401
6404
  safetyNumber: () => safetyNumber,
6405
+ sameLogin: () => sameLogin,
6402
6406
  setStatus: () => setStatus,
6403
6407
  tokenize: () => tokenize,
6404
6408
  validateGraph: () => validateGraph,
@@ -6670,7 +6674,7 @@ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSy
6670
6674
  import { join as join3 } from "path";
6671
6675
  import { homedir as homedir2 } from "os";
6672
6676
  import { createInterface } from "readline";
6673
- var TERMINALHIRE_DIR2 = join3(homedir2(), ".terminalhire");
6677
+ var TERMINALHIRE_DIR2 = process.env.TERMINALHIRE_DIR || join3(homedir2(), ".terminalhire");
6674
6678
  var INDEX_CACHE_FILE = join3(TERMINALHIRE_DIR2, "index-cache.json");
6675
6679
  var INDEX_TTL_MS = 15 * 60 * 1e3;
6676
6680
  var API_URL = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
@@ -4456,6 +4456,8 @@ function readReadCursors() {
4456
4456
  function writeReadCursor(login, iso, deps = {}) {
4457
4457
  const read = deps.readReadCursors ?? readReadCursors;
4458
4458
  const cursors = read();
4459
+ const prev = cursors[login];
4460
+ if (prev && iso <= prev) return;
4459
4461
  cursors[login] = iso;
4460
4462
  mkdirSync6(TERMINALHIRE_DIR5, { recursive: true });
4461
4463
  writeFileSync6(READS_FILE, JSON.stringify(cursors, null, 2), { mode: 384, encoding: "utf8" });
@@ -4595,29 +4597,14 @@ async function gateDisclosure(ensureDisclosure, input, output) {
4595
4597
  }
4596
4598
  return true;
4597
4599
  }
4598
- async function runInbox(opts = {}) {
4600
+ async function buildInboxItems(deps = {}) {
4599
4601
  const {
4600
- output = process.stdout,
4601
- input = process.stdin,
4602
4602
  client = createChatClient(),
4603
4603
  listConnections = defaultListConnections,
4604
- listInvites = defaultListPendingInvites,
4605
- readCursors = readReadCursors,
4606
- ensureDisclosure = ensureChatDisclosure
4607
- } = opts;
4608
- if (!await gateDisclosure(ensureDisclosure, input, output)) {
4609
- return { ok: false, reason: "not-acknowledged" };
4610
- }
4604
+ readCursors = readReadCursors
4605
+ } = deps;
4611
4606
  const listed = await listConnections();
4612
- if (listed.status !== "ok") {
4613
- return { ok: false, reason: writeProblem(output, listed, "") };
4614
- }
4615
- let invites = [];
4616
- try {
4617
- const inv = await listInvites();
4618
- if (inv && inv.status === "ok") invites = inv.invites;
4619
- } catch {
4620
- }
4607
+ if (listed.status !== "ok") return listed;
4621
4608
  const cursors = readCursors();
4622
4609
  const items = [];
4623
4610
  for (const conn of listed.connections) {
@@ -4637,11 +4624,39 @@ async function runInbox(opts = {}) {
4637
4624
  presence: REACHABLE_DISPLAY,
4638
4625
  unread,
4639
4626
  lastStamp: last ? formatStamp(last.createdAt) : "",
4627
+ // Raw ISO of the newest message — the TUI's `r` key marks the thread read at
4628
+ // this exact watermark (postReadCursor). The formatted lastStamp is display-only.
4629
+ lastStampIso: last ? last.createdAt : null,
4640
4630
  preview: last ? last.plaintext : ""
4641
4631
  });
4642
4632
  }
4643
- output.write(renderInbox(items, invites));
4644
- return { ok: true, count: items.length, invites: invites.length };
4633
+ return { status: "ok", items };
4634
+ }
4635
+ async function runInbox(opts = {}) {
4636
+ const {
4637
+ output = process.stdout,
4638
+ input = process.stdin,
4639
+ client = createChatClient(),
4640
+ listConnections = defaultListConnections,
4641
+ listInvites = defaultListPendingInvites,
4642
+ readCursors = readReadCursors,
4643
+ ensureDisclosure = ensureChatDisclosure
4644
+ } = opts;
4645
+ if (!await gateDisclosure(ensureDisclosure, input, output)) {
4646
+ return { ok: false, reason: "not-acknowledged" };
4647
+ }
4648
+ const built = await buildInboxItems({ client, listConnections, readCursors });
4649
+ if (built.status !== "ok") {
4650
+ return { ok: false, reason: writeProblem(output, built, "") };
4651
+ }
4652
+ let invites = [];
4653
+ try {
4654
+ const inv = await listInvites();
4655
+ if (inv && inv.status === "ok") invites = inv.invites;
4656
+ } catch {
4657
+ }
4658
+ output.write(renderInbox(built.items, invites));
4659
+ return { ok: true, count: built.items.length, invites: invites.length };
4645
4660
  }
4646
4661
  async function runReadThread(opts = {}) {
4647
4662
  const {
@@ -4771,7 +4786,7 @@ var init_jpi_chat_read = __esm({
4771
4786
  init_jpi_chat();
4772
4787
  CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
4773
4788
  GH_SESSION_COOKIE3 = "__jpi_gh_session";
4774
- TERMINALHIRE_DIR5 = join8(homedir7(), ".terminalhire");
4789
+ TERMINALHIRE_DIR5 = process.env.TERMINALHIRE_DIR || join8(homedir7(), ".terminalhire");
4775
4790
  READS_FILE = join8(TERMINALHIRE_DIR5, "chat-reads.json");
4776
4791
  INDEX_CACHE_FILE = join8(TERMINALHIRE_DIR5, "index-cache.json");
4777
4792
  REACHABLE_DISPLAY = { shareActivity: false, optin: false, lastSeen: null };
@@ -4779,6 +4794,7 @@ var init_jpi_chat_read = __esm({
4779
4794
  });
4780
4795
  init_jpi_chat_read();
4781
4796
  export {
4797
+ buildInboxItems,
4782
4798
  formatClock,
4783
4799
  formatStamp,
4784
4800
  postReadCursor,