hacklab 0.22.3 → 26.921.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.
Files changed (259) hide show
  1. package/README.md +39 -415
  2. package/dist/index.js +317 -23
  3. package/package.json +22 -40
  4. package/LICENSE +0 -21
  5. package/dist/agent-handoff.d.ts +0 -51
  6. package/dist/agent-handoff.d.ts.map +0 -1
  7. package/dist/agent-handoff.js +0 -91
  8. package/dist/agent-handoff.js.map +0 -1
  9. package/dist/api-client.d.ts +0 -18
  10. package/dist/api-client.d.ts.map +0 -1
  11. package/dist/api-client.js +0 -40
  12. package/dist/api-client.js.map +0 -1
  13. package/dist/belt.d.ts +0 -25
  14. package/dist/belt.d.ts.map +0 -1
  15. package/dist/belt.js +0 -113
  16. package/dist/belt.js.map +0 -1
  17. package/dist/card.d.ts +0 -66
  18. package/dist/card.d.ts.map +0 -1
  19. package/dist/card.js +0 -151
  20. package/dist/card.js.map +0 -1
  21. package/dist/cli.d.ts +0 -2
  22. package/dist/cli.d.ts.map +0 -1
  23. package/dist/cli.js +0 -238
  24. package/dist/cli.js.map +0 -1
  25. package/dist/commands/book.d.ts +0 -14
  26. package/dist/commands/book.d.ts.map +0 -1
  27. package/dist/commands/book.js +0 -90
  28. package/dist/commands/book.js.map +0 -1
  29. package/dist/commands/chat.d.ts +0 -36
  30. package/dist/commands/chat.d.ts.map +0 -1
  31. package/dist/commands/chat.js +0 -642
  32. package/dist/commands/chat.js.map +0 -1
  33. package/dist/commands/config.d.ts +0 -2
  34. package/dist/commands/config.d.ts.map +0 -1
  35. package/dist/commands/config.js +0 -84
  36. package/dist/commands/config.js.map +0 -1
  37. package/dist/commands/daemon.d.ts +0 -19
  38. package/dist/commands/daemon.d.ts.map +0 -1
  39. package/dist/commands/daemon.js +0 -72
  40. package/dist/commands/daemon.js.map +0 -1
  41. package/dist/commands/drop.d.ts +0 -12
  42. package/dist/commands/drop.d.ts.map +0 -1
  43. package/dist/commands/drop.js +0 -103
  44. package/dist/commands/drop.js.map +0 -1
  45. package/dist/commands/drops.d.ts +0 -9
  46. package/dist/commands/drops.d.ts.map +0 -1
  47. package/dist/commands/drops.js +0 -96
  48. package/dist/commands/drops.js.map +0 -1
  49. package/dist/commands/essay.d.ts +0 -40
  50. package/dist/commands/essay.d.ts.map +0 -1
  51. package/dist/commands/essay.js +0 -651
  52. package/dist/commands/essay.js.map +0 -1
  53. package/dist/commands/hackathon.d.ts +0 -2
  54. package/dist/commands/hackathon.d.ts.map +0 -1
  55. package/dist/commands/hackathon.js +0 -893
  56. package/dist/commands/hackathon.js.map +0 -1
  57. package/dist/commands/hacker.d.ts +0 -2
  58. package/dist/commands/hacker.d.ts.map +0 -1
  59. package/dist/commands/hacker.js +0 -87
  60. package/dist/commands/hacker.js.map +0 -1
  61. package/dist/commands/jobs.d.ts +0 -18
  62. package/dist/commands/jobs.d.ts.map +0 -1
  63. package/dist/commands/jobs.js +0 -138
  64. package/dist/commands/jobs.js.map +0 -1
  65. package/dist/commands/keys.d.ts +0 -2
  66. package/dist/commands/keys.d.ts.map +0 -1
  67. package/dist/commands/keys.js +0 -138
  68. package/dist/commands/keys.js.map +0 -1
  69. package/dist/commands/login.d.ts +0 -83
  70. package/dist/commands/login.d.ts.map +0 -1
  71. package/dist/commands/login.js +0 -236
  72. package/dist/commands/login.js.map +0 -1
  73. package/dist/commands/logout.d.ts +0 -2
  74. package/dist/commands/logout.d.ts.map +0 -1
  75. package/dist/commands/logout.js +0 -22
  76. package/dist/commands/logout.js.map +0 -1
  77. package/dist/commands/org-jobs.d.ts +0 -50
  78. package/dist/commands/org-jobs.d.ts.map +0 -1
  79. package/dist/commands/org-jobs.js +0 -383
  80. package/dist/commands/org-jobs.js.map +0 -1
  81. package/dist/commands/org.d.ts +0 -67
  82. package/dist/commands/org.d.ts.map +0 -1
  83. package/dist/commands/org.js +0 -1244
  84. package/dist/commands/org.js.map +0 -1
  85. package/dist/commands/ping.d.ts +0 -2
  86. package/dist/commands/ping.d.ts.map +0 -1
  87. package/dist/commands/ping.js +0 -50
  88. package/dist/commands/ping.js.map +0 -1
  89. package/dist/commands/profile.d.ts +0 -72
  90. package/dist/commands/profile.d.ts.map +0 -1
  91. package/dist/commands/profile.js +0 -672
  92. package/dist/commands/profile.js.map +0 -1
  93. package/dist/commands/project.d.ts +0 -2
  94. package/dist/commands/project.d.ts.map +0 -1
  95. package/dist/commands/project.js +0 -583
  96. package/dist/commands/project.js.map +0 -1
  97. package/dist/commands/referral.d.ts +0 -6
  98. package/dist/commands/referral.d.ts.map +0 -1
  99. package/dist/commands/referral.js +0 -93
  100. package/dist/commands/referral.js.map +0 -1
  101. package/dist/commands/rtfm.d.ts +0 -9
  102. package/dist/commands/rtfm.d.ts.map +0 -1
  103. package/dist/commands/rtfm.js +0 -114
  104. package/dist/commands/rtfm.js.map +0 -1
  105. package/dist/commands/scan.d.ts +0 -13
  106. package/dist/commands/scan.d.ts.map +0 -1
  107. package/dist/commands/scan.js +0 -286
  108. package/dist/commands/scan.js.map +0 -1
  109. package/dist/commands/scout.d.ts +0 -18
  110. package/dist/commands/scout.d.ts.map +0 -1
  111. package/dist/commands/scout.js +0 -232
  112. package/dist/commands/scout.js.map +0 -1
  113. package/dist/commands/setup-rail.d.ts +0 -58
  114. package/dist/commands/setup-rail.d.ts.map +0 -1
  115. package/dist/commands/setup-rail.js +0 -135
  116. package/dist/commands/setup-rail.js.map +0 -1
  117. package/dist/commands/setup.d.ts +0 -29
  118. package/dist/commands/setup.d.ts.map +0 -1
  119. package/dist/commands/setup.js +0 -442
  120. package/dist/commands/setup.js.map +0 -1
  121. package/dist/commands/sync.d.ts +0 -9
  122. package/dist/commands/sync.d.ts.map +0 -1
  123. package/dist/commands/sync.js +0 -345
  124. package/dist/commands/sync.js.map +0 -1
  125. package/dist/commands/update.d.ts +0 -2
  126. package/dist/commands/update.d.ts.map +0 -1
  127. package/dist/commands/update.js +0 -92
  128. package/dist/commands/update.js.map +0 -1
  129. package/dist/commands/whoami.d.ts +0 -2
  130. package/dist/commands/whoami.d.ts.map +0 -1
  131. package/dist/commands/whoami.js +0 -41
  132. package/dist/commands/whoami.js.map +0 -1
  133. package/dist/config.d.ts +0 -78
  134. package/dist/config.d.ts.map +0 -1
  135. package/dist/config.js +0 -93
  136. package/dist/config.js.map +0 -1
  137. package/dist/daily-sync.d.ts +0 -150
  138. package/dist/daily-sync.d.ts.map +0 -1
  139. package/dist/daily-sync.js +0 -665
  140. package/dist/daily-sync.js.map +0 -1
  141. package/dist/dossier.d.ts +0 -73
  142. package/dist/dossier.d.ts.map +0 -1
  143. package/dist/dossier.js +0 -141
  144. package/dist/dossier.js.map +0 -1
  145. package/dist/field-normalize.d.ts +0 -4
  146. package/dist/field-normalize.d.ts.map +0 -1
  147. package/dist/field-normalize.js +0 -8
  148. package/dist/field-normalize.js.map +0 -1
  149. package/dist/index.d.ts +0 -3
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/index.js.map +0 -1
  152. package/dist/job-fields.d.ts +0 -47
  153. package/dist/job-fields.d.ts.map +0 -1
  154. package/dist/job-fields.js +0 -148
  155. package/dist/job-fields.js.map +0 -1
  156. package/dist/machine.d.ts +0 -15
  157. package/dist/machine.d.ts.map +0 -1
  158. package/dist/machine.js +0 -64
  159. package/dist/machine.js.map +0 -1
  160. package/dist/org-fields.d.ts +0 -57
  161. package/dist/org-fields.d.ts.map +0 -1
  162. package/dist/org-fields.js +0 -167
  163. package/dist/org-fields.js.map +0 -1
  164. package/dist/posthog.d.ts +0 -38
  165. package/dist/posthog.d.ts.map +0 -1
  166. package/dist/posthog.js +0 -224
  167. package/dist/posthog.js.map +0 -1
  168. package/dist/project-fields.d.ts +0 -40
  169. package/dist/project-fields.d.ts.map +0 -1
  170. package/dist/project-fields.js +0 -79
  171. package/dist/project-fields.js.map +0 -1
  172. package/dist/prompt-consent.d.ts +0 -73
  173. package/dist/prompt-consent.d.ts.map +0 -1
  174. package/dist/prompt-consent.js +0 -191
  175. package/dist/prompt-consent.js.map +0 -1
  176. package/dist/prompt-stats.d.ts +0 -226
  177. package/dist/prompt-stats.d.ts.map +0 -1
  178. package/dist/prompt-stats.js +0 -561
  179. package/dist/prompt-stats.js.map +0 -1
  180. package/dist/referral.d.ts +0 -14
  181. package/dist/referral.d.ts.map +0 -1
  182. package/dist/referral.js +0 -28
  183. package/dist/referral.js.map +0 -1
  184. package/dist/registry.d.ts +0 -15
  185. package/dist/registry.d.ts.map +0 -1
  186. package/dist/registry.js +0 -180
  187. package/dist/registry.js.map +0 -1
  188. package/dist/resolve-command.d.ts +0 -20
  189. package/dist/resolve-command.d.ts.map +0 -1
  190. package/dist/resolve-command.js +0 -21
  191. package/dist/resolve-command.js.map +0 -1
  192. package/dist/scanners/antigravity.d.ts +0 -41
  193. package/dist/scanners/antigravity.d.ts.map +0 -1
  194. package/dist/scanners/antigravity.js +0 -210
  195. package/dist/scanners/antigravity.js.map +0 -1
  196. package/dist/scanners/github-copilot-telemetry.d.ts +0 -23
  197. package/dist/scanners/github-copilot-telemetry.d.ts.map +0 -1
  198. package/dist/scanners/github-copilot-telemetry.js +0 -220
  199. package/dist/scanners/github-copilot-telemetry.js.map +0 -1
  200. package/dist/scanners/github-copilot.d.ts +0 -68
  201. package/dist/scanners/github-copilot.d.ts.map +0 -1
  202. package/dist/scanners/github-copilot.js +0 -262
  203. package/dist/scanners/github-copilot.js.map +0 -1
  204. package/dist/scanners/incremental.d.ts +0 -282
  205. package/dist/scanners/incremental.d.ts.map +0 -1
  206. package/dist/scanners/incremental.js +0 -788
  207. package/dist/scanners/incremental.js.map +0 -1
  208. package/dist/scanners/index.d.ts +0 -116
  209. package/dist/scanners/index.d.ts.map +0 -1
  210. package/dist/scanners/index.js +0 -726
  211. package/dist/scanners/index.js.map +0 -1
  212. package/dist/scanners/sqlite.d.ts +0 -18
  213. package/dist/scanners/sqlite.d.ts.map +0 -1
  214. package/dist/scanners/sqlite.js +0 -63
  215. package/dist/scanners/sqlite.js.map +0 -1
  216. package/dist/scanners/util.d.ts +0 -112
  217. package/dist/scanners/util.d.ts.map +0 -1
  218. package/dist/scanners/util.js +0 -167
  219. package/dist/scanners/util.js.map +0 -1
  220. package/dist/session.d.ts +0 -106
  221. package/dist/session.d.ts.map +0 -1
  222. package/dist/session.js +0 -191
  223. package/dist/session.js.map +0 -1
  224. package/dist/share-card-colors.d.ts +0 -19
  225. package/dist/share-card-colors.d.ts.map +0 -1
  226. package/dist/share-card-colors.js +0 -36
  227. package/dist/share-card-colors.js.map +0 -1
  228. package/dist/share-card.d.ts +0 -31
  229. package/dist/share-card.d.ts.map +0 -1
  230. package/dist/share-card.js +0 -380
  231. package/dist/share-card.js.map +0 -1
  232. package/dist/share.d.ts +0 -17
  233. package/dist/share.d.ts.map +0 -1
  234. package/dist/share.js +0 -75
  235. package/dist/share.js.map +0 -1
  236. package/dist/sync.d.ts +0 -100
  237. package/dist/sync.d.ts.map +0 -1
  238. package/dist/sync.js +0 -304
  239. package/dist/sync.js.map +0 -1
  240. package/dist/ui.d.ts +0 -33
  241. package/dist/ui.d.ts.map +0 -1
  242. package/dist/ui.js +0 -127
  243. package/dist/ui.js.map +0 -1
  244. package/dist/utils/npmGlobal.d.ts +0 -30
  245. package/dist/utils/npmGlobal.d.ts.map +0 -1
  246. package/dist/utils/npmGlobal.js +0 -69
  247. package/dist/utils/npmGlobal.js.map +0 -1
  248. package/dist/utils/openBrowser.d.ts +0 -14
  249. package/dist/utils/openBrowser.d.ts.map +0 -1
  250. package/dist/utils/openBrowser.js +0 -47
  251. package/dist/utils/openBrowser.js.map +0 -1
  252. package/dist/utils/updateCheck.d.ts +0 -16
  253. package/dist/utils/updateCheck.d.ts.map +0 -1
  254. package/dist/utils/updateCheck.js +0 -111
  255. package/dist/utils/updateCheck.js.map +0 -1
  256. package/dist/utils/waitForEnter.d.ts +0 -12
  257. package/dist/utils/waitForEnter.d.ts.map +0 -1
  258. package/dist/utils/waitForEnter.js +0 -43
  259. package/dist/utils/waitForEnter.js.map +0 -1
@@ -1,345 +0,0 @@
1
- import * as clack from '@clack/prompts';
2
- import { appendSyncLog, clearSyncPaused, markSyncPaused, readSyncPaused, trimSyncLog, } from '../daily-sync.js';
3
- import { captureEvent } from '../posthog.js';
4
- import { loadPromptSync, parsePromptSyncFlag, resolvePromptSync, savePromptSync, } from '../prompt-consent.js';
5
- import { cumulativeTotals, hasPromptActivity, loadScanState, markUploaded, runTick, sameTotals, saveScanState, stageFullScan, tickPayload, } from '../scanners/incremental.js';
6
- import { collectToolScans, mergeToolScans } from '../scanners/index.js';
7
- import { loadSessionState } from '../session.js';
8
- import { checkSession, ensureFreshSession, formatTokens, LOGIN_EXPIRED_MESSAGE, refreshSession, runSync, SyncUploadError, scanConsentedPromptStats, syncGithubRepos, uploadTokenScan, } from '../sync.js';
9
- import { bold, dim, error, info, success } from '../ui.js';
10
- import { daemon } from './daemon.js';
11
- const SESSION_EXPIRED_REASON = 'your hacklab session expired — run `hacklab login`';
12
- /**
13
- * `hacklab sync` — dispatch on flags:
14
- * (none) interactive sync (scan, upload, show stats)
15
- * --install-daily deprecated alias for `hacklab daemon`
16
- * --tick the every-minute incremental run (usually a no-op)
17
- * --quiet the unattended daily run (logs to a file, no output)
18
- */
19
- export async function sync(args = []) {
20
- // Pull --share-prompt-sync out first so it works alongside every mode
21
- // below (an agent can set consent on the same run that installs the daemon).
22
- const { tier: flagTier, rest } = parsePromptSyncFlag(args);
23
- if (flagTier)
24
- await savePromptSync(flagTier);
25
- args = rest;
26
- if (args.includes('--install-daily')) {
27
- // Kept working (it shipped, and installed CLIs / old docs still say it) but
28
- // no longer advertised: scheduling the daemon is `hacklab daemon` now, which
29
- // is what the web onboarding flow tells people to run.
30
- info(dim('`sync --install-daily` is now `hacklab daemon` — running that.'));
31
- return daemon();
32
- }
33
- if (args.includes('--tick'))
34
- return tickSync();
35
- if (args.includes('--quiet'))
36
- return quietSync();
37
- return interactiveSync();
38
- }
39
- /**
40
- * The unattended daily run (launchd/systemd invoke `hacklab sync --quiet`).
41
- * Silent by design — everything goes to ~/.hacklab/sync.log. Proactively
42
- * refreshes a near-expiry session; if the session has truly lapsed it drops a
43
- * paused marker the next interactive run surfaces, then exits cleanly.
44
- *
45
- * It's also the repair pass for the minutely tick: a full stateless scan, so
46
- * whatever the tick's tail-follow missed or double-counted is corrected here and
47
- * the tick's state is re-based on the result. Incremental drift therefore can't
48
- * outlive a day.
49
- */
50
- async function quietSync() {
51
- const state = await loadSessionState();
52
- if (!state.session) {
53
- await appendSyncLog(`skip: ${state.status}`);
54
- // 'expired' or 'invalid' (corrupt/unparseable file) both mean the user must
55
- // log in again — surface it. 'missing' means logged out / never set up, so
56
- // stay silent (nothing to pause).
57
- if (state.status === 'expired' || state.status === 'invalid') {
58
- await markSyncPaused(state.status === 'invalid'
59
- ? 'your hacklab session file is unreadable — run `hacklab login`'
60
- : SESSION_EXPIRED_REASON);
61
- }
62
- return;
63
- }
64
- const session = await ensureFreshSession(state.session);
65
- const results = await collectToolScans();
66
- const scan = mergeToolScans(results);
67
- // Whatever the user already consented to. The unattended run never asks, so
68
- // a machine that has never answered uploads token counts only.
69
- const promptStats = await scanConsentedPromptStats((await loadPromptSync()) ?? 'none');
70
- // Upload tokens AND mirror pinned repos together, so the after-refresh retry
71
- // below does the exact same work as the happy path (no silently-skipped repo
72
- // sync on a day the session had to be refreshed mid-run).
73
- //
74
- // The state rebuild is staged first: it works out which prompt rows are still
75
- // outstanding, and this upload carries them, so a machine whose minutely tick
76
- // never runs still gets its prompt activity up. Re-staging on the retry is
77
- // free — the failed attempt committed nothing, so the claim comes out the
78
- // same.
79
- const push = async (s) => {
80
- const staged = await stageFullScan(results, {
81
- scanned: promptStats?.activity ?? null,
82
- });
83
- await uploadTokenScan(s, staged.promptActivity
84
- ? { ...scan, promptActivity: staged.promptActivity }
85
- : scan, { promptStats });
86
- await staged.commit();
87
- await syncGithubRepos(s);
88
- };
89
- try {
90
- await push(session);
91
- await clearSyncPaused();
92
- await appendSyncLog('ok');
93
- }
94
- catch (e) {
95
- const msg = e instanceof Error ? e.message : String(e);
96
- if (msg !== LOGIN_EXPIRED_MESSAGE) {
97
- await appendSyncLog(`error: ${msg}`);
98
- return;
99
- }
100
- // Proactive refresh missed it — try once more, then pause.
101
- const refreshed = await refreshSession(session);
102
- if (refreshed) {
103
- try {
104
- await push(refreshed);
105
- await clearSyncPaused();
106
- await appendSyncLog('ok (after refresh)');
107
- return;
108
- }
109
- catch {
110
- // fall through to pause
111
- }
112
- }
113
- await markSyncPaused(SESSION_EXPIRED_REASON);
114
- await appendSyncLog('paused: session expired');
115
- }
116
- }
117
- /** How long to sit out after a 429 that came without a Retry-After. */
118
- const DEFAULT_BACKOFF_MS = 15 * 60 * 1000;
119
- const MAX_BACKOFF_MS = 6 * 60 * 60 * 1000;
120
- function backoffMs(retryAfter) {
121
- const seconds = Number(retryAfter);
122
- if (!Number.isFinite(seconds) || seconds <= 0)
123
- return DEFAULT_BACKOFF_MS;
124
- return Math.min(seconds * 1000, MAX_BACKOFF_MS);
125
- }
126
- /**
127
- * Log a tick failure once. A minutely job that keeps hitting the same wall (no
128
- * network, server down) would otherwise write 1440 identical lines a day, so the
129
- * first one goes in and the rest are suppressed until something changes.
130
- */
131
- async function logTickError(state, line) {
132
- if (state.lastError === line)
133
- return;
134
- state.lastError = line;
135
- await appendSyncLog(line);
136
- }
137
- /** Pause the background sync, logging it only the first time. */
138
- async function pauseTick(reason) {
139
- const alreadyPaused = await readSyncPaused();
140
- await markSyncPaused(reason);
141
- if (!alreadyPaused)
142
- await appendSyncLog(`tick paused: ${reason}`);
143
- }
144
- /**
145
- * `hacklab sync --tick` — the every-minute run. Where `--quiet` re-scans every
146
- * log from scratch (~6s and a few hundred MB for a heavy user), this reads only
147
- * what the AI tools appended since the last tick, and on the overwhelmingly
148
- * common minute where nothing was appended it exits after a stat walk, without
149
- * touching the network. Silent unless it uploaded, failed, or got paused: the
150
- * log has to survive 1440 runs a day.
151
- */
152
- async function tickSync() {
153
- const saved = await loadScanState();
154
- // The server asked us to back off — respect it before doing any work at all.
155
- if (saved?.nextAllowedAt && Date.now() < saved.nextAllowedAt)
156
- return;
157
- await trimSyncLog();
158
- const sessionState = await loadSessionState();
159
- if (!sessionState.session) {
160
- // 'missing' is a logged-out machine: nothing to say, every minute.
161
- if (sessionState.status === 'expired' ||
162
- sessionState.status === 'invalid') {
163
- await pauseTick(sessionState.status === 'invalid'
164
- ? 'your hacklab session file is unreadable — run `hacklab login`'
165
- : SESSION_EXPIRED_REASON);
166
- }
167
- return;
168
- }
169
- const session = await ensureFreshSession(sessionState.session);
170
- // An unattended job never expands an older consent scope.
171
- const promptSync = (await loadPromptSync()) ?? 'none';
172
- const { state, changed } = await runTick(saved, undefined, {
173
- promptActivity: promptSync !== 'none',
174
- });
175
- const promptPending = promptSync !== 'none' && hasPromptActivity(state);
176
- const totals = cumulativeTotals(state);
177
- if (state.dirty.length === 0 &&
178
- !promptPending &&
179
- sameTotals(totals.toolTotals, state.uploaded.toolTotals) &&
180
- sameTotals(totals.modelTotals, state.uploaded.modelTotals)) {
181
- // The common case: nothing new to say. Persist only if the walk actually
182
- // saw something move (a touched file, a re-read harness).
183
- if (changed)
184
- await saveScanState(state);
185
- return;
186
- }
187
- const scan = tickPayload(state, { promptActivity: promptPending });
188
- const dates = state.dirty.length;
189
- // No full prompt scan and no GitHub mirror: those are the daily job's work,
190
- // and a minutely run has no business re-reading whole transcripts. Not
191
- // interactive either — a background tick isn't user activity.
192
- try {
193
- const result = await uploadTokenScan(session, scan);
194
- markUploaded(state);
195
- await saveScanState(state);
196
- await clearSyncPaused();
197
- await appendSyncLog(`tick: +${formatTokens(Number(result.tokensDelta ?? 0))} tokens (${dates} date${dates === 1 ? '' : 's'})`);
198
- }
199
- catch (e) {
200
- const message = e instanceof Error ? e.message : String(e);
201
- const status = e instanceof SyncUploadError ? e.status : 0;
202
- if (status === 429) {
203
- const wait = backoffMs(e instanceof SyncUploadError ? e.retryAfter : null);
204
- state.nextAllowedAt = Date.now() + wait;
205
- await logTickError(state, `tick: rate limited, pausing ${Math.round(wait / 1000)}s`);
206
- await saveScanState(state);
207
- return;
208
- }
209
- if (message === LOGIN_EXPIRED_MESSAGE) {
210
- const refreshed = await refreshSession(session);
211
- if (refreshed) {
212
- try {
213
- const result = await uploadTokenScan(refreshed, scan);
214
- markUploaded(state);
215
- await saveScanState(state);
216
- await clearSyncPaused();
217
- await appendSyncLog(`tick: +${formatTokens(Number(result.tokensDelta ?? 0))} tokens (${dates} dates, after refresh)`);
218
- return;
219
- }
220
- catch {
221
- // fall through to pause
222
- }
223
- }
224
- await saveScanState(state);
225
- await pauseTick(SESSION_EXPIRED_REASON);
226
- return;
227
- }
228
- // Dirty dates stay dirty, so the next tick retries them.
229
- await logTickError(state, `tick error: ${message}`);
230
- await saveScanState(state);
231
- }
232
- }
233
- async function interactiveSync() {
234
- const sessionState = await loadSessionState();
235
- if (!sessionState.session) {
236
- error(sessionState.status === 'expired' ? 'login expired' : 'not logged in');
237
- info(`run ${dim('hacklab login')} first`);
238
- process.exit(1);
239
- }
240
- // Fail fast with clear diagnostics (auth / wrong-backend / server-down) before
241
- // scanning and uploading.
242
- const sessionCheck = await checkSession(sessionState.session);
243
- if (sessionCheck.status === 'unauthorized') {
244
- error('login expired');
245
- info(`run ${dim('hacklab login')} again`);
246
- process.exit(1);
247
- }
248
- if (sessionCheck.status === 'failed') {
249
- error(sessionCheck.message);
250
- process.exit(1);
251
- }
252
- // Proactively slide a near-expiry session forward — same behavior as the daily
253
- // job, so expiry management doesn't differ by entry point.
254
- const session = await ensureFreshSession(sessionState.session);
255
- // Ask before scanning anything conversational. Asked once, then remembered;
256
- // an unanswered or non-TTY run resolves to 'none'.
257
- const promptSync = await resolvePromptSync(null, { interactive: true });
258
- console.log('');
259
- console.log(bold(' hacklab sync'));
260
- console.log(dim(' scanning local AI tool usage...'));
261
- console.log('');
262
- let result;
263
- try {
264
- // Manual `hacklab sync` — tag the upload as interactive so the backend counts
265
- // it as user activity (the daily background job doesn't).
266
- result = await runSync(session, { interactive: true, promptSync });
267
- }
268
- catch (e) {
269
- error(e instanceof Error ? e.message : 'sync failed');
270
- process.exit(1);
271
- }
272
- const { claudeTotal, codexTotal, cursorTotal, openclawTotal, hermesTotal, opencodeTotal, grokTotal, copilotTotal, antigravityTotal, cursorScanStatus, result: r, } = result;
273
- if (claudeTotal > 0)
274
- info(` Claude Code ${formatTokens(claudeTotal)} tokens`);
275
- if (codexTotal > 0)
276
- info(` Codex ${formatTokens(codexTotal)} tokens`);
277
- if (cursorTotal > 0)
278
- info(` Cursor ${formatTokens(cursorTotal)} tokens`);
279
- if (openclawTotal > 0)
280
- info(` OpenClaw ${formatTokens(openclawTotal)} tokens`);
281
- if (hermesTotal > 0)
282
- info(` Hermes ${formatTokens(hermesTotal)} tokens`);
283
- if (opencodeTotal > 0)
284
- info(` OpenCode ${formatTokens(opencodeTotal)} tokens`);
285
- if (grokTotal > 0)
286
- info(` Grok Build ${formatTokens(grokTotal)} tokens`);
287
- if (copilotTotal > 0)
288
- info(` Copilot ${formatTokens(copilotTotal)} tokens`);
289
- if (antigravityTotal > 0)
290
- info(` Antigravity ${formatTokens(antigravityTotal)} tokens`);
291
- // A key Cursor rejected must never be silent: the Cursor line above would be
292
- // the local estimate while the user believes they're getting exact counts.
293
- if (cursorScanStatus.source === 'api-failed') {
294
- error(` cursor: ${cursorScanStatus.reason}`);
295
- info(dim(' fell back to a local estimate — the Cursor number above is rough'));
296
- info(dim(' fix it with `hacklab config cursor-api-key <key>`'));
297
- }
298
- else if (cursorScanStatus.source === 'api-partial') {
299
- info(dim(` cursor: partial scan — ${cursorScanStatus.reason}`));
300
- }
301
- console.log('');
302
- success(` ${bold(String(r.title))} lv.${r.level} — ${formatTokens(Number(r.tokensTotal))} total`);
303
- if (Number(r.tokensDelta) > 0) {
304
- info(` +${formatTokens(Number(r.tokensDelta))} since last sync`);
305
- }
306
- if (result.promptStats) {
307
- const { totalPrompts } = result.promptStats;
308
- info(` prompts ${formatTokens(totalPrompts)} scanned${promptSync === 'full' ? dim(' (+ text sample)') : ''}`);
309
- // The backend can only attach a project's count if the repo matches one of
310
- // this user's own projects. Reporting the match rate keeps a scan that
311
- // matched nothing from reading as a success.
312
- const summary = result.result.promptStats;
313
- const reported = summary?.projectsReported ?? 0;
314
- const matched = summary?.projectsMatched ?? 0;
315
- if (reported > 0 && matched === 0) {
316
- info(dim(` none of your ${reported} local repos matched a hacklab project — run \`hacklab project add --title … --url …\``));
317
- }
318
- else if (matched > 0) {
319
- info(dim(` matched ${matched} of ${reported} local repos to projects`));
320
- }
321
- }
322
- // Mirror pinned GitHub repos into projects (best-effort; never fails sync).
323
- const repos = await syncGithubRepos(session);
324
- if (repos && (repos.synced > 0 || repos.removed > 0)) {
325
- const parts = [`${repos.synced} project${repos.synced === 1 ? '' : 's'}`];
326
- if (repos.removed > 0)
327
- parts.push(`removed ${repos.removed}`);
328
- info(` github: ${parts.join(', ')}`);
329
- }
330
- await captureEvent(session.handle, 'cli_sync_completed', {
331
- tokens_claude: claudeTotal,
332
- tokens_codex: codexTotal,
333
- tokens_cursor: cursorTotal,
334
- tokens_openclaw: openclawTotal,
335
- tokens_hermes: hermesTotal,
336
- tokens_opencode: opencodeTotal,
337
- tokens_grok: grokTotal,
338
- tokens_github_copilot: copilotTotal,
339
- tokens_antigravity: antigravityTotal,
340
- level: r.level,
341
- title: r.title,
342
- });
343
- clack.outro(dim('synced.'));
344
- }
345
- //# sourceMappingURL=sync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export declare function update(): Promise<void>;
2
- //# sourceMappingURL=update.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AA6BA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CA+C5C"}
@@ -1,92 +0,0 @@
1
- import { createRequire } from 'node:module';
2
- import { delimiter, join } from 'node:path';
3
- import { captureEvent } from '../posthog.js';
4
- import { loadSession } from '../session.js';
5
- import { dim, error, info, success } from '../ui.js';
6
- import { isWritable, npmGlobalRoot, runNpm, userNpmPrefix, } from '../utils/npmGlobal.js';
7
- import { fetchLatest, isNewerVersion } from '../utils/updateCheck.js';
8
- // The version we're running now — read from package.json (two levels up from
9
- // this module, in both `dist/` and `src/`) the same way index.ts does, so it
10
- // can't drift from a hardcoded string.
11
- const require = createRequire(import.meta.url);
12
- const { version: CURRENT } = require('../../package.json');
13
- // `hacklab update` — a permission-safe wrapper around `npm i -g hacklab@latest`.
14
- // A plain `npm i -g` is enough on most machines, but on systems where npm's
15
- // global folder is root-owned (a stock /usr/local) it dies with EACCES. Rather
16
- // than surface that stack trace or reach for sudo, we probe writability first
17
- // and, if needed, reconfigure npm to a user-owned prefix (option H1) before
18
- // installing. Works on Linux, macOS, and Windows; the prefix reconfigure is a
19
- // POSIX concern only (Windows installs globals into a user-writable %APPDATA%).
20
- export async function update() {
21
- // For analytics only — never block the update on a session read.
22
- const session = await loadSession().catch(() => null);
23
- // Short-circuit when there's nothing to do: if the registry says we're already
24
- // on the latest, skip the install entirely. Crucially this runs BEFORE any
25
- // writability probe / prefix reconfigure — we never want to touch ~/.npmrc when
26
- // there's nothing to install. A failed/timed-out lookup returns undefined and
27
- // falls through to the install (the safe default: attempt it rather than
28
- // wrongly claim we're current).
29
- const latest = await fetchLatest();
30
- if (latest && !isNewerVersion(latest, CURRENT)) {
31
- success(`already on the latest hacklab (${CURRENT}).`);
32
- return;
33
- }
34
- const reconfiguredPrefix = ensureWritableGlobalPrefix();
35
- info('updating hacklab (npm i -g hacklab@latest)…');
36
- const res = runNpm(['install', '-g', 'hacklab@latest']);
37
- if (res.status !== 0) {
38
- error('update failed.');
39
- if (res.error?.message.includes('ENOENT')) {
40
- info('npm not found — it ships with Node. Install Node 20+ and retry.');
41
- }
42
- else {
43
- info('Try again, or install manually: npm install -g hacklab@latest');
44
- }
45
- await captureEvent(session?.handle, 'cli_update_failed');
46
- process.exit(1);
47
- }
48
- success('hacklab is up to date.');
49
- if (reconfiguredPrefix) {
50
- const binDir = join(reconfiguredPrefix, 'bin');
51
- info(`npm now installs global packages under ${reconfiguredPrefix}.`);
52
- info('Add its bin dir to your PATH — put this in your shell profile:');
53
- console.log(dim(` export PATH="${binDir}:$PATH"`));
54
- info(dim('Prefer the system location? Undo with `npm config delete prefix`, then reinstall with sudo.'));
55
- }
56
- await captureEvent(session?.handle, 'cli_update', {
57
- from: CURRENT,
58
- to: latest ?? null,
59
- });
60
- }
61
- /**
62
- * If npm's global folder isn't writable by this user, reconfigure npm to a
63
- * user-owned prefix and return that prefix; otherwise return null (nothing to
64
- * do). The reconfigure is skipped on Windows, where global installs already land
65
- * in a user-writable location. Exits the process with a clear, actionable
66
- * message if the reconfigure itself fails.
67
- */
68
- function ensureWritableGlobalPrefix() {
69
- if (process.platform === 'win32')
70
- return null;
71
- const root = npmGlobalRoot();
72
- if (!root || isWritable(root))
73
- return null;
74
- const prefix = userNpmPrefix();
75
- info(`npm's global folder isn't writable (${root}).`);
76
- info(`Reconfiguring npm to install under ${prefix} — no sudo needed…`);
77
- const cfg = runNpm(['config', 'set', 'prefix', prefix], { capture: true });
78
- if (cfg.status !== 0) {
79
- error("couldn't reconfigure npm automatically.");
80
- info('Install into the system location with sudo instead:');
81
- console.log(dim(' sudo npm install -g hacklab@latest'));
82
- info('or set a user prefix yourself:');
83
- console.log(dim(` npm config set prefix "${prefix}" && npm install -g hacklab@latest`));
84
- process.exit(1);
85
- }
86
- // Make the new bin dir usable by anything this process spawns for the rest of
87
- // the run. The persistent profile edit (printed after install) is only needed
88
- // for future shells.
89
- process.env.PATH = `${join(prefix, 'bin')}${delimiter}${process.env.PATH ?? ''}`;
90
- return prefix;
91
- }
92
- //# sourceMappingURL=update.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export declare function whoami(): Promise<void>;
2
- //# sourceMappingURL=whoami.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAmBA,wBAAsB,MAAM,kBAsB3B"}
@@ -1,41 +0,0 @@
1
- import { envNameForUrl, loadSession, resolveAppUrl } from '../session.js';
2
- import { dim, error, info, success } from '../ui.js';
3
- /**
4
- * `HACKLAB_DEV` — an explicit developer opt-in, read at call time so a test (or
5
- * a `hacklab` invoked from a script) can set it per run. Unset, empty, `0` and
6
- * `false` are off; anything else (typically `1`) is on, so `HACKLAB_DEV=0`
7
- * never turns something on.
8
- *
9
- * It's an env var rather than a filesystem guess: a deployed copy of the repo
10
- * tree (nixpacks-style, `/app`) looks exactly like a source checkout on disk,
11
- * so no path heuristic can tell a developer apart from a deploy.
12
- */
13
- function devMode() {
14
- const raw = process.env.HACKLAB_DEV;
15
- if (!raw)
16
- return false;
17
- return raw !== '0' && raw !== 'false';
18
- }
19
- export async function whoami() {
20
- const session = await loadSession();
21
- if (!session) {
22
- error('not logged in');
23
- info(`run ${dim('hacklab login')} to authenticate`);
24
- process.exit(1);
25
- }
26
- const server = resolveAppUrl(session);
27
- const loginServer = session.appUrl.replace(/\/$/, '');
28
- success(session.handle ? `@${session.handle}` : session.email);
29
- if (session.handle)
30
- info(session.email);
31
- // Production is the default — for users, naming it is noise, and only a
32
- // local/custom backend is worth calling out. Developers opt in with
33
- // HACKLAB_DEV=1 to always see which backend they're talking to, production
34
- // included.
35
- if (envNameForUrl(server) !== 'production' || devMode())
36
- info(server);
37
- if (server !== loginServer) {
38
- info(dim(`logged in against ${loginServer}`));
39
- }
40
- }
41
- //# sourceMappingURL=whoami.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEpD;;;;;;;;;GASG;AACH,SAAS,OAAO;IACd,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;IACnC,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAA;IACtB,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,OAAO,CAAA;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAA;IAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,KAAK,CAAC,eAAe,CAAC,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAA;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IACrC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAErD,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACvC,wEAAwE;IACxE,oEAAoE;IACpE,2EAA2E;IAC3E,YAAY;IACZ,IAAI,aAAa,CAAC,MAAM,CAAC,KAAK,YAAY,IAAI,OAAO,EAAE;QAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACrE,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,qBAAqB,WAAW,EAAE,CAAC,CAAC,CAAA;IAC/C,CAAC;AACH,CAAC"}
package/dist/config.d.ts DELETED
@@ -1,78 +0,0 @@
1
- /**
2
- * What the OS-native background jobs were last installed with — written by
3
- * daily-sync.ts on a successful install, cleared on uninstall. `command`
4
- * fingerprints the scheduled `node <script>` pair plus the template generation
5
- * that produced the jobs, so a routine run can tell a working schedule from one
6
- * worth replacing; hour/minute pin the daily slot so a reinstall doesn't re-roll
7
- * it. Opaque here: daily-sync.ts owns the format.
8
- */
9
- export type DailySyncRecord = {
10
- command: string;
11
- hour?: number;
12
- minute?: number;
13
- /** False when the scheduler accepted the daily job but refused the minutely
14
- * tick (a Windows policy cap), so a later run doesn't read that machine as a
15
- * half-install and reinstall on every scan. */
16
- tick?: boolean;
17
- };
18
- export type HacklabConfig = {
19
- cursorApiKey?: string;
20
- cursorEmail?: string;
21
- dailySync?: DailySyncRecord;
22
- /**
23
- * Consent for syncing supported local harness conversations: 'none' |
24
- * 'stats' | 'full'. A positive answer also needs the current source scope
25
- * version — see prompt-consent.ts. An unset value never means yes.
26
- */
27
- promptSync?: string;
28
- promptSyncVersion?: number;
29
- /**
30
- * The obsolete one-off prompt-stats consent. Declared only so
31
- * `savePromptSync` can delete it: it answered a narrower question (a scan
32
- * uploaded once a day) than `promptSync` asks, so it never carries over.
33
- */
34
- promptStatsConsent?: string;
35
- };
36
- /** Where a resolved credential came from, so `config` can show what actually wins. */
37
- export type CursorAuthSource = 'env' | 'config' | 'none';
38
- export type CursorAuth = {
39
- apiKey?: string;
40
- email?: string;
41
- apiKeySource: CursorAuthSource;
42
- emailSource: CursorAuthSource;
43
- };
44
- /**
45
- * Resolve the Cursor credentials from the three places a user can set them,
46
- * highest priority first:
47
- *
48
- * 1. `--cursor-api-key` / `--cursor-email`
49
- * 2. `CURSOR_API_KEY` / `CURSOR_EMAIL` in the environment
50
- * 3. `~/.hacklab/config.json` (written by `hacklab config cursor-api-key`)
51
- *
52
- * (1) and (2) collapse into one check here because index.ts parks the flags in
53
- * those same env vars before any command runs — the same trick `--env` uses for
54
- * HACKLAB_APP_URL. A flag therefore beats an inherited env var for free, and
55
- * `apiKeySource: 'env'` covers both.
56
- *
57
- * The email matters as much as the key: it scopes a *team* key to one member.
58
- * Without it, Cursor's filtered-usage-events endpoint returns every teammate's
59
- * events and we'd credit the whole team's tokens to one profile.
60
- */
61
- export declare function resolveCursorAuth(): Promise<CursorAuth>;
62
- export declare function loadConfig(): Promise<HacklabConfig>;
63
- export declare function saveConfig(config: HacklabConfig): Promise<void>;
64
- /**
65
- * Read-modify-write the config file for background callers that must not lose
66
- * the rest of it. Unlike `loadConfig`, which flattens every read failure to
67
- * `{}`, this refuses to write when the file exists but can't be parsed —
68
- * spreading `{}` over an unreadable config would silently drop the user's cursor
69
- * key and prompt-sync consent, and nothing here is worth that.
70
- *
71
- * `mutate` returns the config to write, or null for "nothing to change" (no
72
- * write at all — a background job shouldn't rewrite config.json for nothing).
73
- * Never throws: resolves true when the config reflects the mutation, false when
74
- * the write was refused or failed, so the caller can react to not being
75
- * remembered.
76
- */
77
- export declare function updateConfig(mutate: (config: HacklabConfig) => HacklabConfig | null): Promise<boolean>;
78
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;mDAE+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAID,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,gBAAgB,CAAA;IAC9B,WAAW,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,CAgB7D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAOzD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,aAAa,GAAG,IAAI,GACtD,OAAO,CAAC,OAAO,CAAC,CA6BlB"}