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.
- package/dist/bin/jpi-bounties.js +8 -4
- package/dist/bin/jpi-chat-read.js +38 -22
- package/dist/bin/jpi-chat.js +1368 -369
- package/dist/bin/jpi-claim.js +1 -1
- package/dist/bin/jpi-config.js +1 -1
- package/dist/bin/jpi-contribute.js +1 -1
- package/dist/bin/jpi-devs.js +8 -4
- package/dist/bin/jpi-dispatch.js +1283 -587
- package/dist/bin/jpi-inbox.js +6509 -0
- package/dist/bin/jpi-init.js +1 -2
- package/dist/bin/jpi-intro.js +20 -1
- package/dist/bin/jpi-jobs.js +10 -6
- package/dist/bin/jpi-login.js +8 -5
- package/dist/bin/jpi-project.js +8 -4
- package/dist/bin/jpi-refresh.js +298 -197
- package/dist/bin/jpi-save.js +1 -1
- package/dist/bin/jpi-spinner.js +148 -125
- package/dist/bin/jpi-statusline-launch.js +1 -1
- package/dist/bin/jpi-statusline.js +1 -1
- package/dist/bin/jpi.js +1 -1
- package/dist/bin/spinner.js +220 -185
- package/dist/bin/version-nudge.js +1 -1
- package/dist/src/intro.js +20 -1
- package/install.js +1 -2
- package/package.json +2 -2
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -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
|
-
|
|
2957
|
-
if (
|
|
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
|
|
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
|
-
|
|
4605
|
-
|
|
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
|
-
|
|
4644
|
-
|
|
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,
|