hacklab 0.12.2 → 0.12.3
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 +28 -74
- package/dist/belt.d.ts +1 -1
- package/dist/belt.d.ts.map +1 -1
- package/dist/belt.js +2 -2
- package/dist/belt.js.map +1 -1
- package/dist/cli.js +5 -7
- package/dist/cli.js.map +1 -1
- package/dist/commands/daemon.d.ts +1 -1
- package/dist/commands/daemon.js +2 -2
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/login.d.ts +3 -16
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +78 -157
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/referral.js +2 -2
- package/dist/commands/referral.js.map +1 -1
- package/dist/commands/scan.d.ts +7 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +175 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/sync.js +1 -1
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +9 -11
- package/dist/commands/whoami.js.map +1 -1
- package/dist/daily-sync.js +1 -1
- package/dist/daily-sync.js.map +1 -1
- package/dist/posthog.js +1 -1
- package/dist/posthog.js.map +1 -1
- package/dist/referral.js +2 -2
- package/dist/referral.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +6 -11
- package/dist/registry.js.map +1 -1
- package/dist/scanners/index.d.ts +3 -3
- package/dist/scanners/index.js +3 -3
- package/dist/session.d.ts +4 -4
- package/dist/share.d.ts.map +1 -1
- package/dist/share.js +4 -4
- package/dist/share.js.map +1 -1
- package/dist/sync.d.ts +5 -6
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +7 -13
- package/dist/sync.js.map +1 -1
- package/dist/ui.d.ts +2 -0
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +4 -0
- package/dist/ui.js.map +1 -1
- package/dist/utils/openBrowser.d.ts +1 -1
- package/dist/utils/openBrowser.js +1 -1
- package/dist/utils/waitForEnter.d.ts +2 -8
- package/dist/utils/waitForEnter.d.ts.map +1 -1
- package/dist/utils/waitForEnter.js +2 -11
- package/dist/utils/waitForEnter.js.map +1 -1
- package/package.json +1 -1
- package/dist/commands/join.d.ts +0 -15
- package/dist/commands/join.d.ts.map +0 -1
- package/dist/commands/join.js +0 -487
- package/dist/commands/join.js.map +0 -1
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,WAAW,MAAM,cAAc,CAAA;AACtC,OAAO,EAAkB,YAAY,EAAE,MAAM,WAAW,CAAA;AAExD,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAA;AAC5B,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;AAC9B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;AAChC,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAA;AAC5B,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;AAClC,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAA;AACtC,2EAA2E;AAC3E,uCAAuC;AACvC,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* reported by `spawn` as an asynchronous `'error'` event — NOT a thrown
|
|
7
7
|
* exception — so a try/catch alone doesn't catch it, and with no listener Node
|
|
8
8
|
* escalates it to a fatal unhandled error. On a headless box that would kill the
|
|
9
|
-
* whole login
|
|
9
|
+
* whole login flow right after we've printed the URL to visit manually.
|
|
10
10
|
* We listen for `'error'` (failure) and `'spawn'` (success) so exactly one
|
|
11
11
|
* settles the promise and the ENOENT is swallowed.
|
|
12
12
|
*/
|
|
@@ -7,7 +7,7 @@ import { spawn } from 'node:child_process';
|
|
|
7
7
|
* reported by `spawn` as an asynchronous `'error'` event — NOT a thrown
|
|
8
8
|
* exception — so a try/catch alone doesn't catch it, and with no listener Node
|
|
9
9
|
* escalates it to a fatal unhandled error. On a headless box that would kill the
|
|
10
|
-
* whole login
|
|
10
|
+
* whole login flow right after we've printed the URL to visit manually.
|
|
11
11
|
* We listen for `'error'` (failure) and `'spawn'` (success) so exactly one
|
|
12
12
|
* settles the promise and the ENOENT is swallowed.
|
|
13
13
|
*/
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Print `prompt` and block until
|
|
3
|
-
*
|
|
4
|
-
* just carry on).
|
|
5
|
-
*
|
|
6
|
-
* Never hangs an unattended run: a non-TTY stdin (CI, piped input, a `< /dev/null`
|
|
7
|
-
* invocation) returns immediately, as does an EOF/close on the stream. Callers
|
|
8
|
-
* treat this as a courtesy pause, not a gate — whatever comes next must still
|
|
9
|
-
* happen when the answer is false.
|
|
2
|
+
* Print `prompt` and block until Enter. Resolves true if we waited, false if
|
|
3
|
+
* stdin is not a TTY (CI, piped input) so the caller should continue anyway.
|
|
10
4
|
*/
|
|
11
5
|
export declare function waitForEnter(prompt: string): Promise<boolean>;
|
|
12
6
|
//# sourceMappingURL=waitForEnter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"waitForEnter.d.ts","sourceRoot":"","sources":["../../src/utils/waitForEnter.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"waitForEnter.d.ts","sourceRoot":"","sources":["../../src/utils/waitForEnter.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWnE"}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { createInterface } from 'node:readline';
|
|
2
2
|
/**
|
|
3
|
-
* Print `prompt` and block until
|
|
4
|
-
*
|
|
5
|
-
* just carry on).
|
|
6
|
-
*
|
|
7
|
-
* Never hangs an unattended run: a non-TTY stdin (CI, piped input, a `< /dev/null`
|
|
8
|
-
* invocation) returns immediately, as does an EOF/close on the stream. Callers
|
|
9
|
-
* treat this as a courtesy pause, not a gate — whatever comes next must still
|
|
10
|
-
* happen when the answer is false.
|
|
3
|
+
* Print `prompt` and block until Enter. Resolves true if we waited, false if
|
|
4
|
+
* stdin is not a TTY (CI, piped input) so the caller should continue anyway.
|
|
11
5
|
*/
|
|
12
6
|
export async function waitForEnter(prompt) {
|
|
13
7
|
if (!process.stdin.isTTY)
|
|
@@ -18,9 +12,6 @@ export async function waitForEnter(prompt) {
|
|
|
18
12
|
rl.close();
|
|
19
13
|
resolve(true);
|
|
20
14
|
});
|
|
21
|
-
// EOF (or the stream closing under us) fires 'close' without ever answering
|
|
22
|
-
// the question. The first resolve wins, so the normal path above is
|
|
23
|
-
// unaffected — this only rescues the flow from waiting forever.
|
|
24
15
|
rl.once('close', () => resolve(false));
|
|
25
16
|
});
|
|
26
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"waitForEnter.js","sourceRoot":"","sources":["../../src/utils/waitForEnter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C
|
|
1
|
+
{"version":3,"file":"waitForEnter.js","sourceRoot":"","sources":["../../src/utils/waitForEnter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc;IAC/C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAEtC,OAAO,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;QAC5C,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;QAC5E,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;YACvB,EAAE,CAAC,KAAK,EAAE,CAAA;YACV,OAAO,CAAC,IAAI,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;QACF,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
CHANGED
package/dist/commands/join.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The hero command: the guided join ritual.
|
|
3
|
-
*
|
|
4
|
-
* scan → anonymous rank → GitHub OAuth → pick username → claim → card
|
|
5
|
-
*
|
|
6
|
-
* Value (rank) is shown before any account exists. GitHub auth comes right
|
|
7
|
-
* after the rank and before the username, so we know whether the account
|
|
8
|
-
* already has a claimed handle (and can skip the username prompt) before asking.
|
|
9
|
-
* Each stage degrades on its own terms (see the per-stage handling below) so a
|
|
10
|
-
* network blip on the vanity rank never blocks the actual join.
|
|
11
|
-
*/
|
|
12
|
-
export declare function join(opts?: {
|
|
13
|
-
browser?: boolean;
|
|
14
|
-
}): Promise<void>;
|
|
15
|
-
//# sourceMappingURL=join.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"AA4CA;;;;;;;;;;GAUG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,iBA0U1D"}
|
package/dist/commands/join.js
DELETED
|
@@ -1,487 +0,0 @@
|
|
|
1
|
-
import * as clack from '@clack/prompts';
|
|
2
|
-
import { beltForTokens } from '../belt.js';
|
|
3
|
-
import { loadConfig, resolveCursorAuth, saveConfig } from '../config.js';
|
|
4
|
-
import { captureEvent, identifyUser } from '../posthog.js';
|
|
5
|
-
import { referralUrl } from '../referral.js';
|
|
6
|
-
import { collectToolScans, computeStreaks, detectCursorUsage, formatTokens, mergeToolScans, rescanCursorWithApi, } from '../scanners/index.js';
|
|
7
|
-
import { loadSession, resolveAppUrl, saveSession } from '../session.js';
|
|
8
|
-
import { promptShareOnX, renderShareCard, } from '../share.js';
|
|
9
|
-
import { syncGithubRepos, uploadTokenScan } from '../sync.js';
|
|
10
|
-
import { bold, dim, info } from '../ui.js';
|
|
11
|
-
import { login } from './login.js';
|
|
12
|
-
const TOOL_LABELS = {
|
|
13
|
-
claude_code: 'Claude Code',
|
|
14
|
-
codex: 'Codex',
|
|
15
|
-
cursor: 'Cursor',
|
|
16
|
-
openclaw: 'OpenClaw',
|
|
17
|
-
hermes: 'Hermes',
|
|
18
|
-
opencode: 'OpenCode',
|
|
19
|
-
grok: 'Grok Build',
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* The hero command: the guided join ritual.
|
|
23
|
-
*
|
|
24
|
-
* scan → anonymous rank → GitHub OAuth → pick username → claim → card
|
|
25
|
-
*
|
|
26
|
-
* Value (rank) is shown before any account exists. GitHub auth comes right
|
|
27
|
-
* after the rank and before the username, so we know whether the account
|
|
28
|
-
* already has a claimed handle (and can skip the username prompt) before asking.
|
|
29
|
-
* Each stage degrades on its own terms (see the per-stage handling below) so a
|
|
30
|
-
* network blip on the vanity rank never blocks the actual join.
|
|
31
|
-
*/
|
|
32
|
-
export async function join(opts = {}) {
|
|
33
|
-
clack.intro(bold('hacklab'));
|
|
34
|
-
// Already logged in → abort immediately. `join` must not switch accounts,
|
|
35
|
-
// re-register, or scan anything when a session already exists; the way to
|
|
36
|
-
// change accounts is an explicit logout + login.
|
|
37
|
-
// Gate on a *completed* account (username claimed), not merely a handle. A
|
|
38
|
-
// handle alone isn't enough: a profile auto-created on first auth carries a
|
|
39
|
-
// (GitHub-derived) handle but hasn't claimed a username, and that user still
|
|
40
|
-
// needs to run join to pick one and upload their tokens. Only a claimed
|
|
41
|
-
// username means a real, finished profile — stop and point them at the
|
|
42
|
-
// logout/login switch path. Sessions saved before this field existed report
|
|
43
|
-
// it as undefined and fall through (they re-resolve on the next login).
|
|
44
|
-
const current = await loadSession();
|
|
45
|
-
if (current?.handle && current.usernameClaimed) {
|
|
46
|
-
clack.note(`you're already logged in as ${bold(`@${current.handle}`)} (${current.email}).\n` +
|
|
47
|
-
'join here would not switch accounts or change anything, so it stops.\n\n' +
|
|
48
|
-
'to use a different account:\n' +
|
|
49
|
-
' hacklab logout\n' +
|
|
50
|
-
' hacklab login', 'already logged in');
|
|
51
|
-
clack.outro(dim('nothing to do — log out first to switch accounts.'));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Derive the backend from the reused session when one exists: an unclaimed
|
|
55
|
-
// session saved against a non-production backend (via --env or
|
|
56
|
-
// HACKLAB_APP_URL) must not send its token to the production default.
|
|
57
|
-
// HACKLAB_APP_URL still wins inside resolveAppUrl.
|
|
58
|
-
const appUrl = resolveAppUrl(current);
|
|
59
|
-
// ── Stage 1: scan ────────────────────────────────────────────────────────
|
|
60
|
-
// Keep the per-tool results, not just the merged totals: Stage 1.5 may re-scan
|
|
61
|
-
// Cursor alone and re-merge, which needs the other tools' results intact.
|
|
62
|
-
const spin = clack.spinner();
|
|
63
|
-
spin.start('scanning local AI tool usage');
|
|
64
|
-
let results;
|
|
65
|
-
try {
|
|
66
|
-
results = await collectToolScans();
|
|
67
|
-
}
|
|
68
|
-
catch (err) {
|
|
69
|
-
spin.stop('scan failed');
|
|
70
|
-
clack.cancel(`couldn't read local AI usage: ${err instanceof Error ? err.message : String(err)}`);
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
spin.stop('scan complete');
|
|
74
|
-
let scan = mergeToolScans(results);
|
|
75
|
-
printToolTotals(scan);
|
|
76
|
-
// ── Stage 1.5: offer a Cursor API key ────────────────────────────────────
|
|
77
|
-
// Before the rank preview, so an accepted key feeds the rank we show and the
|
|
78
|
-
// numbers we upload — otherwise we'd rank the estimate and upload something
|
|
79
|
-
// else.
|
|
80
|
-
const rescanned = await offerCursorApiKey(results, spin);
|
|
81
|
-
if (rescanned) {
|
|
82
|
-
results = rescanned;
|
|
83
|
-
scan = mergeToolScans(results);
|
|
84
|
-
printToolTotals(scan);
|
|
85
|
-
}
|
|
86
|
-
// Empty-scan branch: no hard floor gate, but nothing to rank — let the user
|
|
87
|
-
// decide whether to continue.
|
|
88
|
-
if (scan.grandTotal <= 0) {
|
|
89
|
-
const cont = await clack.confirm({
|
|
90
|
-
message: 'No AI token usage found on this machine. Sign up anyway? (you can sync usage later)',
|
|
91
|
-
initialValue: false,
|
|
92
|
-
});
|
|
93
|
-
if (clack.isCancel(cont) || !cont) {
|
|
94
|
-
clack.outro(dim('come back after some Claude Code / Codex / Cursor sessions.'));
|
|
95
|
-
process.exit(0);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// ── Stage 2: anonymous rank (best-effort; never blocks the join) ──────────
|
|
99
|
-
// Captured for the share card later — the preview rank equals the post-sync
|
|
100
|
-
// rank (rank counts users with MORE tokens, so the user joining the set
|
|
101
|
-
// doesn't change it), so the card can show it without waiting on the upload.
|
|
102
|
-
let previewRank = null;
|
|
103
|
-
try {
|
|
104
|
-
const res = await fetch(`${appUrl}/api/rank/preview`, {
|
|
105
|
-
method: 'POST',
|
|
106
|
-
headers: { 'Content-Type': 'application/json' },
|
|
107
|
-
body: JSON.stringify({ totalTokens: scan.grandTotal }),
|
|
108
|
-
});
|
|
109
|
-
if (res.ok) {
|
|
110
|
-
const { rank, ofTotal } = (await res.json());
|
|
111
|
-
previewRank = rank;
|
|
112
|
-
clack.note(`${bold(`you'd be #${rank}`)} of ${ofTotal} hackers`, 'your rank');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
// Rank is a hook, not a gate. Skip silently and continue the join.
|
|
117
|
-
}
|
|
118
|
-
// ── Stage 3: GitHub OAuth when needed ─────────────────────────────────────
|
|
119
|
-
// The web onboarding flow runs `hacklab login` before `join`, so reuse that
|
|
120
|
-
// unclaimed session instead of making the user authorize GitHub twice. A
|
|
121
|
-
// direct `hacklab join` still performs the full login flow here.
|
|
122
|
-
let session = current;
|
|
123
|
-
if (!session) {
|
|
124
|
-
try {
|
|
125
|
-
await login({ allowSignup: true, browser: opts.browser });
|
|
126
|
-
}
|
|
127
|
-
catch (err) {
|
|
128
|
-
clack.cancel(`GitHub sign-in failed: ${err instanceof Error ? err.message : String(err)}. run \`hacklab join\` again.`);
|
|
129
|
-
process.exit(1);
|
|
130
|
-
}
|
|
131
|
-
session = await loadSession();
|
|
132
|
-
}
|
|
133
|
-
if (!session) {
|
|
134
|
-
clack.cancel('GitHub sign-in did not complete. run `hacklab join` again.');
|
|
135
|
-
process.exit(1);
|
|
136
|
-
}
|
|
137
|
-
// ── Stage 4: already-CLAIMED GitHub account → log in, never rename ─────────
|
|
138
|
-
// `login` resolves an existing GitHub link to its Hacklab account and stores
|
|
139
|
-
// that account's handle + claim status on the session. Gate on a *claimed*
|
|
140
|
-
// username, not handle presence: a profile auto-created on first auth (web
|
|
141
|
-
// signup, or a prior device login) carries a GitHub-derived handle but
|
|
142
|
-
// `usernameClaimed === false`, and that user came here precisely to pick a
|
|
143
|
-
// username and upload tokens — they fall through to Stage 5. Only a genuinely
|
|
144
|
-
// claimed account owns its handle, so behave like a plain `hacklab login`:
|
|
145
|
-
// leave the profile untouched and stop. (The server's claim route enforces
|
|
146
|
-
// this too — it refuses to rename a claimed profile — so this is UX, not the
|
|
147
|
-
// security boundary.)
|
|
148
|
-
if (session.handle && session.usernameClaimed) {
|
|
149
|
-
const base = appUrl.replace(/\/$/, '');
|
|
150
|
-
clack.note(`that GitHub account already has a hacklab account: ${bold(`@${session.handle}`)}.\n` +
|
|
151
|
-
'logged you in — username, bio, and links are unchanged.', 'welcome back');
|
|
152
|
-
clack.outro(dim(`${base}/${session.handle} · \`hacklab sync\` to update usage · \`hacklab chat\` to jump in`));
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
// ── Stage 5: pick username, then claim ───────────────────────────────────
|
|
156
|
-
// Only reached when the account has no claimed username yet: a fresh signup,
|
|
157
|
-
// or a first-time web user who authenticated on the site and now needs to
|
|
158
|
-
// choose a handle. An account that already set its username skipped this at
|
|
159
|
-
// Stage 4.
|
|
160
|
-
const username = await promptAvailableUsername(appUrl, {
|
|
161
|
-
token: session.token,
|
|
162
|
-
// Default to the handle GitHub auth already assigned, so a user who wants
|
|
163
|
-
// to keep their GitHub username just presses Enter (it no longer reads as
|
|
164
|
-
// taken now that the check excludes their own row).
|
|
165
|
-
initialValue: session.handle ?? undefined,
|
|
166
|
-
});
|
|
167
|
-
if (username === null) {
|
|
168
|
-
clack.outro(dim('cancelled.'));
|
|
169
|
-
process.exit(0);
|
|
170
|
-
}
|
|
171
|
-
// Claim (re-prompt username on a TOCTOU collision).
|
|
172
|
-
let claimedHandle = username;
|
|
173
|
-
while (true) {
|
|
174
|
-
const res = await fetch(`${appUrl}/api/cli/claim`, {
|
|
175
|
-
method: 'POST',
|
|
176
|
-
headers: {
|
|
177
|
-
'Content-Type': 'application/json',
|
|
178
|
-
Authorization: `Bearer ${session.token}`,
|
|
179
|
-
},
|
|
180
|
-
body: JSON.stringify({
|
|
181
|
-
username: claimedHandle,
|
|
182
|
-
}),
|
|
183
|
-
});
|
|
184
|
-
if (res.ok) {
|
|
185
|
-
const data = (await res.json());
|
|
186
|
-
claimedHandle = data.handle;
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
if (res.status === 409) {
|
|
190
|
-
const reprompt = await promptAvailableUsername(appUrl, {
|
|
191
|
-
token: session.token,
|
|
192
|
-
message: 'that name was just taken — pick another',
|
|
193
|
-
});
|
|
194
|
-
if (reprompt === null) {
|
|
195
|
-
clack.cancel('cancelled before claiming a handle.');
|
|
196
|
-
process.exit(1);
|
|
197
|
-
}
|
|
198
|
-
claimedHandle = reprompt;
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
const data = (await res.json().catch(() => null));
|
|
202
|
-
clack.cancel(data?.error ?? `claim failed (${res.status})`);
|
|
203
|
-
process.exit(1);
|
|
204
|
-
}
|
|
205
|
-
// Record the claimed handle on the local session so it reflects a *completed*
|
|
206
|
-
// account. The logged-in guard (here and in the installer) keys off a claimed
|
|
207
|
-
// username, so set both — without this a finished signup would still look
|
|
208
|
-
// half-done and a re-run of join would scan/upload again instead of stopping.
|
|
209
|
-
const claimedSession = {
|
|
210
|
-
...session,
|
|
211
|
-
handle: claimedHandle,
|
|
212
|
-
usernameClaimed: true,
|
|
213
|
-
};
|
|
214
|
-
await saveSession(claimedSession);
|
|
215
|
-
// ── Stage 6: save usage and mirror pinned projects ────────────────────────
|
|
216
|
-
// Finish essential work before the viral loop. The card is the reward for a
|
|
217
|
-
// completed claim, never something standing between the user and an account.
|
|
218
|
-
spin.start('saving your usage');
|
|
219
|
-
let syncResult = null;
|
|
220
|
-
try {
|
|
221
|
-
const result = await uploadTokenScan(claimedSession, scan, {
|
|
222
|
-
timeoutMs: 120_000,
|
|
223
|
-
});
|
|
224
|
-
syncResult = {
|
|
225
|
-
title: typeof result.title === 'string' ? result.title : undefined,
|
|
226
|
-
level: typeof result.level === 'number' ? result.level : undefined,
|
|
227
|
-
beltColor: typeof result.beltColor === 'string' ? result.beltColor : undefined,
|
|
228
|
-
rankAfter: typeof result.rankAfter === 'number' ? result.rankAfter : undefined,
|
|
229
|
-
tokensTotal: typeof result.tokensTotal === 'number' ? result.tokensTotal : undefined,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
catch {
|
|
233
|
-
// A failed usage upload does not undo the claimed handle. `hacklab sync`
|
|
234
|
-
// remains the explicit recovery path.
|
|
235
|
-
}
|
|
236
|
-
const base = appUrl.replace(/\/$/, '');
|
|
237
|
-
if (syncResult?.title && syncResult.level != null) {
|
|
238
|
-
spin.stop('usage saved');
|
|
239
|
-
// The total here is the server's account-wide figure (all machines, full
|
|
240
|
-
// history) — the same number `hacklab sync` reports — not this machine's
|
|
241
|
-
// scan, so the two commands never show a different total.
|
|
242
|
-
info(`${bold(syncResult.title)} lv.${syncResult.level}${syncResult.beltColor ? ` (${syncResult.beltColor} belt)` : ''}${syncResult.tokensTotal != null ? ` — ${formatTokens(syncResult.tokensTotal)} total` : ''}`);
|
|
243
|
-
if (syncResult.rankAfter)
|
|
244
|
-
info(`rank: #${syncResult.rankAfter}`);
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
spin.stop('usage sync deferred');
|
|
248
|
-
info(dim('run `hacklab sync` if your stats look off.'));
|
|
249
|
-
}
|
|
250
|
-
spin.start('syncing pinned github repos');
|
|
251
|
-
const repos = await syncGithubRepos(claimedSession);
|
|
252
|
-
if (repos && repos.synced > 0) {
|
|
253
|
-
spin.stop(`synced ${repos.synced} github project${repos.synced === 1 ? '' : 's'}`);
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
spin.stop('github projects synced');
|
|
257
|
-
}
|
|
258
|
-
clack.log.success(`${bold('claimed.')} ${base}/${claimedHandle}`);
|
|
259
|
-
if (claimedSession.email) {
|
|
260
|
-
await identifyUser(claimedHandle, {
|
|
261
|
-
$set: {
|
|
262
|
-
email: claimedSession.email,
|
|
263
|
-
handle: claimedHandle,
|
|
264
|
-
app_url: appUrl,
|
|
265
|
-
},
|
|
266
|
-
$set_once: { joined_at: new Date().toISOString() },
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
// Account-wide total from the upload response when it succeeded (the figure
|
|
270
|
-
// `hacklab sync` and the profile show), else this machine's scan. The card
|
|
271
|
-
// and analytics use it so every surface reports the same number.
|
|
272
|
-
const tokensTotal = syncResult?.tokensTotal ?? scan.grandTotal;
|
|
273
|
-
await captureEvent(claimedHandle, 'cli_join_completed', {
|
|
274
|
-
tokens_total: tokensTotal,
|
|
275
|
-
rank: syncResult?.rankAfter ?? previewRank ?? undefined,
|
|
276
|
-
});
|
|
277
|
-
// ── Stage 7: show the reward, then offer one sharing action ───────────────
|
|
278
|
-
const belt = beltForTokens(tokensTotal);
|
|
279
|
-
const streaks = computeStreaks(scan.dailyTotals.map((entry) => entry.date));
|
|
280
|
-
const card = {
|
|
281
|
-
handle: claimedHandle,
|
|
282
|
-
level: syncResult?.level ?? belt.level,
|
|
283
|
-
title: syncResult?.title ?? belt.title,
|
|
284
|
-
beltColor: syncResult?.beltColor ?? belt.beltColor,
|
|
285
|
-
tokensTotal,
|
|
286
|
-
rank: syncResult?.rankAfter ?? previewRank ?? 0,
|
|
287
|
-
streak: streaks.current,
|
|
288
|
-
longestStreak: streaks.longest,
|
|
289
|
-
progressPercent: belt.progressPercent,
|
|
290
|
-
estimatedCost: estimateCost(scan.toolTotals),
|
|
291
|
-
toolBreakdown: {
|
|
292
|
-
claudeCode: scan.toolTotals.claude_code ?? 0,
|
|
293
|
-
codex: scan.toolTotals.codex ?? 0,
|
|
294
|
-
cursor: scan.toolTotals.cursor ?? 0,
|
|
295
|
-
},
|
|
296
|
-
models: Object.entries(scan.modelTotals)
|
|
297
|
-
.map(([name, tokens]) => ({ name, tokens }))
|
|
298
|
-
.sort((a, b) => b.tokens - a.tokens),
|
|
299
|
-
dailyActivity: aggregateDailyActivity(scan.dailyTotals),
|
|
300
|
-
};
|
|
301
|
-
const cardPath = await renderShareCard(card);
|
|
302
|
-
await promptShareOnX(card, cardPath);
|
|
303
|
-
// One next block: referral + the daemon command. Discovery copy used to live
|
|
304
|
-
// here too; it is gone. Join still does not schedule the daemon — onboarding
|
|
305
|
-
// owns that step, and a background job should be a command they ran.
|
|
306
|
-
clack.note(`invite your crew\n${referralUrl(claimedHandle, base)}\n\n` +
|
|
307
|
-
'install the daemon — keeps your ai dashboard live\n' +
|
|
308
|
-
'$ hacklab daemon', 'next');
|
|
309
|
-
clack.outro(dim('done. return to onboarding for your bio and drop.'));
|
|
310
|
-
}
|
|
311
|
-
/** The per-tool token lines + grand total shown after a scan. */
|
|
312
|
-
function printToolTotals(scan) {
|
|
313
|
-
for (const [tool, total] of Object.entries(scan.toolTotals)) {
|
|
314
|
-
if (total > 0) {
|
|
315
|
-
info(`${(TOOL_LABELS[tool] ?? tool).padEnd(12)} ${formatTokens(total)} tokens`);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
info(bold(`total: ${formatTokens(scan.grandTotal)} tokens on this machine`));
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Offer to take a Cursor API key, but only from people it can actually help.
|
|
322
|
-
*
|
|
323
|
-
* Without a key the Cursor scanner can only estimate — AI lines × 30, all
|
|
324
|
-
* stamped on today, so no real history — which is the least accurate number in
|
|
325
|
-
* the scan. With one we read exact per-event token counts from Cursor's API.
|
|
326
|
-
* That's worth interrupting a Cursor user for, and worth interrupting nobody
|
|
327
|
-
* else for, so this asks only when the machine shows evidence of Cursor use and
|
|
328
|
-
* no key is configured yet.
|
|
329
|
-
*
|
|
330
|
-
* Returns the re-scanned per-tool results, or null when nothing changed (no
|
|
331
|
-
* Cursor, key already set, or the user skipped) and the caller should keep the
|
|
332
|
-
* scan it has.
|
|
333
|
-
*/
|
|
334
|
-
async function offerCursorApiKey(results, spin) {
|
|
335
|
-
const { apiKey } = await resolveCursorAuth();
|
|
336
|
-
if (apiKey)
|
|
337
|
-
return null;
|
|
338
|
-
if (!(await detectCursorUsage()))
|
|
339
|
-
return null;
|
|
340
|
-
clack.note('your cursor tokens are currently a rough estimate from local activity.\n' +
|
|
341
|
-
'a cursor api key gets exact per-event counts and real daily history.\n' +
|
|
342
|
-
dim('grab one from your cursor dashboard, or skip — you can add it later\n') +
|
|
343
|
-
dim('with `hacklab config cursor-api-key <key>`.'), 'cursor detected');
|
|
344
|
-
// password(), not text(): an API key shouldn't be echoed into the terminal or
|
|
345
|
-
// left sitting in scrollback.
|
|
346
|
-
const entered = await clack.password({
|
|
347
|
-
message: 'cursor api key (enter to skip)',
|
|
348
|
-
});
|
|
349
|
-
if (clack.isCancel(entered))
|
|
350
|
-
return null;
|
|
351
|
-
const key = String(entered ?? '').trim();
|
|
352
|
-
if (!key) {
|
|
353
|
-
info(dim('skipped — cursor tokens will stay estimated.'));
|
|
354
|
-
return null;
|
|
355
|
-
}
|
|
356
|
-
// A team key returns every member's events unless it's filtered by email, so
|
|
357
|
-
// an unscoped team key would credit the whole team's tokens to this profile.
|
|
358
|
-
const email = await optionalText('cursor account email (optional — scopes a team key to just you)', 'enter to skip');
|
|
359
|
-
await saveConfig({
|
|
360
|
-
...(await loadConfig()),
|
|
361
|
-
cursorApiKey: key,
|
|
362
|
-
...(email ? { cursorEmail: email } : {}),
|
|
363
|
-
});
|
|
364
|
-
spin.start('fetching exact cursor usage');
|
|
365
|
-
let rescanned;
|
|
366
|
-
try {
|
|
367
|
-
rescanned = await rescanCursorWithApi(results);
|
|
368
|
-
}
|
|
369
|
-
catch (err) {
|
|
370
|
-
spin.stop('cursor api scan failed');
|
|
371
|
-
info(dim(`keeping the local estimate: ${err instanceof Error ? err.message : String(err)}`));
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
374
|
-
const status = rescanned.find((r) => r.tool === 'cursor')?.cursorScanStatus;
|
|
375
|
-
switch (status?.source) {
|
|
376
|
-
case 'api':
|
|
377
|
-
spin.stop(`cursor: exact counts from ${status.events} usage events`);
|
|
378
|
-
return rescanned;
|
|
379
|
-
case 'api-partial':
|
|
380
|
-
spin.stop(`cursor: ${status.events} usage events (partial)`);
|
|
381
|
-
info(dim(`stopped early: ${status.reason}`));
|
|
382
|
-
return rescanned;
|
|
383
|
-
case 'api-failed':
|
|
384
|
-
spin.stop('cursor api scan failed');
|
|
385
|
-
info(dim(`${status.reason} — keeping the local estimate.`));
|
|
386
|
-
info(dim('fix it later with `hacklab config cursor-api-key <key>`.'));
|
|
387
|
-
return null;
|
|
388
|
-
default:
|
|
389
|
-
// Key accepted, but the API had no token-based events to report (a brand
|
|
390
|
-
// new account, or a team key scoped to an email with no usage).
|
|
391
|
-
spin.stop('cursor api returned no usage events');
|
|
392
|
-
info(dim('keeping the local estimate.'));
|
|
393
|
-
return null;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
/** Blended cost estimate ($/M tokens) across the scanned tools, for the card. */
|
|
397
|
-
function estimateCost(toolTotals) {
|
|
398
|
-
const rate = {
|
|
399
|
-
claude_code: 0.6,
|
|
400
|
-
codex: 0.25,
|
|
401
|
-
cursor: 0.4,
|
|
402
|
-
openclaw: 0.5,
|
|
403
|
-
hermes: 0.5,
|
|
404
|
-
opencode: 0.5,
|
|
405
|
-
grok: 0.5,
|
|
406
|
-
};
|
|
407
|
-
let cost = 0;
|
|
408
|
-
for (const [tool, tokens] of Object.entries(toolTotals)) {
|
|
409
|
-
cost += (tokens / 1_000_000) * (rate[tool] ?? 0.4);
|
|
410
|
-
}
|
|
411
|
-
return cost;
|
|
412
|
-
}
|
|
413
|
-
/** Collapse per-tool daily entries into one {date, tokens}[] for the card graph. */
|
|
414
|
-
function aggregateDailyActivity(dailyTotals) {
|
|
415
|
-
const byDate = new Map();
|
|
416
|
-
for (const entry of dailyTotals) {
|
|
417
|
-
byDate.set(entry.date, (byDate.get(entry.date) ?? 0) + entry.tokens);
|
|
418
|
-
}
|
|
419
|
-
return Array.from(byDate.entries())
|
|
420
|
-
.map(([date, tokens]) => ({ date, tokens }))
|
|
421
|
-
.sort((a, b) => a.date.localeCompare(b.date));
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Prompt for a username and loop until it passes the availability check or the
|
|
425
|
-
* user cancels. Returns the chosen username, or null if cancelled.
|
|
426
|
-
*
|
|
427
|
-
* `token` is sent on the availability check so the server can exclude the
|
|
428
|
-
* caller's OWN auto-assigned handle (auth now happens before this prompt, so
|
|
429
|
-
* without it the user's current handle reads back as "taken"). `initialValue`
|
|
430
|
-
* pre-fills the field on the first prompt — their current handle, so the common
|
|
431
|
-
* case is just pressing Enter to keep it.
|
|
432
|
-
*/
|
|
433
|
-
async function promptAvailableUsername(appUrl, opts = {}) {
|
|
434
|
-
let message = opts.message ?? 'pick your hacklab username';
|
|
435
|
-
// Pre-fill only the first prompt; once the user has edited/submitted, don't
|
|
436
|
-
// re-seed the field (a rejected name shouldn't reappear pre-filled).
|
|
437
|
-
let initialValue = opts.initialValue;
|
|
438
|
-
while (true) {
|
|
439
|
-
const value = await clack.text({
|
|
440
|
-
message,
|
|
441
|
-
placeholder: 'e.g. ada-lovelace',
|
|
442
|
-
initialValue,
|
|
443
|
-
});
|
|
444
|
-
if (clack.isCancel(value))
|
|
445
|
-
return null;
|
|
446
|
-
initialValue = undefined;
|
|
447
|
-
const candidate = String(value).trim();
|
|
448
|
-
let available = false;
|
|
449
|
-
let reason = 'could not check availability — try again';
|
|
450
|
-
try {
|
|
451
|
-
const res = await fetch(`${appUrl}/api/cli/username-available?u=${encodeURIComponent(candidate)}`, opts.token
|
|
452
|
-
? { headers: { Authorization: `Bearer ${opts.token}` } }
|
|
453
|
-
: undefined);
|
|
454
|
-
if (res.ok) {
|
|
455
|
-
const data = (await res.json());
|
|
456
|
-
available = data.available;
|
|
457
|
-
if (!available && data.reason)
|
|
458
|
-
reason = data.reason;
|
|
459
|
-
}
|
|
460
|
-
else if (res.status === 429) {
|
|
461
|
-
reason = 'too many checks — wait a moment and try again';
|
|
462
|
-
}
|
|
463
|
-
else if (res.status === 401) {
|
|
464
|
-
// The check is authenticated now. A rejected session can't be fixed by
|
|
465
|
-
// retrying a name, so break the loop instead of spinning on it. In
|
|
466
|
-
// practice this is near-impossible (the token was just minted this run).
|
|
467
|
-
clack.log.error('your hacklab session is no longer valid. run `hacklab login`, then `hacklab join` again.');
|
|
468
|
-
return null;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
catch {
|
|
472
|
-
// network error — fall through to re-prompt with the generic reason
|
|
473
|
-
}
|
|
474
|
-
if (available)
|
|
475
|
-
return candidate;
|
|
476
|
-
message = `${reason}\n pick your hacklab username`;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
/** A clack text prompt that returns trimmed text, or undefined if empty/cancelled. */
|
|
480
|
-
async function optionalText(message, placeholder = '(optional)') {
|
|
481
|
-
const value = await clack.text({ message, placeholder });
|
|
482
|
-
if (clack.isCancel(value))
|
|
483
|
-
return undefined;
|
|
484
|
-
const trimmed = String(value).trim();
|
|
485
|
-
return trimmed.length > 0 ? trimmed : undefined;
|
|
486
|
-
}
|
|
487
|
-
//# sourceMappingURL=join.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"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"}
|