terminalhire 0.42.4 → 0.42.6
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/founder-bounty-notify.js +117 -0
- package/dist/bin/jpi-bounties.js +28 -2
- package/dist/bin/jpi-chat-read.js +2 -1
- package/dist/bin/jpi-chat.js +2 -1
- package/dist/bin/jpi-config.js +167 -20
- package/dist/bin/jpi-contribute.js +2 -1
- package/dist/bin/jpi-dispatch.js +344 -72
- package/dist/bin/jpi-hub.js +2 -1
- package/dist/bin/jpi-inbox.js +2 -1
- package/dist/bin/jpi-jobs.js +6 -1
- package/dist/bin/jpi-link.js +2 -1
- package/dist/bin/jpi-login.js +2 -1
- package/dist/bin/jpi-mcp-chat.js +2 -1
- package/dist/bin/jpi-mcp.js +6 -1
- package/dist/bin/jpi-post.js +138 -64
- package/dist/bin/jpi-refresh.js +128 -1
- package/dist/bin/peer-connect-prompt.js +2 -1
- package/dist/bin/pulse-prompt.js +2 -1
- package/dist/src/config.js +6 -1
- package/dist/src/link.js +2 -1
- package/dist/src/posting-drafts.js +138 -64
- package/package.json +2 -2
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// bin/founder-bounty-notify.js
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
|
|
4
|
+
// bin/founder-pin.js
|
|
5
|
+
function isPinnedFounderBounty(j) {
|
|
6
|
+
return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// bin/founder-paid-badge.js
|
|
10
|
+
function openPaidIds(index) {
|
|
11
|
+
const jobs = index && index.jobs || [];
|
|
12
|
+
const ids = [];
|
|
13
|
+
for (const j of jobs) {
|
|
14
|
+
if (!j || typeof j.id !== "string") continue;
|
|
15
|
+
if (isPinnedFounderBounty(j)) ids.push(j.id);
|
|
16
|
+
}
|
|
17
|
+
return [...new Set(ids)].sort();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// bin/founder-bounty-notify.js
|
|
21
|
+
function nextFounderBountyNotifyState(index, previous) {
|
|
22
|
+
const open = openPaidIds(index);
|
|
23
|
+
const prior = previous && Array.isArray(previous.ids) ? previous.ids : null;
|
|
24
|
+
if (prior === null) {
|
|
25
|
+
return { ids: open, fire: [], seeded: true };
|
|
26
|
+
}
|
|
27
|
+
const seen = new Set(prior);
|
|
28
|
+
const fire = open.filter((id) => !seen.has(id));
|
|
29
|
+
const ids = [.../* @__PURE__ */ new Set([...prior.filter((id) => open.includes(id)), ...fire])].sort();
|
|
30
|
+
return { ids, fire, seeded: false };
|
|
31
|
+
}
|
|
32
|
+
function formatFounderBountyNotifyBody(index, fireIds) {
|
|
33
|
+
const jobs = index && index.jobs || [];
|
|
34
|
+
const byId = /* @__PURE__ */ new Map();
|
|
35
|
+
for (const j of jobs) {
|
|
36
|
+
if (j && typeof j.id === "string") byId.set(j.id, j);
|
|
37
|
+
}
|
|
38
|
+
if (fireIds.length === 1) {
|
|
39
|
+
const j = byId.get(fireIds[0]);
|
|
40
|
+
const amount = j && j.bounty && typeof j.bounty.amountUSD === "number" ? j.bounty.amountUSD : null;
|
|
41
|
+
const price = typeof amount === "number" && Number.isFinite(amount) && amount > 0 ? `$${Math.round(amount)} ` : "";
|
|
42
|
+
return `${price}founder bounty available \u2014 run: terminalhire bounties`;
|
|
43
|
+
}
|
|
44
|
+
return `${fireIds.length} founder bounties available \u2014 run: terminalhire bounties`;
|
|
45
|
+
}
|
|
46
|
+
function escapeAppleScriptString(s) {
|
|
47
|
+
return String(s).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
48
|
+
}
|
|
49
|
+
function displayLocalNotification({
|
|
50
|
+
title = "Terminalhire",
|
|
51
|
+
body,
|
|
52
|
+
platform = process.platform,
|
|
53
|
+
spawnFn = spawn
|
|
54
|
+
} = {}) {
|
|
55
|
+
if (!body || typeof body !== "string") return false;
|
|
56
|
+
try {
|
|
57
|
+
if (platform === "darwin") {
|
|
58
|
+
const t = escapeAppleScriptString(title);
|
|
59
|
+
const b = escapeAppleScriptString(body);
|
|
60
|
+
const child = spawnFn("osascript", ["-e", `display notification "${b}" with title "${t}"`], {
|
|
61
|
+
detached: true,
|
|
62
|
+
stdio: "ignore"
|
|
63
|
+
});
|
|
64
|
+
if (child && typeof child.unref === "function") child.unref();
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (platform === "win32") {
|
|
68
|
+
const safeTitle = String(title).replace(/'/g, "''");
|
|
69
|
+
const safeBody = String(body).replace(/'/g, "''");
|
|
70
|
+
const ps = `
|
|
71
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
72
|
+
$n = New-Object System.Windows.Forms.NotifyIcon
|
|
73
|
+
$n.Icon = [System.Drawing.SystemIcons]::Information
|
|
74
|
+
$n.Visible = $true
|
|
75
|
+
$n.ShowBalloonTip(8000, '${safeTitle}', '${safeBody}', [System.Windows.Forms.ToolTipIcon]::Info)
|
|
76
|
+
Start-Sleep -Seconds 9
|
|
77
|
+
$n.Dispose()
|
|
78
|
+
`.trim();
|
|
79
|
+
const child = spawnFn("powershell.exe", ["-NoProfile", "-Command", ps], {
|
|
80
|
+
detached: true,
|
|
81
|
+
stdio: "ignore",
|
|
82
|
+
windowsHide: true
|
|
83
|
+
});
|
|
84
|
+
if (child && typeof child.unref === "function") child.unref();
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function maybeNotifyFounderBounties({
|
|
93
|
+
index,
|
|
94
|
+
previous,
|
|
95
|
+
optedIn,
|
|
96
|
+
display = displayLocalNotification
|
|
97
|
+
} = {}) {
|
|
98
|
+
if (!optedIn) {
|
|
99
|
+
const ids = previous && Array.isArray(previous.ids) ? [...previous.ids].sort() : [];
|
|
100
|
+
return { state: { ids }, fired: [] };
|
|
101
|
+
}
|
|
102
|
+
const next = nextFounderBountyNotifyState(index, previous);
|
|
103
|
+
if (next.fire.length > 0) {
|
|
104
|
+
display({
|
|
105
|
+
title: "Terminalhire",
|
|
106
|
+
body: formatFounderBountyNotifyBody(index, next.fire)
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return { state: { ids: next.ids }, fired: next.fire };
|
|
110
|
+
}
|
|
111
|
+
export {
|
|
112
|
+
displayLocalNotification,
|
|
113
|
+
escapeAppleScriptString,
|
|
114
|
+
formatFounderBountyNotifyBody,
|
|
115
|
+
maybeNotifyFounderBounties,
|
|
116
|
+
nextFounderBountyNotifyState
|
|
117
|
+
};
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -11546,6 +11546,7 @@ __export(config_exports, {
|
|
|
11546
11546
|
getSurfaceMix: () => getSurfaceMix,
|
|
11547
11547
|
isBetaOptIn: () => isBetaOptIn,
|
|
11548
11548
|
isContributeEnabled: () => isContributeEnabled,
|
|
11549
|
+
isFounderBountyNotifyEnabled: () => isFounderBountyNotifyEnabled,
|
|
11549
11550
|
isInboundNudgeMuted: () => isInboundNudgeMuted,
|
|
11550
11551
|
isPeerConnectEnabled: () => isPeerConnectEnabled,
|
|
11551
11552
|
parseNudgeMode: () => parseNudgeMode,
|
|
@@ -11630,6 +11631,9 @@ function isContributeEnabled() {
|
|
|
11630
11631
|
function isBetaOptIn() {
|
|
11631
11632
|
return readConfig().betaOptIn === true;
|
|
11632
11633
|
}
|
|
11634
|
+
function isFounderBountyNotifyEnabled() {
|
|
11635
|
+
return readConfig().founderBountyNotify === true;
|
|
11636
|
+
}
|
|
11633
11637
|
var TERMINALHIRE_DIR6, CONFIG_FILE, DEFAULT_CONFIG;
|
|
11634
11638
|
var init_config = __esm({
|
|
11635
11639
|
"src/config.ts"() {
|
|
@@ -11651,7 +11655,8 @@ var init_config = __esm({
|
|
|
11651
11655
|
lastFullFeedbackAt: null,
|
|
11652
11656
|
lastPulseAskAt: null,
|
|
11653
11657
|
pulseDisclosed: false,
|
|
11654
|
-
mix: "balanced"
|
|
11658
|
+
mix: "balanced",
|
|
11659
|
+
founderBountyNotify: false
|
|
11655
11660
|
};
|
|
11656
11661
|
}
|
|
11657
11662
|
});
|
|
@@ -11880,6 +11885,23 @@ ${founderClaimBlurb(job.bounty?.amountUSD, job.bounty?.paidWork)}
|
|
|
11880
11885
|
terminalhire claim ${ref}
|
|
11881
11886
|
${sanitizeText(job.bounty?.claimUrl ?? job.url)}`;
|
|
11882
11887
|
}
|
|
11888
|
+
function wrapIndented(text, indent, width) {
|
|
11889
|
+
const pad = " ".repeat(indent);
|
|
11890
|
+
const words2 = String(text).split(/\s+/).filter(Boolean);
|
|
11891
|
+
if (words2.length === 0) return [];
|
|
11892
|
+
const lines = [];
|
|
11893
|
+
let line = "";
|
|
11894
|
+
for (const w of words2) {
|
|
11895
|
+
if (line === "") line = w;
|
|
11896
|
+
else if (line.length + 1 + w.length <= width) line += ` ${w}`;
|
|
11897
|
+
else {
|
|
11898
|
+
lines.push(pad + line);
|
|
11899
|
+
line = w;
|
|
11900
|
+
}
|
|
11901
|
+
}
|
|
11902
|
+
lines.push(pad + line);
|
|
11903
|
+
return lines;
|
|
11904
|
+
}
|
|
11883
11905
|
function printBounty(i, job, score, reason, matchedTags, claimedIds = /* @__PURE__ */ new Set(), continuityNote = null) {
|
|
11884
11906
|
const b = job.bounty ?? {};
|
|
11885
11907
|
const stars = b.repoStars != null ? ` \xB7 ${b.repoStars}\u2605` : "";
|
|
@@ -11897,6 +11919,9 @@ ${i + 1}. ${linkTitle(job.title, job.url)} [${ref}]`);
|
|
|
11897
11919
|
);
|
|
11898
11920
|
if (reason) console.log(` ${reason}`);
|
|
11899
11921
|
if (continuityNote) console.log(` ${continuityNote}`);
|
|
11922
|
+
if (b.publicSummary) {
|
|
11923
|
+
for (const line of wrapIndented(sanitizeText(b.publicSummary), 3, 76)) console.log(line);
|
|
11924
|
+
}
|
|
11900
11925
|
if (b.bountySource === "founder" && b.specProvenance) {
|
|
11901
11926
|
console.log(
|
|
11902
11927
|
` Spec: ${b.specProvenance === "agent_drafted_human_confirmed" ? "agent drafted \xB7 founder confirmed" : "founder authored"}`
|
|
@@ -12135,7 +12160,8 @@ export {
|
|
|
12135
12160
|
isPinnedFounderBounty,
|
|
12136
12161
|
printBounty,
|
|
12137
12162
|
rankBounties,
|
|
12138
|
-
run
|
|
12163
|
+
run,
|
|
12164
|
+
wrapIndented
|
|
12139
12165
|
};
|
|
12140
12166
|
/*! Bundled license information:
|
|
12141
12167
|
|
package/dist/bin/jpi-chat.js
CHANGED
package/dist/bin/jpi-config.js
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
11
|
|
|
12
12
|
// src/state-dir.ts
|
|
13
13
|
import { closeSync, constants, fchmodSync, fstatSync, mkdirSync, openSync } from "fs";
|
|
14
|
-
var STATE_DIR_MODE = 448;
|
|
15
|
-
var STATE_DIR_OK = "ok";
|
|
16
|
-
var STATE_DIR_SYMLINK = "symlink";
|
|
17
|
-
var STATE_DIR_UNVERIFIED = "unverified";
|
|
18
|
-
var warnedDirs = /* @__PURE__ */ new Set();
|
|
19
14
|
function warnStateDirOnce(dir, message) {
|
|
20
15
|
if (warnedDirs.has(dir)) return;
|
|
21
16
|
warnedDirs.add(dir);
|
|
@@ -56,8 +51,116 @@ function ensureStateDir(dir) {
|
|
|
56
51
|
}
|
|
57
52
|
}
|
|
58
53
|
}
|
|
54
|
+
var STATE_DIR_MODE, STATE_DIR_OK, STATE_DIR_SYMLINK, STATE_DIR_UNVERIFIED, warnedDirs;
|
|
55
|
+
var init_state_dir = __esm({
|
|
56
|
+
"src/state-dir.ts"() {
|
|
57
|
+
"use strict";
|
|
58
|
+
STATE_DIR_MODE = 448;
|
|
59
|
+
STATE_DIR_OK = "ok";
|
|
60
|
+
STATE_DIR_SYMLINK = "symlink";
|
|
61
|
+
STATE_DIR_UNVERIFIED = "unverified";
|
|
62
|
+
warnedDirs = /* @__PURE__ */ new Set();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// bin/founder-pin.js
|
|
67
|
+
function isPinnedFounderBounty(j) {
|
|
68
|
+
return j?.bounty?.bountySource === "founder" && j?.bounty?.claimable === true;
|
|
69
|
+
}
|
|
70
|
+
var init_founder_pin = __esm({
|
|
71
|
+
"bin/founder-pin.js"() {
|
|
72
|
+
"use strict";
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// bin/founder-paid-badge.js
|
|
77
|
+
var founder_paid_badge_exports = {};
|
|
78
|
+
__export(founder_paid_badge_exports, {
|
|
79
|
+
acknowledgeFounderPaid: () => acknowledgeFounderPaid,
|
|
80
|
+
computeFounderPaid: () => computeFounderPaid,
|
|
81
|
+
openPaidIds: () => openPaidIds
|
|
82
|
+
});
|
|
83
|
+
function openPaidIds(index) {
|
|
84
|
+
const jobs = index && index.jobs || [];
|
|
85
|
+
const ids = [];
|
|
86
|
+
for (const j of jobs) {
|
|
87
|
+
if (!j || typeof j.id !== "string") continue;
|
|
88
|
+
if (isPinnedFounderBounty(j)) ids.push(j.id);
|
|
89
|
+
}
|
|
90
|
+
return [...new Set(ids)].sort();
|
|
91
|
+
}
|
|
92
|
+
function gate(openIds, seenIds) {
|
|
93
|
+
const seen = new Set(seenIds);
|
|
94
|
+
const acknowledged = openIds.filter((id) => seen.has(id));
|
|
95
|
+
return { count: openIds.length - acknowledged.length, acknowledged };
|
|
96
|
+
}
|
|
97
|
+
function computeFounderPaid(index, previous) {
|
|
98
|
+
const open = openPaidIds(index);
|
|
99
|
+
const prior = previous && previous.acknowledged;
|
|
100
|
+
return gate(open, Array.isArray(prior) ? prior : []);
|
|
101
|
+
}
|
|
102
|
+
function acknowledgeFounderPaid({ shown = [], open = [], previous } = {}) {
|
|
103
|
+
const prior = previous && Array.isArray(previous.acknowledged) ? previous.acknowledged : [];
|
|
104
|
+
return gate(openPaidIds({ jobs: open }), [...prior, ...openPaidIds({ jobs: shown })]);
|
|
105
|
+
}
|
|
106
|
+
var init_founder_paid_badge = __esm({
|
|
107
|
+
"bin/founder-paid-badge.js"() {
|
|
108
|
+
"use strict";
|
|
109
|
+
init_founder_pin();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// bin/cache-store.js
|
|
114
|
+
var cache_store_exports = {};
|
|
115
|
+
__export(cache_store_exports, {
|
|
116
|
+
readCacheEntry: () => readCacheEntry,
|
|
117
|
+
updateIndexCache: () => updateIndexCache
|
|
118
|
+
});
|
|
119
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, renameSync } from "fs";
|
|
120
|
+
import { join as join2 } from "path";
|
|
121
|
+
import { homedir as homedir2 } from "os";
|
|
122
|
+
function readCacheEntry() {
|
|
123
|
+
try {
|
|
124
|
+
return JSON.parse(readFileSync2(INDEX_CACHE_FILE, "utf8"));
|
|
125
|
+
} catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function updateIndexCache(patch) {
|
|
130
|
+
ensureStateDir(TERMINALHIRE_DIR2);
|
|
131
|
+
const existing = readCacheEntry() ?? {};
|
|
132
|
+
const entry = {
|
|
133
|
+
...existing,
|
|
134
|
+
...patch,
|
|
135
|
+
schemaVersion: SCHEMA_VERSION,
|
|
136
|
+
ts: Date.now()
|
|
137
|
+
};
|
|
138
|
+
const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
|
|
139
|
+
writeFileSync2(tmp, JSON.stringify(entry), "utf8");
|
|
140
|
+
renameSync(tmp, INDEX_CACHE_FILE);
|
|
141
|
+
return entry;
|
|
142
|
+
}
|
|
143
|
+
var TERMINALHIRE_DIR2, INDEX_CACHE_FILE, SCHEMA_VERSION, tmpCounter;
|
|
144
|
+
var init_cache_store = __esm({
|
|
145
|
+
"bin/cache-store.js"() {
|
|
146
|
+
"use strict";
|
|
147
|
+
init_state_dir();
|
|
148
|
+
TERMINALHIRE_DIR2 = process.env.TERMINALHIRE_DIR || join2(homedir2(), ".terminalhire");
|
|
149
|
+
INDEX_CACHE_FILE = join2(TERMINALHIRE_DIR2, "index-cache.json");
|
|
150
|
+
SCHEMA_VERSION = 1;
|
|
151
|
+
tmpCounter = 0;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// bin/jpi-config.js
|
|
156
|
+
import { join as join3 } from "path";
|
|
157
|
+
import { homedir as homedir3 } from "os";
|
|
59
158
|
|
|
60
159
|
// src/config.ts
|
|
160
|
+
init_state_dir();
|
|
161
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
162
|
+
import { join } from "path";
|
|
163
|
+
import { homedir } from "os";
|
|
61
164
|
var TERMINALHIRE_DIR = process.env.TERMINALHIRE_DIR || join(homedir(), ".terminalhire");
|
|
62
165
|
var CONFIG_FILE = join(TERMINALHIRE_DIR, "config.json");
|
|
63
166
|
var DEFAULT_CONFIG = {
|
|
@@ -74,7 +177,8 @@ var DEFAULT_CONFIG = {
|
|
|
74
177
|
lastFullFeedbackAt: null,
|
|
75
178
|
lastPulseAskAt: null,
|
|
76
179
|
pulseDisclosed: false,
|
|
77
|
-
mix: "balanced"
|
|
180
|
+
mix: "balanced",
|
|
181
|
+
founderBountyNotify: false
|
|
78
182
|
};
|
|
79
183
|
function readConfig() {
|
|
80
184
|
try {
|
|
@@ -107,8 +211,8 @@ function parseSurfaceLead(raw) {
|
|
|
107
211
|
}
|
|
108
212
|
|
|
109
213
|
// bin/jpi-config.js
|
|
110
|
-
var
|
|
111
|
-
var CONFIG_FILE2 =
|
|
214
|
+
var TERMINALHIRE_DIR3 = process.env.TERMINALHIRE_DIR || join3(homedir3(), ".terminalhire");
|
|
215
|
+
var CONFIG_FILE2 = join3(TERMINALHIRE_DIR3, "config.json");
|
|
112
216
|
function parseNudgeMode(raw) {
|
|
113
217
|
if (raw === "session" || raw === "always") return raw;
|
|
114
218
|
const m = /^every:(\d+)$/.exec(raw);
|
|
@@ -186,13 +290,20 @@ async function run() {
|
|
|
186
290
|
if (envOverride) {
|
|
187
291
|
console.log(` (overridden by TERMINALHIRE_NUDGE=${envOverride} at runtime)`);
|
|
188
292
|
}
|
|
189
|
-
console.log(
|
|
293
|
+
console.log(
|
|
294
|
+
` peer-connect: ${cfg.peerConnect ? "on" : "off"} (ambient peer & founder surfacing; default off)`
|
|
295
|
+
);
|
|
190
296
|
const mixEnv = process.env["TH_MIX"];
|
|
191
|
-
console.log(
|
|
297
|
+
console.log(
|
|
298
|
+
` mix: ${cfg.mix} (roles vs. contributions on the ambient surface; default balanced)`
|
|
299
|
+
);
|
|
192
300
|
if (mixEnv) {
|
|
193
301
|
console.log(` (mix overridden by TH_MIX=${mixEnv} at runtime)`);
|
|
194
302
|
}
|
|
195
303
|
console.log(` lead: ${cfg.surfaceLead ?? "auto"} (auto derives from your open postings)`);
|
|
304
|
+
console.log(
|
|
305
|
+
` founder-notify: ${cfg.founderBountyNotify ? "on" : "off"} (OS ping when a paid founder bounty drops; default off)`
|
|
306
|
+
);
|
|
196
307
|
console.log(` config file: ${CONFIG_FILE2}`);
|
|
197
308
|
console.log("");
|
|
198
309
|
console.log(" Valid nudge values:");
|
|
@@ -204,9 +315,15 @@ async function run() {
|
|
|
204
315
|
console.log(" (set with: config set mix <value> \xB7 read with: config get mix)");
|
|
205
316
|
console.log("");
|
|
206
317
|
console.log(" Peer-connect (--connect on|off):");
|
|
207
|
-
console.log(
|
|
318
|
+
console.log(
|
|
319
|
+
" on \u2014 surface peers & founders in the spinner + send an anonymous matched signal"
|
|
320
|
+
);
|
|
208
321
|
console.log(" off \u2014 no peer matching, no directory fetch, no signal (default)");
|
|
209
322
|
console.log("");
|
|
323
|
+
console.log(" Founder bounty OS notify (--founder-notify on|off):");
|
|
324
|
+
console.log(" on \u2014 ping when a NEW claimable founder bounty appears (TERM-228)");
|
|
325
|
+
console.log(" off \u2014 no OS toast for founder supply (default)");
|
|
326
|
+
console.log("");
|
|
210
327
|
return;
|
|
211
328
|
}
|
|
212
329
|
const nudgeIdx = filtered.indexOf("--nudge");
|
|
@@ -238,8 +355,38 @@ async function run() {
|
|
|
238
355
|
console.log(` (saved to ${CONFIG_FILE2})`);
|
|
239
356
|
return;
|
|
240
357
|
}
|
|
358
|
+
const founderNotifyIdx = filtered.indexOf("--founder-notify");
|
|
359
|
+
if (founderNotifyIdx !== -1) {
|
|
360
|
+
const value = filtered[founderNotifyIdx + 1];
|
|
361
|
+
if (value !== "on" && value !== "off") {
|
|
362
|
+
console.error("Error: --founder-notify requires a value: on | off");
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
writeConfig({ founderBountyNotify: value === "on" });
|
|
366
|
+
if (value === "on") {
|
|
367
|
+
try {
|
|
368
|
+
const { openPaidIds: openPaidIds2 } = await Promise.resolve().then(() => (init_founder_paid_badge(), founder_paid_badge_exports));
|
|
369
|
+
const { readCacheEntry: readCacheEntry2, updateIndexCache: updateIndexCache2 } = await Promise.resolve().then(() => (init_cache_store(), cache_store_exports));
|
|
370
|
+
const entry = readCacheEntry2() ?? {};
|
|
371
|
+
const ids = openPaidIds2(entry.index);
|
|
372
|
+
updateIndexCache2({ founderPaidOsNotified: { ids } });
|
|
373
|
+
console.log(` founder-notify set to: on`);
|
|
374
|
+
console.log(
|
|
375
|
+
` (seeded ${ids.length} existing open bounty id(s) \u2014 only NEW ones will ping)`
|
|
376
|
+
);
|
|
377
|
+
} catch {
|
|
378
|
+
console.log(` founder-notify set to: on`);
|
|
379
|
+
console.log(" (could not seed from cache \u2014 first refresh will silent-seed)");
|
|
380
|
+
}
|
|
381
|
+
} else {
|
|
382
|
+
console.log(` founder-notify set to: off`);
|
|
383
|
+
}
|
|
384
|
+
console.log(` (saved to ${CONFIG_FILE2})`);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
241
387
|
console.error("Usage: terminalhire config --nudge <session|always|every:N>");
|
|
242
388
|
console.error(" terminalhire config --connect <on|off>");
|
|
389
|
+
console.error(" terminalhire config --founder-notify <on|off>");
|
|
243
390
|
console.error(" terminalhire config set mix <jobs|balanced|credential>");
|
|
244
391
|
console.error(" terminalhire config get mix");
|
|
245
392
|
console.error(" terminalhire config set lead <auto|dev|founder>");
|