terminalhire 0.10.10 → 0.11.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 +53 -0
- package/dist/bin/jpi-chat-read.js +57 -13
- package/dist/bin/jpi-chat.js +448 -28
- package/dist/bin/jpi-config.js +1 -0
- package/dist/bin/jpi-devs.js +53 -0
- package/dist/bin/jpi-dispatch.js +683 -244
- package/dist/bin/jpi-intro.js +8 -0
- package/dist/bin/jpi-jobs.js +307 -42
- package/dist/bin/jpi-learn.js +8 -0
- package/dist/bin/jpi-link.js +1 -0
- package/dist/bin/jpi-login.js +54 -0
- package/dist/bin/jpi-profile.js +8 -0
- package/dist/bin/jpi-project.js +53 -0
- package/dist/bin/jpi-refresh.js +65 -5
- package/dist/bin/jpi-save.js +8 -0
- package/dist/bin/jpi-spinner.js +9 -4
- package/dist/bin/jpi-sync.js +8 -0
- package/dist/bin/jpi-trajectory.js +8 -0
- package/dist/bin/peer-connect-prompt.js +1 -0
- package/dist/bin/spinner.js +10 -4
- package/dist/src/chat-client.js +16 -1
- package/dist/src/config.js +1 -0
- package/dist/src/intro.js +8 -0
- package/dist/src/link.js +1 -0
- package/dist/src/trajectory.js +8 -0
- package/package.json +1 -1
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -5840,6 +5840,53 @@ var init_chatCrypto = __esm({
|
|
|
5840
5840
|
}
|
|
5841
5841
|
});
|
|
5842
5842
|
|
|
5843
|
+
// ../../packages/core/src/job-status.ts
|
|
5844
|
+
function recordClick(map, id) {
|
|
5845
|
+
const prev = map[id];
|
|
5846
|
+
if (prev?.clicked === true) return map;
|
|
5847
|
+
return { ...map, [id]: { ...prev, clicked: true } };
|
|
5848
|
+
}
|
|
5849
|
+
function setStatus(map, id, s, markedAt = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
5850
|
+
const prev = map[id];
|
|
5851
|
+
return { ...map, [id]: { ...prev, status: s, markedAt } };
|
|
5852
|
+
}
|
|
5853
|
+
function funnelCounts(map) {
|
|
5854
|
+
const counts = { clicked: 0, applied: 0, saved: 0, dismissed: 0 };
|
|
5855
|
+
for (const key of Object.keys(map)) {
|
|
5856
|
+
const rec = map[key];
|
|
5857
|
+
if (rec.clicked === true) counts.clicked++;
|
|
5858
|
+
if (rec.status) counts[rec.status]++;
|
|
5859
|
+
}
|
|
5860
|
+
return counts;
|
|
5861
|
+
}
|
|
5862
|
+
function pageMatches(items, page, limit) {
|
|
5863
|
+
const lim = Math.max(1, Math.floor(limit));
|
|
5864
|
+
const total = items.length;
|
|
5865
|
+
const totalPages = Math.max(1, Math.ceil(total / lim));
|
|
5866
|
+
const clamped = Math.min(Math.max(1, Math.floor(page)), totalPages);
|
|
5867
|
+
const start = (clamped - 1) * lim;
|
|
5868
|
+
return {
|
|
5869
|
+
items: items.slice(start, start + lim),
|
|
5870
|
+
page: clamped,
|
|
5871
|
+
limit: lim,
|
|
5872
|
+
total,
|
|
5873
|
+
totalPages,
|
|
5874
|
+
hasPrev: clamped > 1,
|
|
5875
|
+
hasNext: clamped < totalPages
|
|
5876
|
+
};
|
|
5877
|
+
}
|
|
5878
|
+
function decorate(matches, statusMap) {
|
|
5879
|
+
return matches.map((m) => {
|
|
5880
|
+
const rec = statusMap[m.job.id];
|
|
5881
|
+
return rec ? { ...m, jobStatus: rec } : { ...m };
|
|
5882
|
+
});
|
|
5883
|
+
}
|
|
5884
|
+
var init_job_status = __esm({
|
|
5885
|
+
"../../packages/core/src/job-status.ts"() {
|
|
5886
|
+
"use strict";
|
|
5887
|
+
}
|
|
5888
|
+
});
|
|
5889
|
+
|
|
5843
5890
|
// ../../packages/core/src/index.ts
|
|
5844
5891
|
var src_exports = {};
|
|
5845
5892
|
__export(src_exports, {
|
|
@@ -5881,6 +5928,7 @@ __export(src_exports, {
|
|
|
5881
5928
|
computeAcceptanceCredential: () => computeAcceptanceCredential,
|
|
5882
5929
|
computeAcceptanceCredentialPublic: () => computeAcceptanceCredentialPublic,
|
|
5883
5930
|
coreTagsFromTitle: () => coreTagsFromTitle,
|
|
5931
|
+
decorate: () => decorate,
|
|
5884
5932
|
decryptMessage: () => decryptMessage,
|
|
5885
5933
|
deriveResumeTrend: () => deriveResumeTrend,
|
|
5886
5934
|
deriveSharedKey: () => deriveSharedKey,
|
|
@@ -5891,6 +5939,7 @@ __export(src_exports, {
|
|
|
5891
5939
|
fetchOwnedRepoTraction: () => fetchOwnedRepoTraction,
|
|
5892
5940
|
fetchRepoRecency: () => fetchRepoRecency,
|
|
5893
5941
|
flattenTiers: () => flattenTiers,
|
|
5942
|
+
funnelCounts: () => funnelCounts,
|
|
5894
5943
|
generateIdentityKeypair: () => generateIdentityKeypair,
|
|
5895
5944
|
getBuyer: () => getBuyer,
|
|
5896
5945
|
githubBounties: () => githubBounties,
|
|
@@ -5909,12 +5958,15 @@ __export(src_exports, {
|
|
|
5909
5958
|
match: () => match,
|
|
5910
5959
|
normalize: () => normalize,
|
|
5911
5960
|
opire: () => opire,
|
|
5961
|
+
pageMatches: () => pageMatches,
|
|
5912
5962
|
passesMaturityGate: () => passesMaturityGate,
|
|
5913
5963
|
personCardToJob: () => personCardToJob,
|
|
5914
5964
|
projectCardToJob: () => projectCardToJob,
|
|
5965
|
+
recordClick: () => recordClick,
|
|
5915
5966
|
rejectExtraIntroFields: () => rejectExtraIntroFields,
|
|
5916
5967
|
revealIntroContacts: () => revealIntroContacts,
|
|
5917
5968
|
safetyNumber: () => safetyNumber,
|
|
5969
|
+
setStatus: () => setStatus,
|
|
5918
5970
|
tokenize: () => tokenize,
|
|
5919
5971
|
validateGraph: () => validateGraph,
|
|
5920
5972
|
validateIntroPayload: () => validateIntroPayload,
|
|
@@ -5935,6 +5987,7 @@ var init_src = __esm({
|
|
|
5935
5987
|
init_intro();
|
|
5936
5988
|
init_directoryThreshold();
|
|
5937
5989
|
init_chatCrypto();
|
|
5990
|
+
init_job_status();
|
|
5938
5991
|
}
|
|
5939
5992
|
});
|
|
5940
5993
|
|
|
@@ -3749,6 +3749,13 @@ var init_chatCrypto = __esm({
|
|
|
3749
3749
|
}
|
|
3750
3750
|
});
|
|
3751
3751
|
|
|
3752
|
+
// ../../packages/core/src/job-status.ts
|
|
3753
|
+
var init_job_status = __esm({
|
|
3754
|
+
"../../packages/core/src/job-status.ts"() {
|
|
3755
|
+
"use strict";
|
|
3756
|
+
}
|
|
3757
|
+
});
|
|
3758
|
+
|
|
3752
3759
|
// ../../packages/core/src/index.ts
|
|
3753
3760
|
var init_src = __esm({
|
|
3754
3761
|
"../../packages/core/src/index.ts"() {
|
|
@@ -3763,6 +3770,7 @@ var init_src = __esm({
|
|
|
3763
3770
|
init_intro();
|
|
3764
3771
|
init_directoryThreshold();
|
|
3765
3772
|
init_chatCrypto();
|
|
3773
|
+
init_job_status();
|
|
3766
3774
|
}
|
|
3767
3775
|
});
|
|
3768
3776
|
|
|
@@ -4039,7 +4047,21 @@ function createChatClient(overrides) {
|
|
|
4039
4047
|
const data = await res.json();
|
|
4040
4048
|
const presence = data.presence ?? null;
|
|
4041
4049
|
if (!presence) return null;
|
|
4042
|
-
return {
|
|
4050
|
+
return {
|
|
4051
|
+
login: presence.login,
|
|
4052
|
+
lastSeen: presence.lastSeen ?? null,
|
|
4053
|
+
optin: presence.optin === true,
|
|
4054
|
+
shareActivity: presence.shareActivity === true
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
async function setActivitySharing(share) {
|
|
4058
|
+
const res = await authedFetch("/api/chat/activity", {
|
|
4059
|
+
method: "POST",
|
|
4060
|
+
headers: { "Content-Type": "application/json" },
|
|
4061
|
+
body: JSON.stringify({ share })
|
|
4062
|
+
});
|
|
4063
|
+
if (!res.ok) throw new ChatRequestError("/api/chat/activity", res.status);
|
|
4064
|
+
await res.json();
|
|
4043
4065
|
}
|
|
4044
4066
|
async function applyBlock(login, action) {
|
|
4045
4067
|
const target = login.trim();
|
|
@@ -4063,6 +4085,7 @@ function createChatClient(overrides) {
|
|
|
4063
4085
|
pollMessages,
|
|
4064
4086
|
heartbeat,
|
|
4065
4087
|
getPeerPresence,
|
|
4088
|
+
setActivitySharing,
|
|
4066
4089
|
blockPeer: (login) => applyBlock(login, "block"),
|
|
4067
4090
|
unblock: (login) => applyBlock(login, "unblock"),
|
|
4068
4091
|
getSafetyNumber
|
|
@@ -4151,6 +4174,7 @@ var init_config = __esm({
|
|
|
4151
4174
|
peerConnectPrompted: false,
|
|
4152
4175
|
resumePublishPrompted: false,
|
|
4153
4176
|
chatDisclosureAck: false,
|
|
4177
|
+
chatShareActivity: false,
|
|
4154
4178
|
inboundNudgeMuted: false,
|
|
4155
4179
|
inboundNudgeDisclosed: false
|
|
4156
4180
|
};
|
|
@@ -4159,6 +4183,9 @@ var init_config = __esm({
|
|
|
4159
4183
|
|
|
4160
4184
|
// bin/jpi-chat.js
|
|
4161
4185
|
import { createInterface } from "readline";
|
|
4186
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
4187
|
+
import { homedir as homedir6 } from "os";
|
|
4188
|
+
import { join as join7 } from "path";
|
|
4162
4189
|
function sanitizeLine(text) {
|
|
4163
4190
|
return String(text).replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(ANSI_OTHER, "").replace(C0_C1_DEL, "");
|
|
4164
4191
|
}
|
|
@@ -4251,7 +4278,7 @@ async function defaultListPendingInvites(deps = {}) {
|
|
|
4251
4278
|
const invites = listed.intros.filter((it) => it && it.role === "incoming" && it.status === "pending" && it.counterpartyLogin).map((it) => ({ login: it.counterpartyLogin }));
|
|
4252
4279
|
return { status: "ok", invites };
|
|
4253
4280
|
}
|
|
4254
|
-
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;
|
|
4281
|
+
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;
|
|
4255
4282
|
var init_jpi_chat = __esm({
|
|
4256
4283
|
"bin/jpi-chat.js"() {
|
|
4257
4284
|
"use strict";
|
|
@@ -4268,20 +4295,21 @@ var init_jpi_chat = __esm({
|
|
|
4268
4295
|
CHAT_AT_REST = "Your private key is encrypted against casual access, not full machine compromise.";
|
|
4269
4296
|
CHAT_CODE_OF_CONDUCT = "Code of conduct: keep it professional \u2014 harassment, spam, or abuse gets you blocked and removed.";
|
|
4270
4297
|
CHAT_MIN_AGE = "You must be at least 13 years old to use connections chat.";
|
|
4298
|
+
ACTIVE_WINDOW_MS = 2 * 60 * 1e3;
|
|
4271
4299
|
}
|
|
4272
4300
|
});
|
|
4273
4301
|
|
|
4274
4302
|
// bin/jpi-chat-read.js
|
|
4275
|
-
import { existsSync as
|
|
4276
|
-
import { homedir as
|
|
4277
|
-
import { join as
|
|
4303
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
4304
|
+
import { homedir as homedir7 } from "os";
|
|
4305
|
+
import { join as join8 } from "path";
|
|
4278
4306
|
async function syncUnreadBadge(deps = {}) {
|
|
4279
4307
|
const readCookie = deps.readCookie ?? readWebSessionCookie;
|
|
4280
4308
|
const fetchImpl = deps.fetchImpl ?? globalThis.fetch;
|
|
4281
4309
|
const cacheFile = deps.cacheFile ?? INDEX_CACHE_FILE;
|
|
4282
4310
|
try {
|
|
4283
4311
|
const cookie = readCookie();
|
|
4284
|
-
if (!cookie || !
|
|
4312
|
+
if (!cookie || !existsSync7(cacheFile)) return;
|
|
4285
4313
|
const res = await fetchImpl(`${CHAT_BASE3}/api/chat/inbox`, {
|
|
4286
4314
|
method: "GET",
|
|
4287
4315
|
headers: { Cookie: `${GH_SESSION_COOKIE3}=${cookie}` },
|
|
@@ -4294,7 +4322,7 @@ async function syncUnreadBadge(deps = {}) {
|
|
|
4294
4322
|
(sum, it) => sum + (it && typeof it.unreadCount === "number" && it.unreadCount > 0 ? it.unreadCount : 0),
|
|
4295
4323
|
0
|
|
4296
4324
|
);
|
|
4297
|
-
const entry = JSON.parse(
|
|
4325
|
+
const entry = JSON.parse(readFileSync8(cacheFile, "utf8"));
|
|
4298
4326
|
entry.unreadChat = { count: total };
|
|
4299
4327
|
writeFileSync6(cacheFile, JSON.stringify(entry), "utf8");
|
|
4300
4328
|
} catch {
|
|
@@ -4302,8 +4330,8 @@ async function syncUnreadBadge(deps = {}) {
|
|
|
4302
4330
|
}
|
|
4303
4331
|
function readReadCursors() {
|
|
4304
4332
|
try {
|
|
4305
|
-
if (!
|
|
4306
|
-
const parsed = JSON.parse(
|
|
4333
|
+
if (!existsSync7(READS_FILE)) return {};
|
|
4334
|
+
const parsed = JSON.parse(readFileSync8(READS_FILE, "utf8"));
|
|
4307
4335
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
4308
4336
|
const out = {};
|
|
4309
4337
|
for (const [login, iso] of Object.entries(parsed)) {
|
|
@@ -4593,7 +4621,10 @@ async function runSend(opts = {}) {
|
|
|
4593
4621
|
input = process.stdin,
|
|
4594
4622
|
client = createChatClient(),
|
|
4595
4623
|
resolveConnection = defaultResolveConnection,
|
|
4596
|
-
ensureDisclosure = ensureChatDisclosure
|
|
4624
|
+
ensureDisclosure = ensureChatDisclosure,
|
|
4625
|
+
writeCursor = writeReadCursor,
|
|
4626
|
+
syncCursor = postReadCursor,
|
|
4627
|
+
syncBadge = syncUnreadBadge
|
|
4597
4628
|
} = opts;
|
|
4598
4629
|
const target = String(login ?? "").replace(/^@/, "").trim();
|
|
4599
4630
|
const body = String(text ?? "").trim();
|
|
@@ -4619,6 +4650,19 @@ async function runSend(opts = {}) {
|
|
|
4619
4650
|
`);
|
|
4620
4651
|
return { ok: false, reason: "error" };
|
|
4621
4652
|
}
|
|
4653
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4654
|
+
try {
|
|
4655
|
+
writeCursor(peerLogin, nowIso);
|
|
4656
|
+
} catch {
|
|
4657
|
+
}
|
|
4658
|
+
await syncCursor(peerLogin, nowIso);
|
|
4659
|
+
await syncBadge();
|
|
4660
|
+
if (typeof client.heartbeat === "function") {
|
|
4661
|
+
try {
|
|
4662
|
+
await client.heartbeat(false);
|
|
4663
|
+
} catch {
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4622
4666
|
output.write(
|
|
4623
4667
|
`
|
|
4624
4668
|
Sent to @${sanitizeLine(peerLogin)}: ${sanitizeLine(body)}
|
|
@@ -4636,9 +4680,9 @@ var init_jpi_chat_read = __esm({
|
|
|
4636
4680
|
init_jpi_chat();
|
|
4637
4681
|
CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
4638
4682
|
GH_SESSION_COOKIE3 = "__jpi_gh_session";
|
|
4639
|
-
TERMINALHIRE_DIR5 =
|
|
4640
|
-
READS_FILE =
|
|
4641
|
-
INDEX_CACHE_FILE =
|
|
4683
|
+
TERMINALHIRE_DIR5 = join8(homedir7(), ".terminalhire");
|
|
4684
|
+
READS_FILE = join8(TERMINALHIRE_DIR5, "chat-reads.json");
|
|
4685
|
+
INDEX_CACHE_FILE = join8(TERMINALHIRE_DIR5, "index-cache.json");
|
|
4642
4686
|
}
|
|
4643
4687
|
});
|
|
4644
4688
|
init_jpi_chat_read();
|