terminalhire 0.35.4 → 0.36.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/README.md +1 -1
- package/dist/bin/claim-push-bg.js +0 -54
- package/dist/bin/jpi-bounties.js +104 -61
- package/dist/bin/jpi-chat-read.js +16 -56
- package/dist/bin/jpi-chat.js +23 -64
- package/dist/bin/jpi-claim.js +107 -78
- package/dist/bin/jpi-contribute.js +20 -47
- package/dist/bin/jpi-devs.js +104 -61
- package/dist/bin/jpi-dispatch.js +380 -104
- package/dist/bin/jpi-hub.js +104 -75
- package/dist/bin/jpi-inbox.js +23 -64
- package/dist/bin/jpi-init.js +100 -15
- package/dist/bin/jpi-intro.js +20 -47
- package/dist/bin/jpi-jobs.js +104 -61
- package/dist/bin/jpi-learn.js +20 -47
- package/dist/bin/jpi-login.js +107 -78
- package/dist/bin/jpi-mcp-chat.js +27146 -0
- package/dist/bin/jpi-profile.js +20 -47
- package/dist/bin/jpi-project.js +100 -15
- package/dist/bin/jpi-refresh.js +104 -75
- package/dist/bin/jpi-repo.js +19 -46
- package/dist/bin/jpi-save.js +20 -47
- package/dist/bin/jpi-spinner.js +16 -1
- package/dist/bin/jpi-sync.js +20 -47
- package/dist/bin/jpi-trajectory.js +20 -47
- package/dist/bin/spinner.js +16 -1
- package/dist/src/chat-client.js +16 -58
- package/dist/src/chat-keystore.js +16 -58
- package/dist/src/crypto-store.js +4 -49
- package/dist/src/github-auth.js +0 -57
- package/dist/src/intro.js +20 -47
- package/dist/src/profile.js +20 -50
- package/dist/src/repo-experience.js +19 -49
- package/dist/src/reputation/fetch.js +16 -1
- package/dist/src/signal.js +16 -1
- package/dist/src/trajectory.js +20 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,7 +212,7 @@ GitHub (optional enrichment):
|
|
|
212
212
|
## Local profile encryption
|
|
213
213
|
|
|
214
214
|
- Algorithm: **AES-256-GCM** via Node built-in `crypto` (no external deps).
|
|
215
|
-
- Key: stored at `~/.terminalhire/key` with `0600` permissions.
|
|
215
|
+
- Key: stored at `~/.terminalhire/key` with `0600` permissions (a plaintext key file). In a compiled build the OS keychain is **not** used for these stores — the cross-platform plugin ships without `node_modules` and can't reach one. See `docs/adr-002` (keychain promotion is tracked as TERM-9).
|
|
216
216
|
- Profile file: `~/.terminalhire/profile.enc` — JSON blob `{ iv, tag, ciphertext }` (all hex-encoded).
|
|
217
217
|
- GitHub token file: `~/.terminalhire/github-token.enc` — same format, same key.
|
|
218
218
|
|
|
@@ -1,52 +1,12 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
1
|
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
3
|
var __esm = (fn, res) => function __init() {
|
|
8
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
9
5
|
};
|
|
10
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
11
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
-
};
|
|
13
6
|
var __export = (target, all) => {
|
|
14
7
|
for (var name in all)
|
|
15
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
9
|
};
|
|
17
|
-
var __copyProps = (to, from, except, desc) => {
|
|
18
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
-
for (let key of __getOwnPropNames(from))
|
|
20
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
-
}
|
|
23
|
-
return to;
|
|
24
|
-
};
|
|
25
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
-
mod
|
|
32
|
-
));
|
|
33
|
-
|
|
34
|
-
// ../../node_modules/keytar/lib/keytar.js
|
|
35
|
-
var require_keytar = __commonJS({
|
|
36
|
-
"../../node_modules/keytar/lib/keytar.js"(exports, module) {
|
|
37
|
-
"use strict";
|
|
38
|
-
function disabled() {
|
|
39
|
-
throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
|
|
40
|
-
}
|
|
41
|
-
module.exports = {
|
|
42
|
-
getPassword: disabled,
|
|
43
|
-
setPassword: disabled,
|
|
44
|
-
deletePassword: disabled,
|
|
45
|
-
findPassword: disabled,
|
|
46
|
-
findCredentials: disabled
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
10
|
|
|
51
11
|
// src/claims.ts
|
|
52
12
|
var claims_exports = {};
|
|
@@ -259,21 +219,7 @@ var KEY_FILE = join(TERMINALHIRE_DIR, "key");
|
|
|
259
219
|
var ALGO = "aes-256-gcm";
|
|
260
220
|
var KEY_BYTES = 32;
|
|
261
221
|
var IV_BYTES = 12;
|
|
262
|
-
function skipKeychain() {
|
|
263
|
-
return process.env.TERMINALHIRE_NO_KEYCHAIN !== void 0 || process.env.CI !== void 0 || process.env.VITEST !== void 0 || process.env.NODE_ENV === "test";
|
|
264
|
-
}
|
|
265
222
|
async function loadKey() {
|
|
266
|
-
if (!skipKeychain()) {
|
|
267
|
-
try {
|
|
268
|
-
const kt = await Promise.resolve().then(() => __toESM(require_keytar(), 1));
|
|
269
|
-
const stored = await kt.getPassword("terminalhire", "profile-key");
|
|
270
|
-
if (stored) return Buffer.from(stored, "hex");
|
|
271
|
-
const key2 = randomBytes(KEY_BYTES);
|
|
272
|
-
await kt.setPassword("terminalhire", "profile-key", key2.toString("hex"));
|
|
273
|
-
return key2;
|
|
274
|
-
} catch {
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
223
|
mkdirSync(TERMINALHIRE_DIR, { recursive: true, mode: 448 });
|
|
278
224
|
if (existsSync(KEY_FILE)) {
|
|
279
225
|
return Buffer.from(readFileSync(KEY_FILE, "utf8").trim(), "hex");
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
4
|
var __esm = (fn, res) => function __init() {
|
|
9
5
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
6
|
};
|
|
11
|
-
var __commonJS = (cb, mod2) => function __require() {
|
|
12
|
-
return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
|
|
13
|
-
};
|
|
14
7
|
var __export = (target, all) => {
|
|
15
8
|
for (var name in all)
|
|
16
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
10
|
};
|
|
18
|
-
var __copyProps = (to, from, except, desc) => {
|
|
19
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
-
for (let key of __getOwnPropNames(from))
|
|
21
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
-
}
|
|
24
|
-
return to;
|
|
25
|
-
};
|
|
26
|
-
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
27
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
28
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
29
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
30
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
31
|
-
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
32
|
-
mod2
|
|
33
|
-
));
|
|
34
11
|
|
|
35
12
|
// ../../packages/core/src/types.ts
|
|
36
13
|
function isBounty(job) {
|
|
@@ -1748,6 +1725,32 @@ async function openPRClosingRefs(owner, name, token, signal, governor) {
|
|
|
1748
1725
|
return null;
|
|
1749
1726
|
}
|
|
1750
1727
|
}
|
|
1728
|
+
async function issueCrossRefPRAttempts(owner, name, issueNumber, token, signal, governor) {
|
|
1729
|
+
const url = `https://api.github.com/repos/${owner}/${name}/issues/${issueNumber}/timeline?per_page=100`;
|
|
1730
|
+
try {
|
|
1731
|
+
const res = governor ? await governor.get(url, { headers: ghHeaders(token), signal }) : await fetch(url, { headers: ghHeaders(token), signal });
|
|
1732
|
+
if (!res || !res.ok) return null;
|
|
1733
|
+
const link = res.headers?.get("link") ?? null;
|
|
1734
|
+
const hasNextPage = link != null && /\brel="next"/.test(link);
|
|
1735
|
+
const events = await res.json();
|
|
1736
|
+
if (!Array.isArray(events)) return null;
|
|
1737
|
+
if (hasNextPage || events.length >= 100) return null;
|
|
1738
|
+
let hasOpenPR = false;
|
|
1739
|
+
let hasClosedPR = false;
|
|
1740
|
+
const prNumbers = [];
|
|
1741
|
+
for (const ev of events) {
|
|
1742
|
+
if (ev?.event !== "cross-referenced") continue;
|
|
1743
|
+
const src = ev.source?.issue;
|
|
1744
|
+
if (!src || src.pull_request == null) continue;
|
|
1745
|
+
if (typeof src.number === "number") prNumbers.push(src.number);
|
|
1746
|
+
if (src.state === "open") hasOpenPR = true;
|
|
1747
|
+
else if (src.state === "closed") hasClosedPR = true;
|
|
1748
|
+
}
|
|
1749
|
+
return { hasOpenPR, hasClosedPR, prNumbers };
|
|
1750
|
+
} catch {
|
|
1751
|
+
return null;
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1751
1754
|
function makeScoringGovernor(governor) {
|
|
1752
1755
|
return governor ?? makeGitHubGovernor(
|
|
1753
1756
|
((url, init) => fetch(url, init)),
|
|
@@ -3925,6 +3928,30 @@ var init_feeds = __esm({
|
|
|
3925
3928
|
});
|
|
3926
3929
|
|
|
3927
3930
|
// ../../packages/core/src/feeds/contributions.ts
|
|
3931
|
+
function readSearchMaxPages() {
|
|
3932
|
+
const raw = process.env["CONTRIB_SEARCH_MAX_PAGES"];
|
|
3933
|
+
if (raw == null) return DEFAULT_SEARCH_MAX_PAGES;
|
|
3934
|
+
const n = Number.parseInt(raw, 10);
|
|
3935
|
+
if (Number.isNaN(n)) return DEFAULT_SEARCH_MAX_PAGES;
|
|
3936
|
+
return Math.min(Math.max(n, MIN_SEARCH_MAX_PAGES), MAX_SEARCH_MAX_PAGES);
|
|
3937
|
+
}
|
|
3938
|
+
function readMaxContribItems() {
|
|
3939
|
+
const raw = process.env["CONTRIB_MAX_ITEMS"];
|
|
3940
|
+
if (raw == null) return DEFAULT_MAX_CONTRIB_ITEMS;
|
|
3941
|
+
const n = Number.parseInt(raw, 10);
|
|
3942
|
+
if (Number.isNaN(n)) return DEFAULT_MAX_CONTRIB_ITEMS;
|
|
3943
|
+
return Math.min(Math.max(n, MIN_MAX_CONTRIB_ITEMS), MAX_MAX_CONTRIB_ITEMS);
|
|
3944
|
+
}
|
|
3945
|
+
function readMaxContribIssuesScanned() {
|
|
3946
|
+
const raw = process.env["CONTRIB_MAX_ISSUES_SCANNED"];
|
|
3947
|
+
if (raw == null) return DEFAULT_MAX_CONTRIB_ISSUES_SCANNED;
|
|
3948
|
+
const n = Number.parseInt(raw, 10);
|
|
3949
|
+
if (Number.isNaN(n)) return DEFAULT_MAX_CONTRIB_ISSUES_SCANNED;
|
|
3950
|
+
return Math.min(
|
|
3951
|
+
Math.max(n, MIN_MAX_CONTRIB_ISSUES_SCANNED),
|
|
3952
|
+
MAX_MAX_CONTRIB_ISSUES_SCANNED
|
|
3953
|
+
);
|
|
3954
|
+
}
|
|
3928
3955
|
function authHeaders2() {
|
|
3929
3956
|
const token = process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
|
|
3930
3957
|
const h = {
|
|
@@ -4012,13 +4039,21 @@ async function fetchRateLimit(client) {
|
|
|
4012
4039
|
}
|
|
4013
4040
|
async function searchContribIssues(client, queries) {
|
|
4014
4041
|
const byUrl = /* @__PURE__ */ new Map();
|
|
4042
|
+
const maxPages = readSearchMaxPages();
|
|
4015
4043
|
for (const q of queries) {
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
if (
|
|
4044
|
+
for (let page = 1; page <= maxPages; page++) {
|
|
4045
|
+
const res = await client.json(
|
|
4046
|
+
`/search/issues?q=${encodeURIComponent(q)}&sort=created&order=desc&per_page=${SEARCH_PER_PAGE2}&page=${page}`
|
|
4047
|
+
);
|
|
4048
|
+
const items = res?.items;
|
|
4049
|
+
if (items == null) break;
|
|
4050
|
+
for (const it of items) {
|
|
4051
|
+
if (it.pull_request) continue;
|
|
4052
|
+
if (!byUrl.has(it.html_url)) byUrl.set(it.html_url, it);
|
|
4053
|
+
}
|
|
4054
|
+
if (items.length < SEARCH_PER_PAGE2) break;
|
|
4055
|
+
const stats = client.getStats();
|
|
4056
|
+
if (stats.budgetAborted || stats.secondaryAborted) break;
|
|
4022
4057
|
}
|
|
4023
4058
|
}
|
|
4024
4059
|
return [...byUrl.values()].sort(
|
|
@@ -4079,10 +4114,14 @@ async function aggregateContributions(opts = {}) {
|
|
|
4079
4114
|
probeTimeoutMs: opts.fetchImpl ? null : PROBE_TIMEOUT_MS
|
|
4080
4115
|
});
|
|
4081
4116
|
const queries = opts.queries ?? CONTRIB_SEARCH_QUERIES;
|
|
4117
|
+
const maxContribItems = readMaxContribItems();
|
|
4082
4118
|
const startRl = await fetchRateLimit(client);
|
|
4083
4119
|
const coreHealthyAtStart = (startRl?.core?.remaining ?? 0) >= 500;
|
|
4084
4120
|
client.setSecondaryHint(coreHealthyAtStart);
|
|
4085
|
-
const issues = (await searchContribIssues(client, queries)).slice(
|
|
4121
|
+
const issues = (await searchContribIssues(client, queries)).slice(
|
|
4122
|
+
0,
|
|
4123
|
+
readMaxContribIssuesScanned()
|
|
4124
|
+
);
|
|
4086
4125
|
const repoCache = /* @__PURE__ */ new Map();
|
|
4087
4126
|
const contribCache = /* @__PURE__ */ new Map();
|
|
4088
4127
|
const prRefsCache = /* @__PURE__ */ new Map();
|
|
@@ -4172,7 +4211,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
4172
4211
|
let contribUndefined = 0;
|
|
4173
4212
|
let prRefsNull = 0;
|
|
4174
4213
|
for (const issue of issues) {
|
|
4175
|
-
if (jobs.length >=
|
|
4214
|
+
if (jobs.length >= maxContribItems) break;
|
|
4176
4215
|
const fullName = repoFullNameFromApiUrl2(issue.repository_url);
|
|
4177
4216
|
if (!fullName) continue;
|
|
4178
4217
|
const id = `contribute:${repoKey(fullName)}#${issue.number}`;
|
|
@@ -4230,7 +4269,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
4230
4269
|
const doDiscovery = opts.discoverRepos ?? (opts.trendingSlugs != null || opts.vocabTerms != null);
|
|
4231
4270
|
let discoveredEmitted = 0;
|
|
4232
4271
|
let discoveryBudgetStopped = false;
|
|
4233
|
-
if (doDiscovery && jobs.length <
|
|
4272
|
+
if (doDiscovery && jobs.length < maxContribItems) {
|
|
4234
4273
|
const maxRepos = Math.min(
|
|
4235
4274
|
Math.max(0, opts.maxDiscoveredRepos ?? MAX_DISCOVERED_REPOS),
|
|
4236
4275
|
MAX_DISCOVERED_REPOS
|
|
@@ -4283,7 +4322,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
4283
4322
|
}
|
|
4284
4323
|
const scanned = candidates.slice(0, maxRepos);
|
|
4285
4324
|
for (const fullName of scanned) {
|
|
4286
|
-
if (jobs.length >=
|
|
4325
|
+
if (jobs.length >= maxContribItems) break;
|
|
4287
4326
|
if (client.getStats().budgetAborted || client.getStats().secondaryAborted) {
|
|
4288
4327
|
discoveryBudgetStopped = true;
|
|
4289
4328
|
break;
|
|
@@ -4308,7 +4347,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
4308
4347
|
const repoIssues = (searchRes?.items ?? []).filter((it) => !it.pull_request);
|
|
4309
4348
|
let perRepoDiscovered = 0;
|
|
4310
4349
|
for (const issue of repoIssues) {
|
|
4311
|
-
if (jobs.length >=
|
|
4350
|
+
if (jobs.length >= maxContribItems) break;
|
|
4312
4351
|
if (perRepoDiscovered >= MAX_ISSUES_PER_DISCOVERED_REPO) break;
|
|
4313
4352
|
if ((perRepo.get(repoKey(fullName)) ?? 0) >= MAX_BOUNTIES_PER_DISCOVERED_REPO) break;
|
|
4314
4353
|
const id = `contribute:${repoKey(fullName)}#${issue.number}`;
|
|
@@ -4373,7 +4412,7 @@ async function aggregateContributions(opts = {}) {
|
|
|
4373
4412
|
}
|
|
4374
4413
|
return jobs;
|
|
4375
4414
|
}
|
|
4376
|
-
var GITHUB_API2, CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2,
|
|
4415
|
+
var GITHUB_API2, CONTRIB_LABEL_QUERIES, CONTRIB_LANGUAGE_QUERIES, CONTRIB_SEARCH_QUERIES, SEARCH_PER_PAGE2, DEFAULT_SEARCH_MAX_PAGES, MIN_SEARCH_MAX_PAGES, MAX_SEARCH_MAX_PAGES, DEFAULT_MAX_CONTRIB_ITEMS, MIN_MAX_CONTRIB_ITEMS, MAX_MAX_CONTRIB_ITEMS, DEFAULT_MAX_CONTRIB_ISSUES_SCANNED, MIN_MAX_CONTRIB_ISSUES_SCANNED, MAX_MAX_CONTRIB_ISSUES_SCANNED, MAX_DISCOVERED_REPOS, MAX_ISSUES_PER_DISCOVERED_REPO, DISCOVERY_REPOS_PER_TERM, DISCOVERY_VOCAB_TERMS, DISCOVERY_ISSUE_LABELS, repoKey;
|
|
4377
4416
|
var init_contributions = __esm({
|
|
4378
4417
|
"../../packages/core/src/feeds/contributions.ts"() {
|
|
4379
4418
|
"use strict";
|
|
@@ -4392,7 +4431,11 @@ var init_contributions = __esm({
|
|
|
4392
4431
|
'label:"good-first-issue" type:issue state:open',
|
|
4393
4432
|
'label:"help wanted" type:issue state:open',
|
|
4394
4433
|
'label:"help-wanted" type:issue state:open',
|
|
4395
|
-
'label:"up-for-grabs" type:issue state:open'
|
|
4434
|
+
'label:"up-for-grabs" type:issue state:open',
|
|
4435
|
+
// supply-expansion D: two more first-contribution label families widen the
|
|
4436
|
+
// global newest-first slice WITHOUT relaxing the credential gate.
|
|
4437
|
+
'label:"beginner-friendly" type:issue state:open',
|
|
4438
|
+
'label:"first-timers-only" type:issue state:open'
|
|
4396
4439
|
];
|
|
4397
4440
|
CONTRIB_LANGUAGE_QUERIES = [
|
|
4398
4441
|
...["rust", "go", "python", "c++", "ruby"].map(
|
|
@@ -4400,12 +4443,30 @@ var init_contributions = __esm({
|
|
|
4400
4443
|
),
|
|
4401
4444
|
...["rust", "go"].map(
|
|
4402
4445
|
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
4446
|
+
),
|
|
4447
|
+
// supply-expansion D: cover the high-volume web/enterprise ecosystems the
|
|
4448
|
+
// original set omitted. TS/JS were previously left out of "good first issue"
|
|
4449
|
+
// (the global slice over-represented them) but a LANGUAGE-scoped page surfaces
|
|
4450
|
+
// DIFFERENT repos than the global newest-first slice, so re-including them widens
|
|
4451
|
+
// distinct-repo coverage rather than duplicating it.
|
|
4452
|
+
...["typescript", "javascript", "java", "python"].map(
|
|
4453
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
4454
|
+
),
|
|
4455
|
+
...["typescript", "javascript", "c#", "php"].map(
|
|
4456
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
4403
4457
|
)
|
|
4404
4458
|
];
|
|
4405
4459
|
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
4406
4460
|
SEARCH_PER_PAGE2 = 100;
|
|
4407
|
-
|
|
4408
|
-
|
|
4461
|
+
DEFAULT_SEARCH_MAX_PAGES = 1;
|
|
4462
|
+
MIN_SEARCH_MAX_PAGES = 1;
|
|
4463
|
+
MAX_SEARCH_MAX_PAGES = 5;
|
|
4464
|
+
DEFAULT_MAX_CONTRIB_ITEMS = 400;
|
|
4465
|
+
MIN_MAX_CONTRIB_ITEMS = 50;
|
|
4466
|
+
MAX_MAX_CONTRIB_ITEMS = 1e3;
|
|
4467
|
+
DEFAULT_MAX_CONTRIB_ISSUES_SCANNED = 1500;
|
|
4468
|
+
MIN_MAX_CONTRIB_ISSUES_SCANNED = 100;
|
|
4469
|
+
MAX_MAX_CONTRIB_ISSUES_SCANNED = 5e3;
|
|
4409
4470
|
MAX_DISCOVERED_REPOS = 15;
|
|
4410
4471
|
MAX_ISSUES_PER_DISCOVERED_REPO = 3;
|
|
4411
4472
|
DISCOVERY_REPOS_PER_TERM = 20;
|
|
@@ -8387,6 +8448,7 @@ __export(src_exports, {
|
|
|
8387
8448
|
isOverIntroLimit: () => isOverIntroLimit,
|
|
8388
8449
|
isTrivialPRTitle: () => isTrivialPRTitle,
|
|
8389
8450
|
isWinnableIssue: () => isWinnableIssue,
|
|
8451
|
+
issueCrossRefPRAttempts: () => issueCrossRefPRAttempts,
|
|
8390
8452
|
jobShortToken: () => jobShortToken,
|
|
8391
8453
|
joinLabels: () => joinLabels,
|
|
8392
8454
|
labelFor: () => labelFor,
|
|
@@ -8458,23 +8520,6 @@ var init_src = __esm({
|
|
|
8458
8520
|
}
|
|
8459
8521
|
});
|
|
8460
8522
|
|
|
8461
|
-
// ../../node_modules/keytar/lib/keytar.js
|
|
8462
|
-
var require_keytar = __commonJS({
|
|
8463
|
-
"../../node_modules/keytar/lib/keytar.js"(exports, module) {
|
|
8464
|
-
"use strict";
|
|
8465
|
-
function disabled() {
|
|
8466
|
-
throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
|
|
8467
|
-
}
|
|
8468
|
-
module.exports = {
|
|
8469
|
-
getPassword: disabled,
|
|
8470
|
-
setPassword: disabled,
|
|
8471
|
-
deletePassword: disabled,
|
|
8472
|
-
findPassword: disabled,
|
|
8473
|
-
findCredentials: disabled
|
|
8474
|
-
};
|
|
8475
|
-
}
|
|
8476
|
-
});
|
|
8477
|
-
|
|
8478
8523
|
// src/crypto-store.ts
|
|
8479
8524
|
import {
|
|
8480
8525
|
createCipheriv,
|
|
@@ -8519,10 +8564,10 @@ function decrypt(blob, key) {
|
|
|
8519
8564
|
function skipKeychain() {
|
|
8520
8565
|
return process.env.TERMINALHIRE_NO_KEYCHAIN !== void 0 || process.env.CI !== void 0 || process.env.VITEST !== void 0 || process.env.NODE_ENV === "test";
|
|
8521
8566
|
}
|
|
8522
|
-
async function tryLoadFromKeytar(
|
|
8567
|
+
async function tryLoadFromKeytar() {
|
|
8523
8568
|
if (forceKeytarUnavailableForTests || skipKeychain()) return null;
|
|
8524
8569
|
try {
|
|
8525
|
-
const kt =
|
|
8570
|
+
const kt = createRequire(import.meta.url)("keytar");
|
|
8526
8571
|
const stored = await kt.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
|
|
8527
8572
|
if (stored) {
|
|
8528
8573
|
return Buffer.from(stored, "hex");
|
|
@@ -8563,7 +8608,7 @@ async function deleteKey() {
|
|
|
8563
8608
|
}
|
|
8564
8609
|
if (!forceKeytarUnavailableForTests && !skipKeychain()) {
|
|
8565
8610
|
try {
|
|
8566
|
-
const kt =
|
|
8611
|
+
const kt = createRequire(import.meta.url)("keytar");
|
|
8567
8612
|
await kt.deletePassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
|
|
8568
8613
|
} catch {
|
|
8569
8614
|
}
|
|
@@ -8575,15 +8620,13 @@ async function deleteKey() {
|
|
|
8575
8620
|
}
|
|
8576
8621
|
async function resolveKey(filePath, opts) {
|
|
8577
8622
|
if (opts.keyPolicy === "keychain-required") {
|
|
8578
|
-
const key = await tryLoadFromKeytar(
|
|
8623
|
+
const key = await tryLoadFromKeytar();
|
|
8579
8624
|
if (!key) {
|
|
8580
8625
|
warnStderr(`crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`);
|
|
8581
8626
|
return null;
|
|
8582
8627
|
}
|
|
8583
8628
|
return key;
|
|
8584
8629
|
}
|
|
8585
|
-
const fromKeytar = await tryLoadFromKeytar("keytar-first-file-fallback");
|
|
8586
|
-
if (fromKeytar) return fromKeytar;
|
|
8587
8630
|
return loadOrCreateFileKey();
|
|
8588
8631
|
}
|
|
8589
8632
|
function createEncryptedStore(filePath, opts) {
|
|
@@ -1,32 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
3
|
var __esm = (fn, res) => function __init() {
|
|
9
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
5
|
};
|
|
11
|
-
var __commonJS = (cb, mod2) => function __require() {
|
|
12
|
-
return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
|
|
13
|
-
};
|
|
14
|
-
var __copyProps = (to, from, except, desc) => {
|
|
15
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
-
for (let key of __getOwnPropNames(from))
|
|
17
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
23
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
-
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
28
|
-
mod2
|
|
29
|
-
));
|
|
30
6
|
|
|
31
7
|
// ../../packages/core/src/types.ts
|
|
32
8
|
var init_types = __esm({
|
|
@@ -892,7 +868,11 @@ var init_contributions = __esm({
|
|
|
892
868
|
'label:"good-first-issue" type:issue state:open',
|
|
893
869
|
'label:"help wanted" type:issue state:open',
|
|
894
870
|
'label:"help-wanted" type:issue state:open',
|
|
895
|
-
'label:"up-for-grabs" type:issue state:open'
|
|
871
|
+
'label:"up-for-grabs" type:issue state:open',
|
|
872
|
+
// supply-expansion D: two more first-contribution label families widen the
|
|
873
|
+
// global newest-first slice WITHOUT relaxing the credential gate.
|
|
874
|
+
'label:"beginner-friendly" type:issue state:open',
|
|
875
|
+
'label:"first-timers-only" type:issue state:open'
|
|
896
876
|
];
|
|
897
877
|
CONTRIB_LANGUAGE_QUERIES = [
|
|
898
878
|
...["rust", "go", "python", "c++", "ruby"].map(
|
|
@@ -900,6 +880,17 @@ var init_contributions = __esm({
|
|
|
900
880
|
),
|
|
901
881
|
...["rust", "go"].map(
|
|
902
882
|
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
883
|
+
),
|
|
884
|
+
// supply-expansion D: cover the high-volume web/enterprise ecosystems the
|
|
885
|
+
// original set omitted. TS/JS were previously left out of "good first issue"
|
|
886
|
+
// (the global slice over-represented them) but a LANGUAGE-scoped page surfaces
|
|
887
|
+
// DIFFERENT repos than the global newest-first slice, so re-including them widens
|
|
888
|
+
// distinct-repo coverage rather than duplicating it.
|
|
889
|
+
...["typescript", "javascript", "java", "python"].map(
|
|
890
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
891
|
+
),
|
|
892
|
+
...["typescript", "javascript", "c#", "php"].map(
|
|
893
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
903
894
|
)
|
|
904
895
|
];
|
|
905
896
|
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
@@ -4107,23 +4098,6 @@ var init_src = __esm({
|
|
|
4107
4098
|
}
|
|
4108
4099
|
});
|
|
4109
4100
|
|
|
4110
|
-
// ../../node_modules/keytar/lib/keytar.js
|
|
4111
|
-
var require_keytar = __commonJS({
|
|
4112
|
-
"../../node_modules/keytar/lib/keytar.js"(exports, module) {
|
|
4113
|
-
"use strict";
|
|
4114
|
-
function disabled() {
|
|
4115
|
-
throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
|
|
4116
|
-
}
|
|
4117
|
-
module.exports = {
|
|
4118
|
-
getPassword: disabled,
|
|
4119
|
-
setPassword: disabled,
|
|
4120
|
-
deletePassword: disabled,
|
|
4121
|
-
findPassword: disabled,
|
|
4122
|
-
findCredentials: disabled
|
|
4123
|
-
};
|
|
4124
|
-
}
|
|
4125
|
-
});
|
|
4126
|
-
|
|
4127
4101
|
// src/github-auth.ts
|
|
4128
4102
|
import {
|
|
4129
4103
|
createCipheriv,
|
|
@@ -4140,21 +4114,7 @@ import {
|
|
|
4140
4114
|
} from "fs";
|
|
4141
4115
|
import { join as join2 } from "path";
|
|
4142
4116
|
import { homedir } from "os";
|
|
4143
|
-
function skipKeychain() {
|
|
4144
|
-
return process.env.TERMINALHIRE_NO_KEYCHAIN !== void 0 || process.env.CI !== void 0 || process.env.VITEST !== void 0 || process.env.NODE_ENV === "test";
|
|
4145
|
-
}
|
|
4146
4117
|
async function loadKey() {
|
|
4147
|
-
if (!skipKeychain()) {
|
|
4148
|
-
try {
|
|
4149
|
-
const kt = await Promise.resolve().then(() => __toESM(require_keytar(), 1));
|
|
4150
|
-
const stored = await kt.getPassword("terminalhire", "profile-key");
|
|
4151
|
-
if (stored) return Buffer.from(stored, "hex");
|
|
4152
|
-
const key2 = randomBytes3(KEY_BYTES);
|
|
4153
|
-
await kt.setPassword("terminalhire", "profile-key", key2.toString("hex"));
|
|
4154
|
-
return key2;
|
|
4155
|
-
} catch {
|
|
4156
|
-
}
|
|
4157
|
-
}
|
|
4158
4118
|
mkdirSync(TERMINALHIRE_DIR, { recursive: true, mode: 448 });
|
|
4159
4119
|
if (existsSync(KEY_FILE)) {
|
|
4160
4120
|
return Buffer.from(readFileSync2(KEY_FILE, "utf8").trim(), "hex");
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
4
|
var __esm = (fn, res) => function __init() {
|
|
9
5
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
6
|
};
|
|
11
|
-
var __commonJS = (cb, mod2) => function __require() {
|
|
12
|
-
return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
|
|
13
|
-
};
|
|
14
7
|
var __export = (target, all) => {
|
|
15
8
|
for (var name in all)
|
|
16
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
10
|
};
|
|
18
|
-
var __copyProps = (to, from, except, desc) => {
|
|
19
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
-
for (let key of __getOwnPropNames(from))
|
|
21
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
-
}
|
|
24
|
-
return to;
|
|
25
|
-
};
|
|
26
|
-
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
27
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
28
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
29
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
30
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
31
|
-
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
32
|
-
mod2
|
|
33
|
-
));
|
|
34
11
|
|
|
35
12
|
// ../../packages/core/src/types.ts
|
|
36
13
|
var init_types = __esm({
|
|
@@ -909,7 +886,11 @@ var init_contributions = __esm({
|
|
|
909
886
|
'label:"good-first-issue" type:issue state:open',
|
|
910
887
|
'label:"help wanted" type:issue state:open',
|
|
911
888
|
'label:"help-wanted" type:issue state:open',
|
|
912
|
-
'label:"up-for-grabs" type:issue state:open'
|
|
889
|
+
'label:"up-for-grabs" type:issue state:open',
|
|
890
|
+
// supply-expansion D: two more first-contribution label families widen the
|
|
891
|
+
// global newest-first slice WITHOUT relaxing the credential gate.
|
|
892
|
+
'label:"beginner-friendly" type:issue state:open',
|
|
893
|
+
'label:"first-timers-only" type:issue state:open'
|
|
913
894
|
];
|
|
914
895
|
CONTRIB_LANGUAGE_QUERIES = [
|
|
915
896
|
...["rust", "go", "python", "c++", "ruby"].map(
|
|
@@ -917,6 +898,17 @@ var init_contributions = __esm({
|
|
|
917
898
|
),
|
|
918
899
|
...["rust", "go"].map(
|
|
919
900
|
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
901
|
+
),
|
|
902
|
+
// supply-expansion D: cover the high-volume web/enterprise ecosystems the
|
|
903
|
+
// original set omitted. TS/JS were previously left out of "good first issue"
|
|
904
|
+
// (the global slice over-represented them) but a LANGUAGE-scoped page surfaces
|
|
905
|
+
// DIFFERENT repos than the global newest-first slice, so re-including them widens
|
|
906
|
+
// distinct-repo coverage rather than duplicating it.
|
|
907
|
+
...["typescript", "javascript", "java", "python"].map(
|
|
908
|
+
(lang) => `label:"good first issue" language:${lang} type:issue state:open`
|
|
909
|
+
),
|
|
910
|
+
...["typescript", "javascript", "c#", "php"].map(
|
|
911
|
+
(lang) => `label:"help wanted" language:${lang} type:issue state:open`
|
|
920
912
|
)
|
|
921
913
|
];
|
|
922
914
|
CONTRIB_SEARCH_QUERIES = [...CONTRIB_LABEL_QUERIES, ...CONTRIB_LANGUAGE_QUERIES];
|
|
@@ -4135,23 +4127,6 @@ var init_src = __esm({
|
|
|
4135
4127
|
}
|
|
4136
4128
|
});
|
|
4137
4129
|
|
|
4138
|
-
// ../../node_modules/keytar/lib/keytar.js
|
|
4139
|
-
var require_keytar = __commonJS({
|
|
4140
|
-
"../../node_modules/keytar/lib/keytar.js"(exports, module) {
|
|
4141
|
-
"use strict";
|
|
4142
|
-
function disabled() {
|
|
4143
|
-
throw new Error("keytar disabled in this dev checkout (keychain popup guard) \u2014 key-file fallback expected");
|
|
4144
|
-
}
|
|
4145
|
-
module.exports = {
|
|
4146
|
-
getPassword: disabled,
|
|
4147
|
-
setPassword: disabled,
|
|
4148
|
-
deletePassword: disabled,
|
|
4149
|
-
findPassword: disabled,
|
|
4150
|
-
findCredentials: disabled
|
|
4151
|
-
};
|
|
4152
|
-
}
|
|
4153
|
-
});
|
|
4154
|
-
|
|
4155
4130
|
// src/github-auth.ts
|
|
4156
4131
|
import {
|
|
4157
4132
|
createCipheriv,
|
|
@@ -4168,21 +4143,7 @@ import {
|
|
|
4168
4143
|
} from "fs";
|
|
4169
4144
|
import { join as join2 } from "path";
|
|
4170
4145
|
import { homedir } from "os";
|
|
4171
|
-
function skipKeychain() {
|
|
4172
|
-
return process.env.TERMINALHIRE_NO_KEYCHAIN !== void 0 || process.env.CI !== void 0 || process.env.VITEST !== void 0 || process.env.NODE_ENV === "test";
|
|
4173
|
-
}
|
|
4174
4146
|
async function loadKey() {
|
|
4175
|
-
if (!skipKeychain()) {
|
|
4176
|
-
try {
|
|
4177
|
-
const kt = await Promise.resolve().then(() => __toESM(require_keytar(), 1));
|
|
4178
|
-
const stored = await kt.getPassword("terminalhire", "profile-key");
|
|
4179
|
-
if (stored) return Buffer.from(stored, "hex");
|
|
4180
|
-
const key2 = randomBytes3(KEY_BYTES);
|
|
4181
|
-
await kt.setPassword("terminalhire", "profile-key", key2.toString("hex"));
|
|
4182
|
-
return key2;
|
|
4183
|
-
} catch {
|
|
4184
|
-
}
|
|
4185
|
-
}
|
|
4186
4147
|
mkdirSync(TERMINALHIRE_DIR, { recursive: true, mode: 448 });
|
|
4187
4148
|
if (existsSync(KEY_FILE)) {
|
|
4188
4149
|
return Buffer.from(readFileSync2(KEY_FILE, "utf8").trim(), "hex");
|
|
@@ -5072,13 +5033,13 @@ function decrypt2(blob, key) {
|
|
|
5072
5033
|
]);
|
|
5073
5034
|
return plain.toString("utf8");
|
|
5074
5035
|
}
|
|
5075
|
-
function
|
|
5036
|
+
function skipKeychain() {
|
|
5076
5037
|
return process.env.TERMINALHIRE_NO_KEYCHAIN !== void 0 || process.env.CI !== void 0 || process.env.VITEST !== void 0 || process.env.NODE_ENV === "test";
|
|
5077
5038
|
}
|
|
5078
|
-
async function tryLoadFromKeytar(
|
|
5079
|
-
if (forceKeytarUnavailableForTests ||
|
|
5039
|
+
async function tryLoadFromKeytar() {
|
|
5040
|
+
if (forceKeytarUnavailableForTests || skipKeychain()) return null;
|
|
5080
5041
|
try {
|
|
5081
|
-
const kt =
|
|
5042
|
+
const kt = createRequire(import.meta.url)("keytar");
|
|
5082
5043
|
const stored = await kt.getPassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
|
|
5083
5044
|
if (stored) {
|
|
5084
5045
|
return Buffer.from(stored, "hex");
|
|
@@ -5117,9 +5078,9 @@ async function deleteKey() {
|
|
|
5117
5078
|
} catch {
|
|
5118
5079
|
}
|
|
5119
5080
|
}
|
|
5120
|
-
if (!forceKeytarUnavailableForTests && !
|
|
5081
|
+
if (!forceKeytarUnavailableForTests && !skipKeychain()) {
|
|
5121
5082
|
try {
|
|
5122
|
-
const kt =
|
|
5083
|
+
const kt = createRequire(import.meta.url)("keytar");
|
|
5123
5084
|
await kt.deletePassword(KEYTAR_SERVICE, KEYTAR_ACCOUNT);
|
|
5124
5085
|
} catch {
|
|
5125
5086
|
}
|
|
@@ -5131,15 +5092,13 @@ async function deleteKey() {
|
|
|
5131
5092
|
}
|
|
5132
5093
|
async function resolveKey(filePath, opts) {
|
|
5133
5094
|
if (opts.keyPolicy === "keychain-required") {
|
|
5134
|
-
const key = await tryLoadFromKeytar(
|
|
5095
|
+
const key = await tryLoadFromKeytar();
|
|
5135
5096
|
if (!key) {
|
|
5136
5097
|
warnStderr(`crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`);
|
|
5137
5098
|
return null;
|
|
5138
5099
|
}
|
|
5139
5100
|
return key;
|
|
5140
5101
|
}
|
|
5141
|
-
const fromKeytar = await tryLoadFromKeytar("keytar-first-file-fallback");
|
|
5142
|
-
if (fromKeytar) return fromKeytar;
|
|
5143
5102
|
return loadOrCreateFileKey();
|
|
5144
5103
|
}
|
|
5145
5104
|
function createEncryptedStore(filePath, opts) {
|