terminalhire 0.42.18 → 0.42.19

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 CHANGED
@@ -310,6 +310,13 @@ node test/zero-egress.test.js
310
310
  uses that one answer — so reads and writes can no longer disagree about which
311
311
  environment you are on.
312
312
 
313
+ The credential store follows that answer. Pointed at `dev.terminalhire.com` by any
314
+ spelling (`thdev`, the variable, an MCP server entry), the CLI reads and writes
315
+ `~/.terminalhire-dev` unless `TERMINALHIRE_DIR` names a store (`src/state-dir-pin.ts`,
316
+ called first thing in `bin/jpi-dispatch.js`, before any subcommand loads). Production and loopback keep
317
+ `~/.terminalhire`. Before this, only `thdev` switched stores, and every other
318
+ spelling presented the production session to dev.
319
+
313
320
  The override is an **allowlist**, not a free-form URL, because this same base decides
314
321
  where your push token is presented. Only these are accepted:
315
322
 
@@ -182,7 +182,7 @@ async function syncFounderVerdicts({
182
182
  const applied = [];
183
183
  for (const t of plan) {
184
184
  try {
185
- claimsModule.updateClaim(t.id, { state: t.to });
185
+ claimsModule.updateClaim(t.id, { state: t.to, posterVerdict: t.verdict });
186
186
  applied.push(t);
187
187
  const line = buildVerdictNotice(t);
188
188
  if (line) log(line);
@@ -10550,6 +10550,187 @@ var init_state_dir = __esm({
10550
10550
  }
10551
10551
  });
10552
10552
 
10553
+ // src/api-base.ts
10554
+ var api_base_exports = {};
10555
+ __export(api_base_exports, {
10556
+ ApiBaseError: () => ApiBaseError,
10557
+ DEV_API_BASE: () => DEV_API_BASE,
10558
+ DEV_STATE_DIR_NAME: () => DEV_STATE_DIR_NAME,
10559
+ PROD_API_BASE: () => PROD_API_BASE,
10560
+ __resetDevMarkerLatchForTests: () => __resetDevMarkerLatchForTests,
10561
+ formatDevMarker: () => formatDevMarker,
10562
+ isLoopbackOrigin: () => isLoopbackOrigin,
10563
+ isNonProdApiBase: () => isNonProdApiBase,
10564
+ pinToDevApiBase: () => pinToDevApiBase,
10565
+ printDevMarkerIfNeeded: () => printDevMarkerIfNeeded,
10566
+ resolveApiBase: () => resolveApiBase,
10567
+ resolveOAuthBase: () => resolveOAuthBase,
10568
+ warnSharedCredentialsIfNonProd: () => warnSharedCredentialsIfNonProd
10569
+ });
10570
+ import { homedir as homedir2 } from "os";
10571
+ import { join as join3 } from "path";
10572
+ function sanitizeOverrideForError(raw) {
10573
+ try {
10574
+ const url = new URL(raw);
10575
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
10576
+ return `(disallowed scheme: ${url.protocol.slice(0, -1)})`;
10577
+ }
10578
+ if (url.username !== "" || url.password !== "") {
10579
+ return `${url.protocol}//***@${url.host}`;
10580
+ }
10581
+ return url.origin;
10582
+ } catch {
10583
+ return "(unparseable override)";
10584
+ }
10585
+ }
10586
+ function isLoopbackOrigin(origin) {
10587
+ try {
10588
+ const host = new URL(origin).hostname;
10589
+ return host === "localhost" || host === "127.0.0.1";
10590
+ } catch {
10591
+ return false;
10592
+ }
10593
+ }
10594
+ function localApiAllowed(env) {
10595
+ return env[ALLOW_LOCAL_API_KEY] === "1";
10596
+ }
10597
+ function pinToDevApiBase(env = process.env) {
10598
+ env["TERMINALHIRE_API_URL"] = DEV_API_BASE;
10599
+ env["TERMINALHIRE_DIR"] = env["TERMINALHIRE_DIR"] || join3(homedir2(), DEV_STATE_DIR_NAME);
10600
+ return DEV_API_BASE;
10601
+ }
10602
+ function resolveApiBase(env = process.env) {
10603
+ for (const key of ENV_KEYS) {
10604
+ const raw = env[key];
10605
+ if (typeof raw !== "string") continue;
10606
+ const trimmed = raw.trim();
10607
+ if (trimmed === "") continue;
10608
+ const normalized = normalizeOverride(trimmed);
10609
+ if (normalized === null) {
10610
+ throw new ApiBaseError(
10611
+ `terminalhire: ${key}=${sanitizeOverrideForError(trimmed)} is not an allowed API host (allowed: ${ALLOWED_DESCRIPTION}). Refusing to continue so we do not silently hit production.`
10612
+ );
10613
+ }
10614
+ if (isLoopbackOrigin(normalized) && !localApiAllowed(env)) {
10615
+ throw new ApiBaseError(
10616
+ `terminalhire: ${key}=${normalized} is a loopback origin. Set ${ALLOW_LOCAL_API_KEY}=1 to talk to a local web app on purpose. Refusing so stored credentials cannot be exfiltrated to localhost by a poisoned override.`
10617
+ );
10618
+ }
10619
+ return normalized;
10620
+ }
10621
+ return PROD_API_BASE;
10622
+ }
10623
+ function resolveOAuthBase(env = process.env) {
10624
+ const base = resolveApiBase(env);
10625
+ if (OAUTH_ALLOWED_ORIGINS.includes(base)) return base;
10626
+ if (env[ALLOW_LOCAL_OAUTH_KEY] === "1") return base;
10627
+ throw new ApiBaseError(
10628
+ `terminalhire: the API base is ${base}, which is not a trusted origin for a browser sign-in. Point the CLI at ${DEV_API_BASE} for an end-to-end login, or set ${ALLOW_LOCAL_OAUTH_KEY}=1 (with ${ALLOW_LOCAL_API_KEY}=1) if you are running the web app locally on purpose. Refusing to open production sign-in while the API is local.`
10629
+ );
10630
+ }
10631
+ function resolveApiBaseOrProd(env = process.env) {
10632
+ try {
10633
+ return resolveApiBase(env);
10634
+ } catch {
10635
+ return PROD_API_BASE;
10636
+ }
10637
+ }
10638
+ function normalizeOverride(raw) {
10639
+ let url;
10640
+ try {
10641
+ url = new URL(raw);
10642
+ } catch {
10643
+ return null;
10644
+ }
10645
+ if (url.username !== "" || url.password !== "") return null;
10646
+ const expectedProtocol = ALLOWED_HOSTS[url.hostname];
10647
+ if (expectedProtocol === void 0) return null;
10648
+ if (url.protocol !== expectedProtocol) return null;
10649
+ if (url.hostname !== "localhost" && url.hostname !== "127.0.0.1" && url.port !== "") {
10650
+ return null;
10651
+ }
10652
+ const rewrite = CANONICAL_REWRITES[url.hostname];
10653
+ if (rewrite !== void 0) return rewrite;
10654
+ return url.origin;
10655
+ }
10656
+ function isNonProdApiBase(base = resolveApiBaseOrProd()) {
10657
+ return base !== PROD_API_BASE;
10658
+ }
10659
+ function formatDevMarker(base = resolveApiBaseOrProd()) {
10660
+ if (!isNonProdApiBase(base)) return null;
10661
+ let host = base;
10662
+ try {
10663
+ host = new URL(base).host;
10664
+ } catch {
10665
+ }
10666
+ return `[dev \u2192 ${host}]`;
10667
+ }
10668
+ function printDevMarkerIfNeeded(stream = process.stderr) {
10669
+ if (markerPrinted) return;
10670
+ const marker = formatDevMarker();
10671
+ if (marker === null) return;
10672
+ markerPrinted = true;
10673
+ try {
10674
+ stream.write(`${marker}
10675
+ `);
10676
+ } catch {
10677
+ }
10678
+ }
10679
+ function __resetDevMarkerLatchForTests() {
10680
+ markerPrinted = false;
10681
+ }
10682
+ function warnSharedCredentialsIfNonProd(base, stream = process.stderr) {
10683
+ if (!isNonProdApiBase(base)) return;
10684
+ if (usingSeparateStateDir()) return;
10685
+ try {
10686
+ stream.write(
10687
+ "terminalhire: non-prod API base \u2014 using the same local session/push credentials as prod; do not mix environments casually.\n"
10688
+ );
10689
+ } catch {
10690
+ }
10691
+ }
10692
+ function usingSeparateStateDir(env = process.env) {
10693
+ const dir = env["TERMINALHIRE_DIR"];
10694
+ if (dir === void 0 || dir === "") return false;
10695
+ return dir.endsWith(DEV_STATE_DIR_NAME);
10696
+ }
10697
+ var PROD_API_BASE, DEV_API_BASE, DEV_STATE_DIR_NAME, ApiBaseError, ALLOWED_HOSTS, OAUTH_ALLOWED_ORIGINS, ALLOW_LOCAL_OAUTH_KEY, ALLOW_LOCAL_API_KEY, ALLOWED_DESCRIPTION, CANONICAL_REWRITES, ENV_KEYS, markerPrinted;
10698
+ var init_api_base = __esm({
10699
+ "src/api-base.ts"() {
10700
+ "use strict";
10701
+ PROD_API_BASE = "https://terminalhire.com";
10702
+ DEV_API_BASE = "https://dev.terminalhire.com";
10703
+ DEV_STATE_DIR_NAME = ".terminalhire-dev";
10704
+ ApiBaseError = class extends Error {
10705
+ constructor(message) {
10706
+ super(message);
10707
+ this.name = "ApiBaseError";
10708
+ }
10709
+ };
10710
+ ALLOWED_HOSTS = {
10711
+ "terminalhire.com": "https:",
10712
+ "www.terminalhire.com": "https:",
10713
+ "dev.terminalhire.com": "https:",
10714
+ localhost: "http:",
10715
+ "127.0.0.1": "http:"
10716
+ };
10717
+ OAUTH_ALLOWED_ORIGINS = [PROD_API_BASE, DEV_API_BASE];
10718
+ ALLOW_LOCAL_OAUTH_KEY = "TERMINALHIRE_ALLOW_LOCAL_OAUTH";
10719
+ ALLOW_LOCAL_API_KEY = "TERMINALHIRE_ALLOW_LOCAL_API";
10720
+ ALLOWED_DESCRIPTION = [
10721
+ PROD_API_BASE,
10722
+ DEV_API_BASE,
10723
+ `http://localhost:<port> (requires ${ALLOW_LOCAL_API_KEY}=1)`,
10724
+ `http://127.0.0.1:<port> (requires ${ALLOW_LOCAL_API_KEY}=1)`
10725
+ ].join(", ");
10726
+ CANONICAL_REWRITES = {
10727
+ "www.terminalhire.com": PROD_API_BASE
10728
+ };
10729
+ ENV_KEYS = ["TERMINALHIRE_API_URL", "JPI_API_URL"];
10730
+ markerPrinted = false;
10731
+ }
10732
+ });
10733
+
10553
10734
  // bin/founder-pin.js
10554
10735
  function isPinnedFounderBounty(j) {
10555
10736
  return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
@@ -11785,12 +11966,16 @@ var init_founder_paid_badge = __esm({
11785
11966
  var web_session_exports = {};
11786
11967
  __export(web_session_exports, {
11787
11968
  clearWebSessionFile: () => clearWebSessionFile,
11969
+ hostLabel: () => hostLabel,
11970
+ missingSessionLines: () => missingSessionLines,
11788
11971
  readWebSessionCookie: () => readWebSessionCookie,
11789
11972
  readWebSessionFile: () => readWebSessionFile,
11790
11973
  readWebSessionRecord: () => readWebSessionRecord,
11974
+ refusedSessionLines: () => refusedSessionLines,
11791
11975
  webSessionCookieForHost: () => webSessionCookieForHost,
11792
11976
  webSessionFilePath: () => webSessionFilePath,
11793
11977
  webSessionForHost: () => webSessionForHost,
11978
+ withSessionDeps: () => withSessionDeps,
11794
11979
  writeWebSessionFile: () => writeWebSessionFile
11795
11980
  });
11796
11981
  import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
@@ -11830,6 +12015,7 @@ function readWebSessionFile() {
11830
12015
  return readWebSessionRecord()?.token ?? null;
11831
12016
  }
11832
12017
  function webSessionForHost(apiBase) {
12018
+ assertBase(apiBase, "webSessionForHost");
11833
12019
  const record = readWebSessionRecord();
11834
12020
  if (!record) return { cookie: null, mismatch: null };
11835
12021
  if (record.host !== null && record.host !== apiBase) {
@@ -11843,11 +12029,50 @@ function webSessionCookieForHost(apiBase) {
11843
12029
  const env = process.env["TERMINALHIRE_WEB_SESSION"];
11844
12030
  return { cookie: typeof env === "string" && env.length > 0 ? env : null, mismatch: null };
11845
12031
  }
11846
- function readWebSessionCookie() {
11847
- const fromFile = readWebSessionFile();
11848
- if (fromFile) return fromFile;
11849
- const env = process.env["TERMINALHIRE_WEB_SESSION"];
11850
- return typeof env === "string" && env.length > 0 ? env : null;
12032
+ function assertBase(apiBase, fn) {
12033
+ if (typeof apiBase !== "string" || apiBase.length === 0) {
12034
+ throw new TypeError(
12035
+ `${fn}(apiBase) requires the destination base as a non-empty string; received ${apiBase === "" ? "''" : String(apiBase)}. This is a wiring bug in the calling command, not a developer misconfiguration: pass the same resolveApiBase() value the request is sent to, so the session's host affinity can be checked (TERM-991).`
12036
+ );
12037
+ }
12038
+ }
12039
+ function hostLabel(base) {
12040
+ return String(base ?? "").replace(/^https?:\/\//, "");
12041
+ }
12042
+ function missingSessionLines(mismatch) {
12043
+ if (!mismatch) {
12044
+ return [
12045
+ "No linked web session found on this machine.",
12046
+ "Run `terminalhire link` to connect this terminal to your account, then re-run."
12047
+ ];
12048
+ }
12049
+ const linked = hostLabel(mismatch.linkedHost);
12050
+ const current = hostLabel(mismatch.currentHost);
12051
+ const reach = mismatch.linkedHost === PROD_API_BASE ? `unset TERMINALHIRE_API_URL to reach ${linked}` : isLoopbackOrigin(mismatch.linkedHost) ? `set TERMINALHIRE_ALLOW_LOCAL_API=1 TERMINALHIRE_API_URL=${mismatch.linkedHost} to reach ${linked}` : `set TERMINALHIRE_API_URL=${mismatch.linkedHost} to reach ${linked}`;
12052
+ const link = isLoopbackOrigin(mismatch.currentHost) ? "`TERMINALHIRE_ALLOW_LOCAL_OAUTH=1 terminalhire link`" : "`terminalhire link`";
12053
+ return [
12054
+ `This terminal is on ${current}, but your linked session belongs to ${linked}. Nothing was sent.`,
12055
+ `Either ${reach}, or run ${link} to link this terminal to ${current} instead.`
12056
+ ];
12057
+ }
12058
+ function withSessionDeps(defaults, overrides) {
12059
+ const merged = { ...defaults, ...overrides };
12060
+ if (overrides?.sessionCookie && !overrides.sessionMismatch) merged.sessionMismatch = () => null;
12061
+ return merged;
12062
+ }
12063
+ function refusedSessionLines(apiBase) {
12064
+ return [
12065
+ `${hostLabel(apiBase)} refused your linked session.`,
12066
+ "Run `terminalhire link` to link this terminal again, then re-run."
12067
+ ];
12068
+ }
12069
+ function readWebSessionCookie(apiBase) {
12070
+ if (typeof apiBase !== "string" || apiBase.length === 0) {
12071
+ throw new TypeError(
12072
+ `readWebSessionCookie(apiBase) requires the destination base as a non-empty string; received ${apiBase === "" ? "''" : String(apiBase)}. This is a wiring bug in the calling command, not a developer misconfiguration: pass the same resolveApiBase() value the request is sent to, so the session's host affinity can be checked (TERM-991).`
12073
+ );
12074
+ }
12075
+ return webSessionCookieForHost(apiBase).cookie;
11851
12076
  }
11852
12077
  function writeWebSessionFile(token, host) {
11853
12078
  ensureStateDirForSecret(terminalhireDir());
@@ -11868,6 +12093,7 @@ function clearWebSessionFile() {
11868
12093
  var init_web_session = __esm({
11869
12094
  "src/web-session.ts"() {
11870
12095
  "use strict";
12096
+ init_api_base();
11871
12097
  init_state_dir();
11872
12098
  }
11873
12099
  });
@@ -11976,15 +12202,27 @@ async function sendDecline(bountyId, reason) {
11976
12202
  console.error("Not one of the answers \u2014 nothing sent.");
11977
12203
  return false;
11978
12204
  }
11979
- const { readWebSessionCookie: readWebSessionCookie2 } = await Promise.resolve().then(() => (init_web_session(), web_session_exports));
11980
- const cookie = readWebSessionCookie2();
12205
+ let apiUrl;
12206
+ try {
12207
+ const { resolveApiBase: resolveApiBase2 } = await Promise.resolve().then(() => (init_api_base(), api_base_exports));
12208
+ apiUrl = resolveApiBase2();
12209
+ } catch (err) {
12210
+ console.log(`
12211
+ ${err instanceof Error ? err.message : String(err)}`);
12212
+ return false;
12213
+ }
12214
+ const { missingSessionLines: missingSessionLines2, webSessionCookieForHost: webSessionCookieForHost2 } = await Promise.resolve().then(() => (init_web_session(), web_session_exports));
12215
+ const { cookie, mismatch } = webSessionCookieForHost2(apiUrl);
11981
12216
  if (!cookie) {
11982
- console.log("\nRun `terminalhire link` first \u2014 a poster needs to know the answer is real.");
12217
+ if (mismatch) console.log(`
12218
+ ${missingSessionLines2(mismatch).join("\n")}`);
12219
+ else
12220
+ console.log("\nRun `terminalhire link` first \u2014 a poster needs to know the answer is real.");
11983
12221
  return false;
11984
12222
  }
11985
12223
  if (!await ensureDeclineConsent(bountyId, reason)) return false;
11986
12224
  try {
11987
- const res = await fetch(`${API_URL}/api/posting/decline`, {
12225
+ const res = await fetch(`${apiUrl}/api/posting/decline`, {
11988
12226
  method: "POST",
11989
12227
  headers: {
11990
12228
  "content-type": "application/json",
@@ -12013,11 +12251,10 @@ async function runDeclinePrompt(bountyId, { ask = prompt } = {}) {
12013
12251
  if (!reason) return false;
12014
12252
  return sendDecline(bountyId, reason);
12015
12253
  }
12016
- var API_URL, GH_SESSION_COOKIE, DECLINE_CHOICES;
12254
+ var GH_SESSION_COOKIE, DECLINE_CHOICES;
12017
12255
  var init_jpi_decline = __esm({
12018
12256
  "bin/jpi-decline.js"() {
12019
12257
  "use strict";
12020
- API_URL = process.env["TERMINALHIRE_API_URL"] || "https://terminalhire.com";
12021
12258
  GH_SESSION_COOKIE = "__jpi_gh_session";
12022
12259
  DECLINE_CHOICES = [
12023
12260
  { key: "1", reason: "price_low", label: "the price is too low for the work" },
@@ -12249,106 +12486,13 @@ function linkTitle(title, url) {
12249
12486
  return href ? `${safeTitle} (${href})` : safeTitle;
12250
12487
  }
12251
12488
 
12252
- // src/api-base.ts
12253
- import { homedir as homedir2 } from "os";
12254
- import { join as join3 } from "path";
12255
- var PROD_API_BASE = "https://terminalhire.com";
12256
- var DEV_API_BASE = "https://dev.terminalhire.com";
12257
- var ApiBaseError = class extends Error {
12258
- constructor(message) {
12259
- super(message);
12260
- this.name = "ApiBaseError";
12261
- }
12262
- };
12263
- var ALLOWED_HOSTS = {
12264
- "terminalhire.com": "https:",
12265
- "www.terminalhire.com": "https:",
12266
- "dev.terminalhire.com": "https:",
12267
- localhost: "http:",
12268
- "127.0.0.1": "http:"
12269
- };
12270
- var ALLOW_LOCAL_API_KEY = "TERMINALHIRE_ALLOW_LOCAL_API";
12271
- var ALLOWED_DESCRIPTION = [
12272
- PROD_API_BASE,
12273
- DEV_API_BASE,
12274
- `http://localhost:<port> (requires ${ALLOW_LOCAL_API_KEY}=1)`,
12275
- `http://127.0.0.1:<port> (requires ${ALLOW_LOCAL_API_KEY}=1)`
12276
- ].join(", ");
12277
- var CANONICAL_REWRITES = {
12278
- "www.terminalhire.com": PROD_API_BASE
12279
- };
12280
- var ENV_KEYS = ["TERMINALHIRE_API_URL", "JPI_API_URL"];
12281
- function sanitizeOverrideForError(raw) {
12282
- try {
12283
- const url = new URL(raw);
12284
- if (url.protocol !== "http:" && url.protocol !== "https:") {
12285
- return `(disallowed scheme: ${url.protocol.slice(0, -1)})`;
12286
- }
12287
- if (url.username !== "" || url.password !== "") {
12288
- return `${url.protocol}//***@${url.host}`;
12289
- }
12290
- return url.origin;
12291
- } catch {
12292
- return "(unparseable override)";
12293
- }
12294
- }
12295
- function isLoopbackOrigin(origin) {
12296
- try {
12297
- const host = new URL(origin).hostname;
12298
- return host === "localhost" || host === "127.0.0.1";
12299
- } catch {
12300
- return false;
12301
- }
12302
- }
12303
- function localApiAllowed(env) {
12304
- return env[ALLOW_LOCAL_API_KEY] === "1";
12305
- }
12306
- function resolveApiBase(env = process.env) {
12307
- for (const key of ENV_KEYS) {
12308
- const raw = env[key];
12309
- if (typeof raw !== "string") continue;
12310
- const trimmed = raw.trim();
12311
- if (trimmed === "") continue;
12312
- const normalized = normalizeOverride(trimmed);
12313
- if (normalized === null) {
12314
- throw new ApiBaseError(
12315
- `terminalhire: ${key}=${sanitizeOverrideForError(trimmed)} is not an allowed API host (allowed: ${ALLOWED_DESCRIPTION}). Refusing to continue so we do not silently hit production.`
12316
- );
12317
- }
12318
- if (isLoopbackOrigin(normalized) && !localApiAllowed(env)) {
12319
- throw new ApiBaseError(
12320
- `terminalhire: ${key}=${normalized} is a loopback origin. Set ${ALLOW_LOCAL_API_KEY}=1 to talk to a local web app on purpose. Refusing so stored credentials cannot be exfiltrated to localhost by a poisoned override.`
12321
- );
12322
- }
12323
- return normalized;
12324
- }
12325
- return PROD_API_BASE;
12326
- }
12327
- function normalizeOverride(raw) {
12328
- let url;
12329
- try {
12330
- url = new URL(raw);
12331
- } catch {
12332
- return null;
12333
- }
12334
- if (url.username !== "" || url.password !== "") return null;
12335
- const expectedProtocol = ALLOWED_HOSTS[url.hostname];
12336
- if (expectedProtocol === void 0) return null;
12337
- if (url.protocol !== expectedProtocol) return null;
12338
- if (url.hostname !== "localhost" && url.hostname !== "127.0.0.1" && url.port !== "") {
12339
- return null;
12340
- }
12341
- const rewrite = CANONICAL_REWRITES[url.hostname];
12342
- if (rewrite !== void 0) return rewrite;
12343
- return url.origin;
12344
- }
12345
-
12346
12489
  // bin/jpi-bounties.js
12490
+ init_api_base();
12347
12491
  init_founder_pin();
12348
12492
  var TERMINALHIRE_DIR7 = process.env.TERMINALHIRE_DIR || join13(homedir10(), ".terminalhire");
12349
12493
  var INDEX_CACHE_FILE2 = join13(TERMINALHIRE_DIR7, "index-cache.json");
12350
12494
  var INDEX_TTL_MS = 15 * 60 * 1e3;
12351
- var API_URL2 = resolveApiBase();
12495
+ var API_URL = resolveApiBase();
12352
12496
  var RANK_MODE = process.env["TERMINALHIRE_BOUNTY_RANK"] ?? "winnability";
12353
12497
  var CONTINUITY_RANK_DISABLED = process.env["TERMINALHIRE_NO_CONTINUITY_RANK"] === "1";
12354
12498
  var DEFAULT_LIMIT = 15;
@@ -12369,7 +12513,7 @@ function readIndexCache() {
12369
12513
  }
12370
12514
  async function fetchIndex(quiet = false) {
12371
12515
  const { index, reason, source, cachedAt } = await revalidateIndex({
12372
- apiUrl: API_URL2,
12516
+ apiUrl: API_URL,
12373
12517
  fetchImpl: (url, init) => fetch(url, init),
12374
12518
  readEntry: readCacheEntry,
12375
12519
  writeEntry: updateIndexCache
@@ -12520,7 +12664,7 @@ function classifyEmptyStatus({ preFilterCount, postFilterCount, priced }) {
12520
12664
  return "empty";
12521
12665
  }
12522
12666
  async function getBounties({ quiet = false, offline = false, priced = PRICED_ONLY } = {}) {
12523
- if (!quiet) console.log(`Fetching bounty index from ${API_URL2}/api/index...`);
12667
+ if (!quiet) console.log(`Fetching bounty index from ${API_URL}/api/index...`);
12524
12668
  const index = offline ? readIndexCache() : await fetchIndex(quiet);
12525
12669
  if (offline && !index) return { status: "no-cache" };
12526
12670
  let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");