terminalhire 0.9.0 → 0.9.2
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 +74 -39
- package/dist/bin/jpi-chat.js +75 -44
- package/dist/bin/jpi-dispatch.js +452 -210
- package/dist/bin/jpi-intro.js +72 -45
- package/dist/bin/jpi-link.js +285 -0
- package/dist/bin/jpi-trajectory.js +83 -44
- package/dist/src/chat-client.js +48 -15
- package/dist/src/intro.js +68 -45
- package/dist/src/link.js +253 -0
- package/dist/src/trajectory.js +77 -44
- package/dist/src/web-session.js +55 -0
- package/package.json +1 -1
package/dist/bin/jpi-dispatch.js
CHANGED
|
@@ -1943,14 +1943,14 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
1943
1943
|
if (items.length === 0) return results;
|
|
1944
1944
|
const workers = Math.max(1, Math.min(Math.floor(limit) || 1, items.length));
|
|
1945
1945
|
let next = 0;
|
|
1946
|
-
async function
|
|
1946
|
+
async function run19() {
|
|
1947
1947
|
for (; ; ) {
|
|
1948
1948
|
const i = next++;
|
|
1949
1949
|
if (i >= items.length) return;
|
|
1950
1950
|
results[i] = await fn(items[i], i);
|
|
1951
1951
|
}
|
|
1952
1952
|
}
|
|
1953
|
-
await Promise.all(Array.from({ length: workers },
|
|
1953
|
+
await Promise.all(Array.from({ length: workers }, run19));
|
|
1954
1954
|
return results;
|
|
1955
1955
|
}
|
|
1956
1956
|
var init_concurrency = __esm({
|
|
@@ -4603,7 +4603,7 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
|
|
|
4603
4603
|
});
|
|
4604
4604
|
const { prehash } = eddsaOpts;
|
|
4605
4605
|
const { BASE, Fp: Fp2, Fn: Fn2 } = Point;
|
|
4606
|
-
const
|
|
4606
|
+
const randomBytes6 = eddsaOpts.randomBytes || randomBytes2;
|
|
4607
4607
|
const adjustScalarBytes2 = eddsaOpts.adjustScalarBytes || ((bytes) => bytes);
|
|
4608
4608
|
const domain = eddsaOpts.domain || ((data, ctx, phflag) => {
|
|
4609
4609
|
_abool2(phflag, "phflag");
|
|
@@ -4685,7 +4685,7 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
|
|
|
4685
4685
|
signature: 2 * _size,
|
|
4686
4686
|
seed: _size
|
|
4687
4687
|
};
|
|
4688
|
-
function randomSecretKey(seed =
|
|
4688
|
+
function randomSecretKey(seed = randomBytes6(lengths.seed)) {
|
|
4689
4689
|
return _abytes2(seed, lengths.seed, "seed");
|
|
4690
4690
|
}
|
|
4691
4691
|
function keygen(seed) {
|
|
@@ -6370,13 +6370,13 @@ async function removeSavedJob(id) {
|
|
|
6370
6370
|
return true;
|
|
6371
6371
|
}
|
|
6372
6372
|
async function deleteProfile() {
|
|
6373
|
-
const { rmSync:
|
|
6373
|
+
const { rmSync: rmSync5 } = await import("fs");
|
|
6374
6374
|
try {
|
|
6375
|
-
|
|
6375
|
+
rmSync5(PROFILE_FILE);
|
|
6376
6376
|
} catch {
|
|
6377
6377
|
}
|
|
6378
6378
|
try {
|
|
6379
|
-
|
|
6379
|
+
rmSync5(KEY_FILE2);
|
|
6380
6380
|
} catch {
|
|
6381
6381
|
}
|
|
6382
6382
|
}
|
|
@@ -6613,11 +6613,11 @@ async function runLogin() {
|
|
|
6613
6613
|
if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
|
|
6614
6614
|
const { createRequire: createRequire2 } = await import("module");
|
|
6615
6615
|
const { fileURLToPath: fileURLToPath7 } = await import("url");
|
|
6616
|
-
const { join:
|
|
6616
|
+
const { join: join25, dirname: dirname3 } = await import("path");
|
|
6617
6617
|
const __dirname6 = fileURLToPath7(new URL(".", import.meta.url));
|
|
6618
|
-
const fixturePath =
|
|
6619
|
-
const { readFileSync:
|
|
6620
|
-
ghProfile = JSON.parse(
|
|
6618
|
+
const fixturePath = join25(__dirname6, "../../fixtures/github-sample.json");
|
|
6619
|
+
const { readFileSync: readFileSync23 } = await import("fs");
|
|
6620
|
+
ghProfile = JSON.parse(readFileSync23(fixturePath, "utf8"));
|
|
6621
6621
|
} else {
|
|
6622
6622
|
ghProfile = await fetchGitHubProfile2(login, token);
|
|
6623
6623
|
}
|
|
@@ -8377,7 +8377,7 @@ function finalize(build) {
|
|
|
8377
8377
|
};
|
|
8378
8378
|
}
|
|
8379
8379
|
function reconstruct(files, opts = {}) {
|
|
8380
|
-
const
|
|
8380
|
+
const join25 = opts.joinSidechains !== false;
|
|
8381
8381
|
const mains = [];
|
|
8382
8382
|
const sidechains = [];
|
|
8383
8383
|
for (const file of files) {
|
|
@@ -8402,7 +8402,7 @@ function reconstruct(files, opts = {}) {
|
|
|
8402
8402
|
}
|
|
8403
8403
|
const orphanedSidechainPaths = [];
|
|
8404
8404
|
const joinedPaths = /* @__PURE__ */ new Set();
|
|
8405
|
-
if (
|
|
8405
|
+
if (join25) {
|
|
8406
8406
|
const sidechainsBySession = /* @__PURE__ */ new Map();
|
|
8407
8407
|
for (const sc of sidechains) {
|
|
8408
8408
|
const acc = sidechainsBySession.get(sc.sessionId) ?? [];
|
|
@@ -8889,12 +8889,12 @@ function deriveRecoveryDepth(episodes, nodesByUuid) {
|
|
|
8889
8889
|
continue;
|
|
8890
8890
|
}
|
|
8891
8891
|
spansConsidered++;
|
|
8892
|
-
let
|
|
8892
|
+
let run19 = 0;
|
|
8893
8893
|
const closeChain = () => {
|
|
8894
|
-
if (
|
|
8894
|
+
if (run19 > 0) {
|
|
8895
8895
|
recoveryChains++;
|
|
8896
|
-
totalDepth +=
|
|
8897
|
-
|
|
8896
|
+
totalDepth += run19;
|
|
8897
|
+
run19 = 0;
|
|
8898
8898
|
}
|
|
8899
8899
|
};
|
|
8900
8900
|
for (const uuid of episode.mainNodeUuids) {
|
|
@@ -8903,9 +8903,9 @@ function deriveRecoveryDepth(episodes, nodesByUuid) {
|
|
|
8903
8903
|
continue;
|
|
8904
8904
|
}
|
|
8905
8905
|
if (node.kind === "tool_result" /* ToolResult */ && node.isError) {
|
|
8906
|
-
|
|
8907
|
-
if (
|
|
8908
|
-
maxConsecutiveErrors =
|
|
8906
|
+
run19++;
|
|
8907
|
+
if (run19 > maxConsecutiveErrors) {
|
|
8908
|
+
maxConsecutiveErrors = run19;
|
|
8909
8909
|
}
|
|
8910
8910
|
} else if (node.kind === "tool_result" /* ToolResult */ && !node.isError) {
|
|
8911
8911
|
closeChain();
|
|
@@ -8947,6 +8947,60 @@ var init_episodes = __esm({
|
|
|
8947
8947
|
}
|
|
8948
8948
|
});
|
|
8949
8949
|
|
|
8950
|
+
// src/web-session.ts
|
|
8951
|
+
import {
|
|
8952
|
+
chmodSync as chmodSync2,
|
|
8953
|
+
existsSync as existsSync7,
|
|
8954
|
+
mkdirSync as mkdirSync9,
|
|
8955
|
+
readFileSync as readFileSync11,
|
|
8956
|
+
rmSync as rmSync2,
|
|
8957
|
+
writeFileSync as writeFileSync9
|
|
8958
|
+
} from "fs";
|
|
8959
|
+
import { homedir as homedir10 } from "os";
|
|
8960
|
+
import { join as join11 } from "path";
|
|
8961
|
+
function terminalhireDir() {
|
|
8962
|
+
return join11(homedir10(), ".terminalhire");
|
|
8963
|
+
}
|
|
8964
|
+
function webSessionFilePath() {
|
|
8965
|
+
return join11(terminalhireDir(), "web-session");
|
|
8966
|
+
}
|
|
8967
|
+
function readWebSessionFile() {
|
|
8968
|
+
try {
|
|
8969
|
+
const path = webSessionFilePath();
|
|
8970
|
+
if (!existsSync7(path)) return null;
|
|
8971
|
+
const v = readFileSync11(path, "utf8").trim();
|
|
8972
|
+
return v.length > 0 ? v : null;
|
|
8973
|
+
} catch {
|
|
8974
|
+
return null;
|
|
8975
|
+
}
|
|
8976
|
+
}
|
|
8977
|
+
function readWebSessionCookie() {
|
|
8978
|
+
const fromFile = readWebSessionFile();
|
|
8979
|
+
if (fromFile) return fromFile;
|
|
8980
|
+
const env = process.env["TERMINALHIRE_WEB_SESSION"];
|
|
8981
|
+
return typeof env === "string" && env.length > 0 ? env : null;
|
|
8982
|
+
}
|
|
8983
|
+
function writeWebSessionFile(token) {
|
|
8984
|
+
mkdirSync9(terminalhireDir(), { recursive: true });
|
|
8985
|
+
const path = webSessionFilePath();
|
|
8986
|
+
writeFileSync9(path, token, { mode: 384, encoding: "utf8" });
|
|
8987
|
+
try {
|
|
8988
|
+
chmodSync2(path, 384);
|
|
8989
|
+
} catch {
|
|
8990
|
+
}
|
|
8991
|
+
}
|
|
8992
|
+
function clearWebSessionFile() {
|
|
8993
|
+
try {
|
|
8994
|
+
rmSync2(webSessionFilePath());
|
|
8995
|
+
} catch {
|
|
8996
|
+
}
|
|
8997
|
+
}
|
|
8998
|
+
var init_web_session = __esm({
|
|
8999
|
+
"src/web-session.ts"() {
|
|
9000
|
+
"use strict";
|
|
9001
|
+
}
|
|
9002
|
+
});
|
|
9003
|
+
|
|
8950
9004
|
// src/trajectory.ts
|
|
8951
9005
|
var trajectory_exports = {};
|
|
8952
9006
|
__export(trajectory_exports, {
|
|
@@ -8956,14 +9010,14 @@ __export(trajectory_exports, {
|
|
|
8956
9010
|
runTrajectoryPush: () => runTrajectoryPush
|
|
8957
9011
|
});
|
|
8958
9012
|
import {
|
|
8959
|
-
existsSync as
|
|
8960
|
-
mkdirSync as
|
|
8961
|
-
readFileSync as
|
|
9013
|
+
existsSync as existsSync8,
|
|
9014
|
+
mkdirSync as mkdirSync10,
|
|
9015
|
+
readFileSync as readFileSync12,
|
|
8962
9016
|
readdirSync,
|
|
8963
|
-
writeFileSync as
|
|
9017
|
+
writeFileSync as writeFileSync10
|
|
8964
9018
|
} from "fs";
|
|
8965
|
-
import { homedir as
|
|
8966
|
-
import { join as
|
|
9019
|
+
import { homedir as homedir11 } from "os";
|
|
9020
|
+
import { join as join12 } from "path";
|
|
8967
9021
|
function isRecord4(value) {
|
|
8968
9022
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8969
9023
|
}
|
|
@@ -8995,7 +9049,7 @@ function findJsonlFiles(dir) {
|
|
|
8995
9049
|
return out;
|
|
8996
9050
|
}
|
|
8997
9051
|
for (const entry of entries) {
|
|
8998
|
-
const full =
|
|
9052
|
+
const full = join12(dir, entry.name);
|
|
8999
9053
|
if (entry.isDirectory()) {
|
|
9000
9054
|
out.push(...findJsonlFiles(full));
|
|
9001
9055
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -9009,7 +9063,7 @@ function loadCorpus(paths) {
|
|
|
9009
9063
|
for (const path of paths) {
|
|
9010
9064
|
let text;
|
|
9011
9065
|
try {
|
|
9012
|
-
text =
|
|
9066
|
+
text = readFileSync12(path, "utf8");
|
|
9013
9067
|
} catch {
|
|
9014
9068
|
continue;
|
|
9015
9069
|
}
|
|
@@ -9108,12 +9162,12 @@ function renderMarkdown(view) {
|
|
|
9108
9162
|
return lines.join("\n");
|
|
9109
9163
|
}
|
|
9110
9164
|
function writeExportArtifacts(score, markdown) {
|
|
9111
|
-
const dir =
|
|
9112
|
-
|
|
9113
|
-
const jsonPath =
|
|
9114
|
-
const mdPath =
|
|
9115
|
-
|
|
9116
|
-
|
|
9165
|
+
const dir = join12(homedir11(), ".terminalhire");
|
|
9166
|
+
mkdirSync10(dir, { recursive: true });
|
|
9167
|
+
const jsonPath = join12(dir, "trajectory-export.json");
|
|
9168
|
+
const mdPath = join12(dir, "trajectory-export.md");
|
|
9169
|
+
writeFileSync10(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
|
|
9170
|
+
writeFileSync10(mdPath, markdown, "utf8");
|
|
9117
9171
|
return { jsonPath, mdPath };
|
|
9118
9172
|
}
|
|
9119
9173
|
function renderInward(allNodes, view, files) {
|
|
@@ -9132,8 +9186,8 @@ function renderInward(allNodes, view, files) {
|
|
|
9132
9186
|
console.log("");
|
|
9133
9187
|
}
|
|
9134
9188
|
function buildTrajectory() {
|
|
9135
|
-
const projectsDir =
|
|
9136
|
-
if (!
|
|
9189
|
+
const projectsDir = join12(homedir11(), ".claude", "projects");
|
|
9190
|
+
if (!existsSync8(projectsDir)) return null;
|
|
9137
9191
|
const paths = findJsonlFiles(projectsDir);
|
|
9138
9192
|
if (paths.length === 0) return null;
|
|
9139
9193
|
const files = loadCorpus(paths);
|
|
@@ -9220,10 +9274,9 @@ function defaultPushDeps() {
|
|
|
9220
9274
|
void Promise.resolve().then(() => (init_open_url(), open_url_exports)).then((m) => m.openInBrowser(url)).catch(() => {
|
|
9221
9275
|
});
|
|
9222
9276
|
},
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
},
|
|
9277
|
+
// Session source priority: persisted file (`terminalhire link`) FIRST, then the
|
|
9278
|
+
// legacy TERMINALHIRE_WEB_SESSION env, then none.
|
|
9279
|
+
sessionCookie: () => readWebSessionCookie(),
|
|
9227
9280
|
log: (msg) => console.log(msg),
|
|
9228
9281
|
errorLog: (msg) => console.error(msg),
|
|
9229
9282
|
exit: (code) => process.exit(code)
|
|
@@ -9382,6 +9435,7 @@ var init_trajectory = __esm({
|
|
|
9382
9435
|
"src/trajectory.ts"() {
|
|
9383
9436
|
"use strict";
|
|
9384
9437
|
init_episodes();
|
|
9438
|
+
init_web_session();
|
|
9385
9439
|
CAP_LABELS = {
|
|
9386
9440
|
"cap:ui-automation": "UI automation",
|
|
9387
9441
|
"cap:deploys": "Deployment",
|
|
@@ -9471,10 +9525,9 @@ function defaultIntroDeps() {
|
|
|
9471
9525
|
void Promise.resolve().then(() => (init_open_url(), open_url_exports)).then((m) => m.openInBrowser(url)).catch(() => {
|
|
9472
9526
|
});
|
|
9473
9527
|
},
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
},
|
|
9528
|
+
// Session source priority: persisted file (`terminalhire link`) FIRST, then the
|
|
9529
|
+
// legacy TERMINALHIRE_WEB_SESSION env, then none.
|
|
9530
|
+
sessionCookie: () => readWebSessionCookie(),
|
|
9478
9531
|
log: (msg) => console.log(msg),
|
|
9479
9532
|
errorLog: (msg) => console.error(msg),
|
|
9480
9533
|
exit: (code) => process.exit(code)
|
|
@@ -9546,10 +9599,7 @@ async function runIntroRequest(args5, overrides) {
|
|
|
9546
9599
|
const cookie = deps.sessionCookie();
|
|
9547
9600
|
if (!cookie) {
|
|
9548
9601
|
deps.log("\n No linked web session found on this machine.");
|
|
9549
|
-
deps.log("
|
|
9550
|
-
deps.log(` \u2192 ${LINK_BASE2}/dashboard
|
|
9551
|
-
`);
|
|
9552
|
-
deps.openBrowser(`${LINK_BASE2}/dashboard`);
|
|
9602
|
+
deps.log(" Run `terminalhire link` to connect this terminal to your account, then re-run.\n");
|
|
9553
9603
|
deps.exit(0);
|
|
9554
9604
|
return;
|
|
9555
9605
|
}
|
|
@@ -9569,9 +9619,8 @@ async function runIntroRequest(args5, overrides) {
|
|
|
9569
9619
|
return;
|
|
9570
9620
|
}
|
|
9571
9621
|
if (res.status === 401) {
|
|
9572
|
-
deps.log("\n Your web session expired
|
|
9573
|
-
deps.log(
|
|
9574
|
-
`);
|
|
9622
|
+
deps.log("\n Your linked web session expired.");
|
|
9623
|
+
deps.log(" Run `terminalhire link` to reconnect this terminal, then re-run.\n");
|
|
9575
9624
|
deps.exit(1);
|
|
9576
9625
|
return;
|
|
9577
9626
|
}
|
|
@@ -9602,10 +9651,7 @@ async function runIntroDecision(args5, overrides) {
|
|
|
9602
9651
|
const cookie = deps.sessionCookie();
|
|
9603
9652
|
if (!cookie) {
|
|
9604
9653
|
deps.log("\n No linked web session found on this machine.");
|
|
9605
|
-
deps.log("
|
|
9606
|
-
deps.log(` \u2192 ${LINK_BASE2}/dashboard
|
|
9607
|
-
`);
|
|
9608
|
-
deps.openBrowser(`${LINK_BASE2}/dashboard`);
|
|
9654
|
+
deps.log(" Run `terminalhire link` to connect this terminal to your account, then re-run.\n");
|
|
9609
9655
|
deps.exit(0);
|
|
9610
9656
|
return;
|
|
9611
9657
|
}
|
|
@@ -9648,9 +9694,8 @@ async function runIntroDecision(args5, overrides) {
|
|
|
9648
9694
|
return;
|
|
9649
9695
|
}
|
|
9650
9696
|
if (res.status === 401) {
|
|
9651
|
-
deps.log("\n Your web session expired
|
|
9652
|
-
deps.log(
|
|
9653
|
-
`);
|
|
9697
|
+
deps.log("\n Your linked web session expired.");
|
|
9698
|
+
deps.log(" Run `terminalhire link` to reconnect this terminal, then re-run.\n");
|
|
9654
9699
|
deps.exit(1);
|
|
9655
9700
|
return;
|
|
9656
9701
|
}
|
|
@@ -9689,10 +9734,7 @@ async function runIntroList(overrides) {
|
|
|
9689
9734
|
const cookie = deps.sessionCookie();
|
|
9690
9735
|
if (!cookie) {
|
|
9691
9736
|
deps.log("\n No linked web session found on this machine.");
|
|
9692
|
-
deps.log("
|
|
9693
|
-
deps.log(` \u2192 ${LINK_BASE2}/dashboard
|
|
9694
|
-
`);
|
|
9695
|
-
deps.openBrowser(`${LINK_BASE2}/dashboard`);
|
|
9737
|
+
deps.log(" Run `terminalhire link` to connect this terminal to your account, then re-run.\n");
|
|
9696
9738
|
deps.exit(0);
|
|
9697
9739
|
return;
|
|
9698
9740
|
}
|
|
@@ -9711,9 +9753,8 @@ async function runIntroList(overrides) {
|
|
|
9711
9753
|
return;
|
|
9712
9754
|
}
|
|
9713
9755
|
if (res.status === 401) {
|
|
9714
|
-
deps.log("\n Your web session expired
|
|
9715
|
-
deps.log(
|
|
9716
|
-
`);
|
|
9756
|
+
deps.log("\n Your linked web session expired.");
|
|
9757
|
+
deps.log(" Run `terminalhire link` to reconnect this terminal, then re-run.\n");
|
|
9717
9758
|
deps.exit(1);
|
|
9718
9759
|
return;
|
|
9719
9760
|
}
|
|
@@ -9751,6 +9792,7 @@ var init_intro2 = __esm({
|
|
|
9751
9792
|
"src/intro.ts"() {
|
|
9752
9793
|
"use strict";
|
|
9753
9794
|
init_src();
|
|
9795
|
+
init_web_session();
|
|
9754
9796
|
LINK_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
9755
9797
|
GH_SESSION_COOKIE2 = "__jpi_gh_session";
|
|
9756
9798
|
}
|
|
@@ -9807,19 +9849,19 @@ var init_jpi_intro = __esm({
|
|
|
9807
9849
|
});
|
|
9808
9850
|
|
|
9809
9851
|
// src/chat-keystore.ts
|
|
9810
|
-
import { existsSync as
|
|
9811
|
-
import { homedir as
|
|
9812
|
-
import { join as
|
|
9852
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync11, rmSync as rmSync3 } from "fs";
|
|
9853
|
+
import { homedir as homedir12 } from "os";
|
|
9854
|
+
import { join as join13 } from "path";
|
|
9813
9855
|
async function loadOrCreateIdentity() {
|
|
9814
9856
|
const key = await loadKey();
|
|
9815
|
-
if (
|
|
9816
|
-
const blob2 = JSON.parse(
|
|
9857
|
+
if (existsSync9(IDENTITY_FILE)) {
|
|
9858
|
+
const blob2 = JSON.parse(readFileSync13(IDENTITY_FILE, "utf8"));
|
|
9817
9859
|
return JSON.parse(decrypt(blob2, key));
|
|
9818
9860
|
}
|
|
9819
9861
|
const keypair = generateIdentityKeypair();
|
|
9820
|
-
|
|
9862
|
+
mkdirSync11(TERMINALHIRE_DIR10, { recursive: true });
|
|
9821
9863
|
const blob = encrypt(JSON.stringify(keypair), key);
|
|
9822
|
-
|
|
9864
|
+
writeFileSync11(IDENTITY_FILE, JSON.stringify(blob, null, 2), { mode: 384, encoding: "utf8" });
|
|
9823
9865
|
return keypair;
|
|
9824
9866
|
}
|
|
9825
9867
|
var TERMINALHIRE_DIR10, IDENTITY_FILE;
|
|
@@ -9828,19 +9870,19 @@ var init_chat_keystore = __esm({
|
|
|
9828
9870
|
"use strict";
|
|
9829
9871
|
init_src();
|
|
9830
9872
|
init_github_auth();
|
|
9831
|
-
TERMINALHIRE_DIR10 =
|
|
9832
|
-
IDENTITY_FILE =
|
|
9873
|
+
TERMINALHIRE_DIR10 = join13(homedir12(), ".terminalhire");
|
|
9874
|
+
IDENTITY_FILE = join13(TERMINALHIRE_DIR10, "chat-identity.enc");
|
|
9833
9875
|
}
|
|
9834
9876
|
});
|
|
9835
9877
|
|
|
9836
9878
|
// src/chat-client.ts
|
|
9837
|
-
import { existsSync as
|
|
9838
|
-
import { homedir as
|
|
9839
|
-
import { join as
|
|
9879
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
|
|
9880
|
+
import { homedir as homedir13 } from "os";
|
|
9881
|
+
import { join as join14 } from "path";
|
|
9840
9882
|
function defaultReadPeerPins() {
|
|
9841
9883
|
try {
|
|
9842
|
-
if (!
|
|
9843
|
-
const parsed = JSON.parse(
|
|
9884
|
+
if (!existsSync10(PEERS_FILE)) return {};
|
|
9885
|
+
const parsed = JSON.parse(readFileSync14(PEERS_FILE, "utf8"));
|
|
9844
9886
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
9845
9887
|
const out = {};
|
|
9846
9888
|
for (const [login, key] of Object.entries(parsed)) {
|
|
@@ -9852,16 +9894,15 @@ function defaultReadPeerPins() {
|
|
|
9852
9894
|
}
|
|
9853
9895
|
}
|
|
9854
9896
|
function defaultWritePeerPins(pins) {
|
|
9855
|
-
|
|
9856
|
-
|
|
9897
|
+
mkdirSync12(TERMINALHIRE_DIR11, { recursive: true });
|
|
9898
|
+
writeFileSync12(PEERS_FILE, JSON.stringify(pins, null, 2), { mode: 384, encoding: "utf8" });
|
|
9857
9899
|
}
|
|
9858
9900
|
function defaultChatClientDeps() {
|
|
9859
9901
|
return {
|
|
9860
9902
|
fetchImpl: (...args5) => globalThis.fetch(...args5),
|
|
9861
|
-
|
|
9862
|
-
|
|
9863
|
-
|
|
9864
|
-
},
|
|
9903
|
+
// Session source priority: persisted file (`terminalhire link`) FIRST, then the
|
|
9904
|
+
// legacy TERMINALHIRE_WEB_SESSION env, then none.
|
|
9905
|
+
sessionCookie: () => readWebSessionCookie(),
|
|
9865
9906
|
loadIdentity: () => loadOrCreateIdentity(),
|
|
9866
9907
|
readPeerPins: defaultReadPeerPins,
|
|
9867
9908
|
writePeerPins: defaultWritePeerPins
|
|
@@ -10014,15 +10055,16 @@ var init_chat_client = __esm({
|
|
|
10014
10055
|
"use strict";
|
|
10015
10056
|
init_src();
|
|
10016
10057
|
init_chat_keystore();
|
|
10058
|
+
init_web_session();
|
|
10017
10059
|
CHAT_BASE = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
10018
10060
|
GH_SESSION_COOKIE3 = "__jpi_gh_session";
|
|
10019
|
-
TERMINALHIRE_DIR11 =
|
|
10020
|
-
PEERS_FILE =
|
|
10061
|
+
TERMINALHIRE_DIR11 = join14(homedir13(), ".terminalhire");
|
|
10062
|
+
PEERS_FILE = join14(TERMINALHIRE_DIR11, "chat-peers.json");
|
|
10021
10063
|
REQUEST_TIMEOUT_MS = 1e4;
|
|
10022
10064
|
ChatNotLinkedError = class extends Error {
|
|
10023
10065
|
constructor() {
|
|
10024
10066
|
super(
|
|
10025
|
-
|
|
10067
|
+
"No linked web session found on this machine. Run `terminalhire link` to connect this terminal to your account, then re-run."
|
|
10026
10068
|
);
|
|
10027
10069
|
this.name = "ChatNotLinkedError";
|
|
10028
10070
|
}
|
|
@@ -10030,7 +10072,7 @@ var init_chat_client = __esm({
|
|
|
10030
10072
|
ChatSessionExpiredError = class extends Error {
|
|
10031
10073
|
constructor() {
|
|
10032
10074
|
super(
|
|
10033
|
-
|
|
10075
|
+
"Your linked web session expired. Run `terminalhire link` to reconnect this terminal, then re-run."
|
|
10034
10076
|
);
|
|
10035
10077
|
this.name = "ChatSessionExpiredError";
|
|
10036
10078
|
}
|
|
@@ -10071,13 +10113,13 @@ __export(jpi_chat_read_exports, {
|
|
|
10071
10113
|
runSend: () => runSend,
|
|
10072
10114
|
writeReadCursor: () => writeReadCursor
|
|
10073
10115
|
});
|
|
10074
|
-
import { existsSync as
|
|
10075
|
-
import { homedir as
|
|
10076
|
-
import { join as
|
|
10116
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync13, readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "fs";
|
|
10117
|
+
import { homedir as homedir14 } from "os";
|
|
10118
|
+
import { join as join15 } from "path";
|
|
10077
10119
|
function readReadCursors() {
|
|
10078
10120
|
try {
|
|
10079
|
-
if (!
|
|
10080
|
-
const parsed = JSON.parse(
|
|
10121
|
+
if (!existsSync11(READS_FILE)) return {};
|
|
10122
|
+
const parsed = JSON.parse(readFileSync15(READS_FILE, "utf8"));
|
|
10081
10123
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
10082
10124
|
const out = {};
|
|
10083
10125
|
for (const [login, iso] of Object.entries(parsed)) {
|
|
@@ -10092,8 +10134,8 @@ function writeReadCursor(login, iso, deps = {}) {
|
|
|
10092
10134
|
const read = deps.readReadCursors ?? readReadCursors;
|
|
10093
10135
|
const cursors = read();
|
|
10094
10136
|
cursors[login] = iso;
|
|
10095
|
-
|
|
10096
|
-
|
|
10137
|
+
mkdirSync13(TERMINALHIRE_DIR12, { recursive: true });
|
|
10138
|
+
writeFileSync13(READS_FILE, JSON.stringify(cursors, null, 2), { mode: 384, encoding: "utf8" });
|
|
10097
10139
|
}
|
|
10098
10140
|
function formatClock(iso) {
|
|
10099
10141
|
const d = new Date(iso);
|
|
@@ -10167,11 +10209,7 @@ function writeProblem(output, result, target) {
|
|
|
10167
10209
|
switch (result.status) {
|
|
10168
10210
|
case "not-linked":
|
|
10169
10211
|
output.write(
|
|
10170
|
-
`
|
|
10171
|
-
No linked web session found on this machine.
|
|
10172
|
-
Sign in at ${CHAT_BASE2}/dashboard, then re-run.
|
|
10173
|
-
|
|
10174
|
-
`
|
|
10212
|
+
"\n No linked web session found on this machine.\n Run `terminalhire link` to connect this terminal to your account, then re-run.\n\n"
|
|
10175
10213
|
);
|
|
10176
10214
|
return "not-linked";
|
|
10177
10215
|
case "expired":
|
|
@@ -10377,8 +10415,8 @@ var init_jpi_chat_read = __esm({
|
|
|
10377
10415
|
init_chat_client();
|
|
10378
10416
|
init_jpi_chat();
|
|
10379
10417
|
CHAT_BASE2 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
10380
|
-
TERMINALHIRE_DIR12 =
|
|
10381
|
-
READS_FILE =
|
|
10418
|
+
TERMINALHIRE_DIR12 = join15(homedir14(), ".terminalhire");
|
|
10419
|
+
READS_FILE = join15(TERMINALHIRE_DIR12, "chat-reads.json");
|
|
10382
10420
|
}
|
|
10383
10421
|
});
|
|
10384
10422
|
|
|
@@ -10442,8 +10480,7 @@ async function ensureChatDisclosure(opts = {}) {
|
|
|
10442
10480
|
return { shown: true, acknowledged: true };
|
|
10443
10481
|
}
|
|
10444
10482
|
function defaultSessionCookie() {
|
|
10445
|
-
|
|
10446
|
-
return typeof v === "string" && v.length > 0 ? v : null;
|
|
10483
|
+
return readWebSessionCookie();
|
|
10447
10484
|
}
|
|
10448
10485
|
async function fetchIntroList(deps = {}) {
|
|
10449
10486
|
const fetchImpl = deps.fetchImpl ?? ((...a) => globalThis.fetch(...a));
|
|
@@ -10542,11 +10579,7 @@ async function runChatPane(opts = {}) {
|
|
|
10542
10579
|
const resolved = await resolveConnection(target);
|
|
10543
10580
|
if (resolved.status === "not-linked") {
|
|
10544
10581
|
output.write(
|
|
10545
|
-
`
|
|
10546
|
-
No linked web session found on this machine.
|
|
10547
|
-
Sign in at ${CHAT_BASE3}/dashboard, then re-run.
|
|
10548
|
-
|
|
10549
|
-
`
|
|
10582
|
+
"\n No linked web session found on this machine.\n Run `terminalhire link` to connect this terminal to your account, then re-run.\n\n"
|
|
10550
10583
|
);
|
|
10551
10584
|
return { entered: false, reason: "not-linked" };
|
|
10552
10585
|
}
|
|
@@ -11006,6 +11039,7 @@ var init_jpi_chat = __esm({
|
|
|
11006
11039
|
"use strict";
|
|
11007
11040
|
init_chat_client();
|
|
11008
11041
|
init_config();
|
|
11042
|
+
init_web_session();
|
|
11009
11043
|
CHAT_BASE3 = process.env["TERMINALHIRE_API_URL"] || "https://www.terminalhire.com";
|
|
11010
11044
|
GH_SESSION_COOKIE4 = "__jpi_gh_session";
|
|
11011
11045
|
HIDE_CURSOR = "\x1B[?25l";
|
|
@@ -11030,10 +11064,210 @@ var init_jpi_chat = __esm({
|
|
|
11030
11064
|
}
|
|
11031
11065
|
});
|
|
11032
11066
|
|
|
11067
|
+
// src/link.ts
|
|
11068
|
+
var link_exports = {};
|
|
11069
|
+
__export(link_exports, {
|
|
11070
|
+
resolveLoopbackRequest: () => resolveLoopbackRequest,
|
|
11071
|
+
runLink: () => runLink,
|
|
11072
|
+
runLinkLogout: () => runLinkLogout
|
|
11073
|
+
});
|
|
11074
|
+
import { createServer } from "http";
|
|
11075
|
+
import { randomBytes as randomBytes5 } from "crypto";
|
|
11076
|
+
function resolveLoopbackRequest(rawUrl, expectedNonce) {
|
|
11077
|
+
let u;
|
|
11078
|
+
try {
|
|
11079
|
+
u = new URL(rawUrl, "http://127.0.0.1");
|
|
11080
|
+
} catch {
|
|
11081
|
+
return { ok: false, reason: "bad_url" };
|
|
11082
|
+
}
|
|
11083
|
+
const nonce = u.searchParams.get("nonce");
|
|
11084
|
+
if (!nonce || nonce !== expectedNonce) return { ok: false, reason: "nonce_mismatch" };
|
|
11085
|
+
const token = u.searchParams.get("token");
|
|
11086
|
+
if (!token) return { ok: false, reason: "missing_token" };
|
|
11087
|
+
return { ok: true, token };
|
|
11088
|
+
}
|
|
11089
|
+
function defaultStartLoopback(expectedNonce, timeoutMs) {
|
|
11090
|
+
return new Promise((resolveHandle) => {
|
|
11091
|
+
let settle;
|
|
11092
|
+
const result = new Promise((res) => {
|
|
11093
|
+
settle = res;
|
|
11094
|
+
});
|
|
11095
|
+
let done = false;
|
|
11096
|
+
const finish = (r) => {
|
|
11097
|
+
if (done) return;
|
|
11098
|
+
done = true;
|
|
11099
|
+
clearTimeout(timer);
|
|
11100
|
+
settle(r);
|
|
11101
|
+
setImmediate(() => {
|
|
11102
|
+
try {
|
|
11103
|
+
server.close();
|
|
11104
|
+
} catch {
|
|
11105
|
+
}
|
|
11106
|
+
});
|
|
11107
|
+
};
|
|
11108
|
+
const server = createServer((req, res) => {
|
|
11109
|
+
const outcome = resolveLoopbackRequest(req.url ?? "", expectedNonce);
|
|
11110
|
+
res.writeHead(outcome.ok ? 200 : 400, { "Content-Type": "text/html; charset=utf-8" });
|
|
11111
|
+
res.end(outcome.ok ? LINKED_HTML : FAILED_HTML);
|
|
11112
|
+
finish(outcome);
|
|
11113
|
+
});
|
|
11114
|
+
const timer = setTimeout(() => finish({ ok: false, reason: "timeout" }), timeoutMs);
|
|
11115
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
11116
|
+
server.on("error", () => finish({ ok: false, reason: "listen_error" }));
|
|
11117
|
+
server.listen(0, "127.0.0.1", () => {
|
|
11118
|
+
const addr = server.address();
|
|
11119
|
+
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
11120
|
+
resolveHandle({
|
|
11121
|
+
port,
|
|
11122
|
+
result,
|
|
11123
|
+
close: () => {
|
|
11124
|
+
try {
|
|
11125
|
+
server.close();
|
|
11126
|
+
} catch {
|
|
11127
|
+
}
|
|
11128
|
+
}
|
|
11129
|
+
});
|
|
11130
|
+
});
|
|
11131
|
+
});
|
|
11132
|
+
}
|
|
11133
|
+
function defaultLinkDeps() {
|
|
11134
|
+
return {
|
|
11135
|
+
startLoopback: defaultStartLoopback,
|
|
11136
|
+
openBrowser: (url) => {
|
|
11137
|
+
void Promise.resolve().then(() => (init_open_url(), open_url_exports)).then((m) => m.openInBrowser(url)).catch(() => {
|
|
11138
|
+
});
|
|
11139
|
+
},
|
|
11140
|
+
generateNonce: () => randomBytes5(16).toString("hex"),
|
|
11141
|
+
persistToken: (token) => writeWebSessionFile(token),
|
|
11142
|
+
log: (msg) => console.log(msg),
|
|
11143
|
+
errorLog: (msg) => console.error(msg),
|
|
11144
|
+
exit: (code) => process.exit(code)
|
|
11145
|
+
};
|
|
11146
|
+
}
|
|
11147
|
+
async function runLink(overrides) {
|
|
11148
|
+
const deps = { ...defaultLinkDeps(), ...overrides };
|
|
11149
|
+
const nonce = deps.generateNonce();
|
|
11150
|
+
const handle = await deps.startLoopback(nonce, LINK_TIMEOUT_MS);
|
|
11151
|
+
const url = `${LINK_BASE3}/api/auth/link?port=${handle.port}&nonce=${encodeURIComponent(nonce)}`;
|
|
11152
|
+
deps.log("");
|
|
11153
|
+
deps.log(" terminalhire \u2014 link this terminal to your account");
|
|
11154
|
+
deps.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
11155
|
+
deps.log(" Opening your browser to approve. If it does not open, paste this URL:");
|
|
11156
|
+
deps.log(` \u2192 ${url}`);
|
|
11157
|
+
deps.log(" Waiting for approval (this tab closes itself once you approve)\u2026");
|
|
11158
|
+
deps.openBrowser(url);
|
|
11159
|
+
let outcome;
|
|
11160
|
+
try {
|
|
11161
|
+
outcome = await handle.result;
|
|
11162
|
+
} finally {
|
|
11163
|
+
handle.close();
|
|
11164
|
+
}
|
|
11165
|
+
if (!outcome.ok || !outcome.token) {
|
|
11166
|
+
if (outcome.reason === "timeout") {
|
|
11167
|
+
deps.errorLog("\n Link timed out \u2014 run `terminalhire link` again.\n");
|
|
11168
|
+
} else if (outcome.reason === "nonce_mismatch") {
|
|
11169
|
+
deps.errorLog("\n Link rejected (nonce did not match) \u2014 run `terminalhire link` again.\n");
|
|
11170
|
+
} else {
|
|
11171
|
+
deps.errorLog("\n Link failed \u2014 run `terminalhire link` again.\n");
|
|
11172
|
+
}
|
|
11173
|
+
deps.exit(1);
|
|
11174
|
+
return;
|
|
11175
|
+
}
|
|
11176
|
+
deps.persistToken(outcome.token);
|
|
11177
|
+
deps.log("\n This terminal is now linked to your terminalhire account.");
|
|
11178
|
+
deps.log(" Try `terminalhire intro <login>`, `terminalhire chat`, or `terminalhire trajectory --push`.");
|
|
11179
|
+
deps.log(" Unlink any time with `terminalhire link --logout`.\n");
|
|
11180
|
+
deps.exit(0);
|
|
11181
|
+
}
|
|
11182
|
+
function defaultLinkLogoutDeps() {
|
|
11183
|
+
return {
|
|
11184
|
+
fetchImpl: (...args5) => globalThis.fetch(...args5),
|
|
11185
|
+
readSessionFile: () => readWebSessionFile(),
|
|
11186
|
+
clearSessionFile: () => clearWebSessionFile(),
|
|
11187
|
+
log: (msg) => console.log(msg),
|
|
11188
|
+
errorLog: (msg) => console.error(msg),
|
|
11189
|
+
exit: (code) => process.exit(code)
|
|
11190
|
+
};
|
|
11191
|
+
}
|
|
11192
|
+
async function runLinkLogout(overrides) {
|
|
11193
|
+
const deps = { ...defaultLinkLogoutDeps(), ...overrides };
|
|
11194
|
+
const token = deps.readSessionFile();
|
|
11195
|
+
if (!token) {
|
|
11196
|
+
deps.log("\n No linked web session on this machine \u2014 nothing to unlink.\n");
|
|
11197
|
+
deps.exit(0);
|
|
11198
|
+
return;
|
|
11199
|
+
}
|
|
11200
|
+
let revoked = false;
|
|
11201
|
+
try {
|
|
11202
|
+
const res = await deps.fetchImpl(`${LINK_BASE3}/api/auth/session`, {
|
|
11203
|
+
method: "DELETE",
|
|
11204
|
+
headers: { Cookie: `${GH_SESSION_COOKIE5}=${token}` },
|
|
11205
|
+
signal: AbortSignal.timeout(1e4)
|
|
11206
|
+
});
|
|
11207
|
+
revoked = res.ok;
|
|
11208
|
+
} catch {
|
|
11209
|
+
}
|
|
11210
|
+
deps.clearSessionFile();
|
|
11211
|
+
if (revoked) {
|
|
11212
|
+
deps.log("\n Unlinked \u2014 the session was revoked server-side and removed from this machine.\n");
|
|
11213
|
+
} else {
|
|
11214
|
+
deps.log("\n Removed the local session from this machine.");
|
|
11215
|
+
deps.log(" (Could not reach the server to revoke it \u2014 it expires on its own.)\n");
|
|
11216
|
+
}
|
|
11217
|
+
deps.exit(0);
|
|
11218
|
+
}
|
|
11219
|
+
var LINK_BASE3, GH_SESSION_COOKIE5, LINK_TIMEOUT_MS, LINKED_HTML, FAILED_HTML;
|
|
11220
|
+
var init_link = __esm({
|
|
11221
|
+
"src/link.ts"() {
|
|
11222
|
+
"use strict";
|
|
11223
|
+
init_web_session();
|
|
11224
|
+
LINK_BASE3 = "https://www.terminalhire.com";
|
|
11225
|
+
GH_SESSION_COOKIE5 = "__jpi_gh_session";
|
|
11226
|
+
LINK_TIMEOUT_MS = 12e4;
|
|
11227
|
+
LINKED_HTML = `<!doctype html><html><head><meta charset="utf-8"><title>terminalhire</title></head>
|
|
11228
|
+
<body style="font-family:system-ui;padding:2rem;background:#0b0d10;color:#e6e6e6">
|
|
11229
|
+
<script>history.replaceState({},'','/');</script>
|
|
11230
|
+
<p>CLI linked \u2014 you can close this tab.</p>
|
|
11231
|
+
<script>setTimeout(function(){window.close();},400);</script>
|
|
11232
|
+
</body></html>`;
|
|
11233
|
+
FAILED_HTML = `<!doctype html><html><head><meta charset="utf-8"><title>terminalhire</title></head>
|
|
11234
|
+
<body style="font-family:system-ui;padding:2rem;background:#0b0d10;color:#e6e6e6">
|
|
11235
|
+
<script>history.replaceState({},'','/');</script>
|
|
11236
|
+
<p>Link failed \u2014 return to your terminal and run <code>terminalhire link</code> again.</p>
|
|
11237
|
+
</body></html>`;
|
|
11238
|
+
}
|
|
11239
|
+
});
|
|
11240
|
+
|
|
11241
|
+
// bin/jpi-link.js
|
|
11242
|
+
var jpi_link_exports = {};
|
|
11243
|
+
__export(jpi_link_exports, {
|
|
11244
|
+
run: () => run10
|
|
11245
|
+
});
|
|
11246
|
+
async function run10() {
|
|
11247
|
+
try {
|
|
11248
|
+
const args5 = process.argv.slice(2);
|
|
11249
|
+
if (args5.includes("--logout")) {
|
|
11250
|
+
const { runLinkLogout: runLinkLogout2 } = await Promise.resolve().then(() => (init_link(), link_exports));
|
|
11251
|
+
await runLinkLogout2();
|
|
11252
|
+
return;
|
|
11253
|
+
}
|
|
11254
|
+
const { runLink: runLink2 } = await Promise.resolve().then(() => (init_link(), link_exports));
|
|
11255
|
+
await runLink2();
|
|
11256
|
+
} catch (err) {
|
|
11257
|
+
console.error("terminalhire link error:", err?.message ?? err);
|
|
11258
|
+
process.exit(1);
|
|
11259
|
+
}
|
|
11260
|
+
}
|
|
11261
|
+
var init_jpi_link = __esm({
|
|
11262
|
+
"bin/jpi-link.js"() {
|
|
11263
|
+
"use strict";
|
|
11264
|
+
}
|
|
11265
|
+
});
|
|
11266
|
+
|
|
11033
11267
|
// bin/jpi-profile.js
|
|
11034
11268
|
var jpi_profile_exports = {};
|
|
11035
11269
|
__export(jpi_profile_exports, {
|
|
11036
|
-
run: () =>
|
|
11270
|
+
run: () => run11
|
|
11037
11271
|
});
|
|
11038
11272
|
import { createInterface as createInterface8 } from "readline";
|
|
11039
11273
|
function prompt4(question) {
|
|
@@ -11045,7 +11279,7 @@ function prompt4(question) {
|
|
|
11045
11279
|
});
|
|
11046
11280
|
});
|
|
11047
11281
|
}
|
|
11048
|
-
async function
|
|
11282
|
+
async function run11() {
|
|
11049
11283
|
const { readProfile: readProfile2, writeProfile: writeProfile2, deleteProfile: deleteProfile2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
|
|
11050
11284
|
const args5 = process.argv.slice(2);
|
|
11051
11285
|
if (args5.includes("--show")) {
|
|
@@ -11118,9 +11352,9 @@ var signal_exports = {};
|
|
|
11118
11352
|
__export(signal_exports, {
|
|
11119
11353
|
extractFingerprint: () => extractFingerprint
|
|
11120
11354
|
});
|
|
11121
|
-
import { readFileSync as
|
|
11355
|
+
import { readFileSync as readFileSync16, readdirSync as readdirSync2 } from "fs";
|
|
11122
11356
|
import { execFileSync } from "child_process";
|
|
11123
|
-
import { join as
|
|
11357
|
+
import { join as join16 } from "path";
|
|
11124
11358
|
function safeGit(args5, cwd) {
|
|
11125
11359
|
try {
|
|
11126
11360
|
return execFileSync("git", ["-C", cwd, ...args5], {
|
|
@@ -11148,20 +11382,20 @@ function isEmployerContext(cwd) {
|
|
|
11148
11382
|
}
|
|
11149
11383
|
function readJsonSafe(path) {
|
|
11150
11384
|
try {
|
|
11151
|
-
return JSON.parse(
|
|
11385
|
+
return JSON.parse(readFileSync16(path, "utf8"));
|
|
11152
11386
|
} catch {
|
|
11153
11387
|
return null;
|
|
11154
11388
|
}
|
|
11155
11389
|
}
|
|
11156
11390
|
function readFileSafe(path) {
|
|
11157
11391
|
try {
|
|
11158
|
-
return
|
|
11392
|
+
return readFileSync16(path, "utf8");
|
|
11159
11393
|
} catch {
|
|
11160
11394
|
return "";
|
|
11161
11395
|
}
|
|
11162
11396
|
}
|
|
11163
11397
|
function tokensFromPackageJson(cwd) {
|
|
11164
|
-
const pkg = readJsonSafe(
|
|
11398
|
+
const pkg = readJsonSafe(join16(cwd, "package.json"));
|
|
11165
11399
|
if (!pkg || typeof pkg !== "object") return [];
|
|
11166
11400
|
const p = pkg;
|
|
11167
11401
|
const deps = {
|
|
@@ -11175,9 +11409,9 @@ function workspaceMemberDirs(cwd) {
|
|
|
11175
11409
|
const dirs = [cwd];
|
|
11176
11410
|
for (const group of ["apps", "packages"]) {
|
|
11177
11411
|
try {
|
|
11178
|
-
const groupDir =
|
|
11412
|
+
const groupDir = join16(cwd, group);
|
|
11179
11413
|
for (const e of readdirSync2(groupDir, { withFileTypes: true })) {
|
|
11180
|
-
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(
|
|
11414
|
+
if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join16(groupDir, e.name));
|
|
11181
11415
|
}
|
|
11182
11416
|
} catch {
|
|
11183
11417
|
}
|
|
@@ -11185,18 +11419,18 @@ function workspaceMemberDirs(cwd) {
|
|
|
11185
11419
|
return dirs;
|
|
11186
11420
|
}
|
|
11187
11421
|
function tokensFromRequirementsTxt(cwd) {
|
|
11188
|
-
const content = readFileSafe(
|
|
11422
|
+
const content = readFileSafe(join16(cwd, "requirements.txt"));
|
|
11189
11423
|
if (!content) return [];
|
|
11190
11424
|
return content.split("\n").map((l) => l.trim().split(/[>=<!\[;]/)[0].trim().toLowerCase()).filter(Boolean);
|
|
11191
11425
|
}
|
|
11192
11426
|
function tokensFromGoMod(cwd) {
|
|
11193
|
-
const content = readFileSafe(
|
|
11427
|
+
const content = readFileSafe(join16(cwd, "go.mod"));
|
|
11194
11428
|
if (!content) return [];
|
|
11195
11429
|
const requires = Array.from(content.matchAll(/^\s+([^\s]+)\s+v/gm)).map((m) => m[1].split("/").pop() ?? "").filter(Boolean);
|
|
11196
11430
|
return ["go", ...requires];
|
|
11197
11431
|
}
|
|
11198
11432
|
function tokensFromCargoToml(cwd) {
|
|
11199
|
-
const content = readFileSafe(
|
|
11433
|
+
const content = readFileSafe(join16(cwd, "Cargo.toml"));
|
|
11200
11434
|
if (!content) return [];
|
|
11201
11435
|
const deps = [];
|
|
11202
11436
|
let inDeps = false;
|
|
@@ -11217,7 +11451,7 @@ function tokensFromFileExtensions(cwd) {
|
|
|
11217
11451
|
const tokens = [];
|
|
11218
11452
|
const scanDirs = [cwd];
|
|
11219
11453
|
try {
|
|
11220
|
-
const srcDir =
|
|
11454
|
+
const srcDir = join16(cwd, "src");
|
|
11221
11455
|
readdirSync2(srcDir);
|
|
11222
11456
|
scanDirs.push(srcDir);
|
|
11223
11457
|
} catch {
|
|
@@ -11378,9 +11612,9 @@ var init_signal = __esm({
|
|
|
11378
11612
|
// bin/jpi-learn.js
|
|
11379
11613
|
var jpi_learn_exports = {};
|
|
11380
11614
|
__export(jpi_learn_exports, {
|
|
11381
|
-
run: () =>
|
|
11615
|
+
run: () => run12
|
|
11382
11616
|
});
|
|
11383
|
-
async function
|
|
11617
|
+
async function run12() {
|
|
11384
11618
|
try {
|
|
11385
11619
|
const args5 = process.argv.slice(2);
|
|
11386
11620
|
const cwdIdx = args5.indexOf("--cwd");
|
|
@@ -11407,7 +11641,7 @@ var init_jpi_learn = __esm({
|
|
|
11407
11641
|
"use strict";
|
|
11408
11642
|
isMain = process.argv[1]?.endsWith("jpi-learn.js") || process.argv[1]?.endsWith("jpi-learn");
|
|
11409
11643
|
if (isMain) {
|
|
11410
|
-
|
|
11644
|
+
run12();
|
|
11411
11645
|
}
|
|
11412
11646
|
}
|
|
11413
11647
|
});
|
|
@@ -11415,17 +11649,17 @@ var init_jpi_learn = __esm({
|
|
|
11415
11649
|
// bin/jpi-config.js
|
|
11416
11650
|
var jpi_config_exports = {};
|
|
11417
11651
|
__export(jpi_config_exports, {
|
|
11418
|
-
run: () =>
|
|
11652
|
+
run: () => run13
|
|
11419
11653
|
});
|
|
11420
|
-
import { join as
|
|
11421
|
-
import { homedir as
|
|
11654
|
+
import { join as join17 } from "path";
|
|
11655
|
+
import { homedir as homedir15 } from "os";
|
|
11422
11656
|
function parseNudgeMode(raw) {
|
|
11423
11657
|
if (raw === "session" || raw === "always") return raw;
|
|
11424
11658
|
const m = /^every:(\d+)$/.exec(raw);
|
|
11425
11659
|
if (m && parseInt(m[1], 10) >= 1) return raw;
|
|
11426
11660
|
return null;
|
|
11427
11661
|
}
|
|
11428
|
-
async function
|
|
11662
|
+
async function run13() {
|
|
11429
11663
|
const args5 = process.argv.slice(2);
|
|
11430
11664
|
const filtered = args5[0] === "config" ? args5.slice(1) : args5;
|
|
11431
11665
|
if (filtered.includes("--show") || filtered.length === 0) {
|
|
@@ -11491,8 +11725,8 @@ var init_jpi_config = __esm({
|
|
|
11491
11725
|
"bin/jpi-config.js"() {
|
|
11492
11726
|
"use strict";
|
|
11493
11727
|
init_config();
|
|
11494
|
-
TERMINALHIRE_DIR13 =
|
|
11495
|
-
CONFIG_FILE2 =
|
|
11728
|
+
TERMINALHIRE_DIR13 = join17(homedir15(), ".terminalhire");
|
|
11729
|
+
CONFIG_FILE2 = join17(TERMINALHIRE_DIR13, "config.json");
|
|
11496
11730
|
}
|
|
11497
11731
|
});
|
|
11498
11732
|
|
|
@@ -11515,25 +11749,25 @@ __export(spinner_exports, {
|
|
|
11515
11749
|
readSpinnerConfig: () => readSpinnerConfig
|
|
11516
11750
|
});
|
|
11517
11751
|
import {
|
|
11518
|
-
readFileSync as
|
|
11519
|
-
writeFileSync as
|
|
11520
|
-
existsSync as
|
|
11521
|
-
mkdirSync as
|
|
11752
|
+
readFileSync as readFileSync17,
|
|
11753
|
+
writeFileSync as writeFileSync14,
|
|
11754
|
+
existsSync as existsSync12,
|
|
11755
|
+
mkdirSync as mkdirSync14,
|
|
11522
11756
|
renameSync as renameSync2
|
|
11523
11757
|
} from "fs";
|
|
11524
|
-
import { join as
|
|
11525
|
-
import { homedir as
|
|
11758
|
+
import { join as join18, dirname } from "path";
|
|
11759
|
+
import { homedir as homedir16 } from "os";
|
|
11526
11760
|
function readJson(path, fallback) {
|
|
11527
11761
|
try {
|
|
11528
|
-
return
|
|
11762
|
+
return existsSync12(path) ? JSON.parse(readFileSync17(path, "utf8")) : fallback;
|
|
11529
11763
|
} catch {
|
|
11530
11764
|
return fallback;
|
|
11531
11765
|
}
|
|
11532
11766
|
}
|
|
11533
11767
|
function atomicWriteJson(path, obj) {
|
|
11534
|
-
|
|
11768
|
+
mkdirSync14(dirname(path), { recursive: true });
|
|
11535
11769
|
const tmp = `${path}.tmp-${process.pid}`;
|
|
11536
|
-
|
|
11770
|
+
writeFileSync14(tmp, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
11537
11771
|
renameSync2(tmp, path);
|
|
11538
11772
|
}
|
|
11539
11773
|
function titleCase(s) {
|
|
@@ -11793,10 +12027,10 @@ var TH_DIR, CLAUDE_SETTINGS, CONFIG_FILE3, SPINNER_STATE_FILE, SPINNER_DEFAULTS,
|
|
|
11793
12027
|
var init_spinner = __esm({
|
|
11794
12028
|
"bin/spinner.js"() {
|
|
11795
12029
|
"use strict";
|
|
11796
|
-
TH_DIR = process.env["TERMINALHIRE_DIR"] ||
|
|
11797
|
-
CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
11798
|
-
CONFIG_FILE3 =
|
|
11799
|
-
SPINNER_STATE_FILE =
|
|
12030
|
+
TH_DIR = process.env["TERMINALHIRE_DIR"] || join18(homedir16(), ".terminalhire");
|
|
12031
|
+
CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join18(homedir16(), ".claude", "settings.json");
|
|
12032
|
+
CONFIG_FILE3 = join18(TH_DIR, "config.json");
|
|
12033
|
+
SPINNER_STATE_FILE = join18(TH_DIR, "spinner-state.json");
|
|
11800
12034
|
SPINNER_DEFAULTS = { enabled: false, mode: "append", max: 6, frequency: "sometimes" };
|
|
11801
12035
|
VERB_INTROS = ["Matched:", "You\u2019d fit:", "Worth a look:", "On your radar:", "Fits your stack:"];
|
|
11802
12036
|
}
|
|
@@ -11805,32 +12039,32 @@ var init_spinner = __esm({
|
|
|
11805
12039
|
// bin/jpi-spinner.js
|
|
11806
12040
|
var jpi_spinner_exports = {};
|
|
11807
12041
|
__export(jpi_spinner_exports, {
|
|
11808
|
-
run: () =>
|
|
12042
|
+
run: () => run14
|
|
11809
12043
|
});
|
|
11810
12044
|
import {
|
|
11811
|
-
readFileSync as
|
|
11812
|
-
writeFileSync as
|
|
12045
|
+
readFileSync as readFileSync18,
|
|
12046
|
+
writeFileSync as writeFileSync15,
|
|
11813
12047
|
copyFileSync,
|
|
11814
|
-
existsSync as
|
|
11815
|
-
mkdirSync as
|
|
12048
|
+
existsSync as existsSync13,
|
|
12049
|
+
mkdirSync as mkdirSync15
|
|
11816
12050
|
} from "fs";
|
|
11817
|
-
import { join as
|
|
11818
|
-
import { homedir as
|
|
12051
|
+
import { join as join19 } from "path";
|
|
12052
|
+
import { homedir as homedir17 } from "os";
|
|
11819
12053
|
import { createInterface as createInterface9 } from "readline";
|
|
11820
12054
|
function readConfig2() {
|
|
11821
12055
|
try {
|
|
11822
|
-
return
|
|
12056
|
+
return existsSync13(CONFIG_FILE4) ? JSON.parse(readFileSync18(CONFIG_FILE4, "utf8")) : {};
|
|
11823
12057
|
} catch {
|
|
11824
12058
|
return {};
|
|
11825
12059
|
}
|
|
11826
12060
|
}
|
|
11827
12061
|
function writeConfig2(patch) {
|
|
11828
|
-
|
|
12062
|
+
mkdirSync15(TH_DIR2, { recursive: true });
|
|
11829
12063
|
const merged = { ...readConfig2(), ...patch };
|
|
11830
|
-
|
|
12064
|
+
writeFileSync15(CONFIG_FILE4, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
11831
12065
|
}
|
|
11832
12066
|
function backupSettings() {
|
|
11833
|
-
if (!
|
|
12067
|
+
if (!existsSync13(SETTINGS_PATH)) return null;
|
|
11834
12068
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
11835
12069
|
const backupPath = `${SETTINGS_PATH}.terminalhire-backup-${ts}`;
|
|
11836
12070
|
copyFileSync(SETTINGS_PATH, backupPath);
|
|
@@ -11847,13 +12081,13 @@ function ask(question) {
|
|
|
11847
12081
|
}
|
|
11848
12082
|
function readTopMatches() {
|
|
11849
12083
|
try {
|
|
11850
|
-
const c = JSON.parse(
|
|
12084
|
+
const c = JSON.parse(readFileSync18(CACHE_FILE, "utf8"));
|
|
11851
12085
|
return Array.isArray(c.topMatches) ? c.topMatches : [];
|
|
11852
12086
|
} catch {
|
|
11853
12087
|
return [];
|
|
11854
12088
|
}
|
|
11855
12089
|
}
|
|
11856
|
-
async function
|
|
12090
|
+
async function run14() {
|
|
11857
12091
|
const args5 = process.argv.slice(2).filter((a) => a !== "spinner");
|
|
11858
12092
|
const has = (f) => args5.includes(f);
|
|
11859
12093
|
const val = (f) => {
|
|
@@ -11990,21 +12224,21 @@ var init_jpi_spinner = __esm({
|
|
|
11990
12224
|
"bin/jpi-spinner.js"() {
|
|
11991
12225
|
"use strict";
|
|
11992
12226
|
init_spinner();
|
|
11993
|
-
TH_DIR2 = process.env["TERMINALHIRE_DIR"] ||
|
|
11994
|
-
CONFIG_FILE4 =
|
|
11995
|
-
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] ||
|
|
11996
|
-
CACHE_FILE =
|
|
12227
|
+
TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join19(homedir17(), ".terminalhire");
|
|
12228
|
+
CONFIG_FILE4 = join19(TH_DIR2, "config.json");
|
|
12229
|
+
SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join19(homedir17(), ".claude", "settings.json");
|
|
12230
|
+
CACHE_FILE = join19(TH_DIR2, "index-cache.json");
|
|
11997
12231
|
}
|
|
11998
12232
|
});
|
|
11999
12233
|
|
|
12000
12234
|
// bin/jpi-sync.js
|
|
12001
12235
|
var jpi_sync_exports = {};
|
|
12002
12236
|
__export(jpi_sync_exports, {
|
|
12003
|
-
run: () =>
|
|
12237
|
+
run: () => run15
|
|
12004
12238
|
});
|
|
12005
|
-
import { readFileSync as
|
|
12006
|
-
import { join as
|
|
12007
|
-
import { homedir as
|
|
12239
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync16, mkdirSync as mkdirSync16, existsSync as existsSync14, rmSync as rmSync4 } from "fs";
|
|
12240
|
+
import { join as join20 } from "path";
|
|
12241
|
+
import { homedir as homedir18, hostname as osHostname } from "os";
|
|
12008
12242
|
import { createInterface as createInterface10 } from "readline";
|
|
12009
12243
|
function ask2(question) {
|
|
12010
12244
|
const rl = createInterface10({ input: process.stdin, output: process.stdout });
|
|
@@ -12017,18 +12251,18 @@ function ask2(question) {
|
|
|
12017
12251
|
}
|
|
12018
12252
|
function readMarker() {
|
|
12019
12253
|
try {
|
|
12020
|
-
return
|
|
12254
|
+
return existsSync14(TIER1_MARKER) ? JSON.parse(readFileSync19(TIER1_MARKER, "utf8")) : null;
|
|
12021
12255
|
} catch {
|
|
12022
12256
|
return null;
|
|
12023
12257
|
}
|
|
12024
12258
|
}
|
|
12025
12259
|
function writeMarker(marker) {
|
|
12026
|
-
|
|
12027
|
-
|
|
12260
|
+
mkdirSync16(TH_DIR3, { recursive: true });
|
|
12261
|
+
writeFileSync16(TIER1_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
12028
12262
|
}
|
|
12029
12263
|
function clearMarker() {
|
|
12030
12264
|
try {
|
|
12031
|
-
|
|
12265
|
+
rmSync4(TIER1_MARKER);
|
|
12032
12266
|
} catch {
|
|
12033
12267
|
}
|
|
12034
12268
|
}
|
|
@@ -12312,7 +12546,7 @@ async function runDelete() {
|
|
|
12312
12546
|
clearMarker();
|
|
12313
12547
|
console.log("\n Synced profile deleted and local marker cleared.\n");
|
|
12314
12548
|
}
|
|
12315
|
-
async function
|
|
12549
|
+
async function run15() {
|
|
12316
12550
|
const args5 = process.argv.slice(2).filter((a) => a !== "sync");
|
|
12317
12551
|
const has = (f) => args5.includes(f);
|
|
12318
12552
|
if (has("--push") || has("--enable")) {
|
|
@@ -12343,8 +12577,8 @@ var init_jpi_sync = __esm({
|
|
|
12343
12577
|
"bin/jpi-sync.js"() {
|
|
12344
12578
|
"use strict";
|
|
12345
12579
|
init_open_url();
|
|
12346
|
-
TH_DIR3 = process.env["TERMINALHIRE_DIR"] ||
|
|
12347
|
-
TIER1_MARKER =
|
|
12580
|
+
TH_DIR3 = process.env["TERMINALHIRE_DIR"] || join20(homedir18(), ".terminalhire");
|
|
12581
|
+
TIER1_MARKER = join20(TH_DIR3, "tier1.json");
|
|
12348
12582
|
API_URL5 = process.env["TERMINALHIRE_API_URL"] || process.env["JPI_API_URL"] || "https://terminalhire.com";
|
|
12349
12583
|
SYNC_BASE = "https://www.terminalhire.com";
|
|
12350
12584
|
POLL_INTERVAL_MS = 2e3;
|
|
@@ -12356,14 +12590,14 @@ var init_jpi_sync = __esm({
|
|
|
12356
12590
|
// bin/jpi-init.js
|
|
12357
12591
|
var jpi_init_exports = {};
|
|
12358
12592
|
__export(jpi_init_exports, {
|
|
12359
|
-
run: () =>
|
|
12593
|
+
run: () => run16
|
|
12360
12594
|
});
|
|
12361
|
-
import { existsSync as
|
|
12362
|
-
import { join as
|
|
12595
|
+
import { existsSync as existsSync15 } from "fs";
|
|
12596
|
+
import { join as join21, resolve } from "path";
|
|
12363
12597
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
12364
12598
|
import { createInterface as createInterface11 } from "readline";
|
|
12365
12599
|
import { spawnSync, spawn as spawn2 } from "child_process";
|
|
12366
|
-
import { homedir as
|
|
12600
|
+
import { homedir as homedir19 } from "os";
|
|
12367
12601
|
function ask3(question) {
|
|
12368
12602
|
const rl = createInterface11({ input: process.stdin, output: process.stdout });
|
|
12369
12603
|
return new Promise((resolve2) => {
|
|
@@ -12374,18 +12608,18 @@ function ask3(question) {
|
|
|
12374
12608
|
});
|
|
12375
12609
|
}
|
|
12376
12610
|
function resolveScript(name) {
|
|
12377
|
-
const distPath = resolve(
|
|
12378
|
-
const legacyPath = resolve(
|
|
12379
|
-
return
|
|
12611
|
+
const distPath = resolve(join21(__dirname2, "..", "..", "dist", "bin", `${name}.js`));
|
|
12612
|
+
const legacyPath = resolve(join21(__dirname2, `${name}.js`));
|
|
12613
|
+
return existsSync15(distPath) ? distPath : legacyPath;
|
|
12380
12614
|
}
|
|
12381
12615
|
function resolveInstallJs() {
|
|
12382
|
-
const fromDist = resolve(
|
|
12383
|
-
const fromBin = resolve(
|
|
12384
|
-
if (
|
|
12385
|
-
if (
|
|
12616
|
+
const fromDist = resolve(join21(__dirname2, "..", "..", "install.js"));
|
|
12617
|
+
const fromBin = resolve(join21(__dirname2, "..", "install.js"));
|
|
12618
|
+
if (existsSync15(fromDist)) return fromDist;
|
|
12619
|
+
if (existsSync15(fromBin)) return fromBin;
|
|
12386
12620
|
return fromBin;
|
|
12387
12621
|
}
|
|
12388
|
-
async function
|
|
12622
|
+
async function run16() {
|
|
12389
12623
|
console.log("");
|
|
12390
12624
|
console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
12391
12625
|
console.log("\u2502 terminalhire init \u2014 one-command onboarding \u2502");
|
|
@@ -12488,13 +12722,13 @@ var init_jpi_init = __esm({
|
|
|
12488
12722
|
// bin/jpi-refresh.js
|
|
12489
12723
|
var jpi_refresh_exports = {};
|
|
12490
12724
|
__export(jpi_refresh_exports, {
|
|
12491
|
-
run: () =>
|
|
12725
|
+
run: () => run17
|
|
12492
12726
|
});
|
|
12493
|
-
import { readFileSync as
|
|
12494
|
-
import { join as
|
|
12495
|
-
import { homedir as
|
|
12727
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync17, existsSync as existsSync16, mkdirSync as mkdirSync17 } from "fs";
|
|
12728
|
+
import { join as join22 } from "path";
|
|
12729
|
+
import { homedir as homedir20 } from "os";
|
|
12496
12730
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12497
|
-
async function
|
|
12731
|
+
async function run17() {
|
|
12498
12732
|
try {
|
|
12499
12733
|
let index;
|
|
12500
12734
|
try {
|
|
@@ -12584,7 +12818,7 @@ async function run16() {
|
|
|
12584
12818
|
}
|
|
12585
12819
|
} catch {
|
|
12586
12820
|
}
|
|
12587
|
-
|
|
12821
|
+
mkdirSync17(TERMINALHIRE_DIR14, { recursive: true });
|
|
12588
12822
|
const cacheEntry = {
|
|
12589
12823
|
ts: Date.now(),
|
|
12590
12824
|
index,
|
|
@@ -12592,7 +12826,7 @@ async function run16() {
|
|
|
12592
12826
|
topMatches,
|
|
12593
12827
|
topPeers
|
|
12594
12828
|
};
|
|
12595
|
-
|
|
12829
|
+
writeFileSync17(INDEX_CACHE_FILE4, JSON.stringify(cacheEntry), "utf8");
|
|
12596
12830
|
try {
|
|
12597
12831
|
const {
|
|
12598
12832
|
readSpinnerConfig: readSpinnerConfig2,
|
|
@@ -12643,8 +12877,8 @@ var init_jpi_refresh = __esm({
|
|
|
12643
12877
|
init_directory2();
|
|
12644
12878
|
init_config();
|
|
12645
12879
|
__dirname3 = fileURLToPath4(new URL(".", import.meta.url));
|
|
12646
|
-
TERMINALHIRE_DIR14 =
|
|
12647
|
-
INDEX_CACHE_FILE4 =
|
|
12880
|
+
TERMINALHIRE_DIR14 = join22(homedir20(), ".terminalhire");
|
|
12881
|
+
INDEX_CACHE_FILE4 = join22(TERMINALHIRE_DIR14, "index-cache.json");
|
|
12648
12882
|
API_URL6 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
|
|
12649
12883
|
}
|
|
12650
12884
|
});
|
|
@@ -12652,16 +12886,16 @@ var init_jpi_refresh = __esm({
|
|
|
12652
12886
|
// bin/jpi-save.js
|
|
12653
12887
|
var jpi_save_exports = {};
|
|
12654
12888
|
__export(jpi_save_exports, {
|
|
12655
|
-
run: () =>
|
|
12889
|
+
run: () => run18
|
|
12656
12890
|
});
|
|
12657
|
-
import { readFileSync as
|
|
12658
|
-
import { join as
|
|
12659
|
-
import { homedir as
|
|
12891
|
+
import { readFileSync as readFileSync21, existsSync as existsSync17 } from "fs";
|
|
12892
|
+
import { join as join23 } from "path";
|
|
12893
|
+
import { homedir as homedir21 } from "os";
|
|
12660
12894
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
12661
12895
|
function findJobInCache(jobId) {
|
|
12662
12896
|
try {
|
|
12663
|
-
if (!
|
|
12664
|
-
const raw =
|
|
12897
|
+
if (!existsSync17(INDEX_CACHE_FILE5)) return null;
|
|
12898
|
+
const raw = readFileSync21(INDEX_CACHE_FILE5, "utf8");
|
|
12665
12899
|
const entry = JSON.parse(raw);
|
|
12666
12900
|
const jobs = entry?.index?.jobs ?? [];
|
|
12667
12901
|
return jobs.find((j) => j.id === jobId) ?? null;
|
|
@@ -12730,7 +12964,7 @@ async function cmdUnsave(jobId) {
|
|
|
12730
12964
|
process.exit(1);
|
|
12731
12965
|
}
|
|
12732
12966
|
}
|
|
12733
|
-
async function
|
|
12967
|
+
async function run18() {
|
|
12734
12968
|
const verb = process.argv[2];
|
|
12735
12969
|
const jobId = process.argv[3];
|
|
12736
12970
|
try {
|
|
@@ -12754,26 +12988,26 @@ var init_jpi_save = __esm({
|
|
|
12754
12988
|
"bin/jpi-save.js"() {
|
|
12755
12989
|
"use strict";
|
|
12756
12990
|
__dirname4 = fileURLToPath5(new URL(".", import.meta.url));
|
|
12757
|
-
TERMINALHIRE_DIR15 =
|
|
12758
|
-
INDEX_CACHE_FILE5 =
|
|
12991
|
+
TERMINALHIRE_DIR15 = join23(homedir21(), ".terminalhire");
|
|
12992
|
+
INDEX_CACHE_FILE5 = join23(TERMINALHIRE_DIR15, "index-cache.json");
|
|
12759
12993
|
}
|
|
12760
12994
|
});
|
|
12761
12995
|
|
|
12762
12996
|
// bin/jpi-dispatch.js
|
|
12763
12997
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
12764
|
-
import { join as
|
|
12765
|
-
import { existsSync as
|
|
12998
|
+
import { join as join24, dirname as dirname2 } from "path";
|
|
12999
|
+
import { existsSync as existsSync18, readFileSync as readFileSync22 } from "fs";
|
|
12766
13000
|
import { createRequire } from "module";
|
|
12767
13001
|
var __dirname5 = fileURLToPath6(new URL(".", import.meta.url));
|
|
12768
13002
|
function readPackageVersion() {
|
|
12769
13003
|
try {
|
|
12770
13004
|
const candidates = [
|
|
12771
|
-
|
|
12772
|
-
|
|
13005
|
+
join24(__dirname5, "..", "..", "package.json"),
|
|
13006
|
+
join24(__dirname5, "..", "package.json")
|
|
12773
13007
|
];
|
|
12774
13008
|
for (const p of candidates) {
|
|
12775
|
-
if (
|
|
12776
|
-
const pkg = JSON.parse(
|
|
13009
|
+
if (existsSync18(p)) {
|
|
13010
|
+
const pkg = JSON.parse(readFileSync22(p, "utf8"));
|
|
12777
13011
|
if (pkg.version) return pkg.version;
|
|
12778
13012
|
}
|
|
12779
13013
|
}
|
|
@@ -12784,7 +13018,7 @@ function readPackageVersion() {
|
|
|
12784
13018
|
var firstArg = process.argv[2];
|
|
12785
13019
|
if (!firstArg && !process.stdin.isTTY) {
|
|
12786
13020
|
const { default: childProcess } = await import("child_process");
|
|
12787
|
-
const nudgeScript =
|
|
13021
|
+
const nudgeScript = join24(__dirname5, "jpi.js");
|
|
12788
13022
|
const child = childProcess.spawnSync(process.execPath, [nudgeScript], {
|
|
12789
13023
|
stdio: ["inherit", "inherit", "inherit"]
|
|
12790
13024
|
});
|
|
@@ -12820,6 +13054,8 @@ if (!firstArg || firstArg === "help" || firstArg === "--help" || firstArg === "-
|
|
|
12820
13054
|
console.log(" terminalhire chat <github-login> --read Read a thread inline (last 8; -n N / --all for depth)");
|
|
12821
13055
|
console.log(' terminalhire chat <github-login> --send "\u2026" Send one line to a connection (E2E encrypted)');
|
|
12822
13056
|
console.log(" terminalhire chat <github-login> Open the live E2E chat pane with an accepted connection");
|
|
13057
|
+
console.log(" terminalhire link Connect this terminal to your terminalhire account");
|
|
13058
|
+
console.log(" terminalhire link --logout Revoke + remove this terminal's linked session");
|
|
12823
13059
|
console.log(" terminalhire profile --show Display your encrypted local profile");
|
|
12824
13060
|
console.log(" terminalhire profile --edit Set displayName, contactEmail, prefs");
|
|
12825
13061
|
console.log(" terminalhire profile --delete Wipe profile and encryption key from disk");
|
|
@@ -12909,6 +13145,12 @@ if (firstArg === "chat") {
|
|
|
12909
13145
|
await mod2.run();
|
|
12910
13146
|
process.exit(0);
|
|
12911
13147
|
}
|
|
13148
|
+
if (firstArg === "link") {
|
|
13149
|
+
process.argv.splice(2, 1);
|
|
13150
|
+
const mod2 = await Promise.resolve().then(() => (init_jpi_link(), jpi_link_exports));
|
|
13151
|
+
await mod2.run();
|
|
13152
|
+
process.exit(0);
|
|
13153
|
+
}
|
|
12912
13154
|
if (firstArg === "profile") {
|
|
12913
13155
|
const mod2 = await Promise.resolve().then(() => (init_jpi_profile(), jpi_profile_exports));
|
|
12914
13156
|
await mod2.run();
|