hacklab 0.22.2 → 26.921.1

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 +23 -430
  2. package/dist/index.js +132 -23
  3. package/package.json +20 -42
  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 -32
  229. package/dist/share-card.d.ts.map +0 -1
  230. package/dist/share-card.js +0 -420
  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 -77
  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 +0,0 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
package/dist/sync.js DELETED
@@ -1,304 +0,0 @@
1
- import { getMachineIdentity } from './machine.js';
2
- import { PROMPT_SCANNER_VERSION, promptStatsPayload, scanPromptStats, } from './prompt-stats.js';
3
- import { stageFullScan } from './scanners/incremental.js';
4
- import { collectToolScans, formatBytes, formatTokens, mergeToolScans, } from './scanners/index.js';
5
- import { getSessionExpiresAt, resolveAppUrl, saveSession, } from './session.js';
6
- import { dim } from './ui.js';
7
- // Token scanning lives in one place — the scanners/ module (used by both `scan`
8
- // and `sync`). This file is just the `sync` command's API layer: session
9
- // checks, the claim upload, and error formatting. Re-export the shared scan
10
- // helpers so existing importers don't have to reach into scanners/ directly.
11
- export { formatBytes, formatTokens };
12
- export const LOGIN_EXPIRED_MESSAGE = 'login expired. run hacklab login again';
13
- /**
14
- * A rejected upload, carrying the HTTP status and Retry-After. The minutely
15
- * tick needs to tell a 429 (back off, the server said so) from a 500 (retry
16
- * next minute); every other caller only ever reads `.message`, which is
17
- * unchanged from the plain Error this replaced.
18
- */
19
- export class SyncUploadError extends Error {
20
- status;
21
- retryAfter;
22
- constructor(message, status, retryAfter = null) {
23
- super(message);
24
- this.status = status;
25
- this.retryAfter = retryAfter;
26
- this.name = 'SyncUploadError';
27
- }
28
- }
29
- function buildApiUrl(session, path) {
30
- return `${resolveAppUrl(session)}${path}`;
31
- }
32
- function isLoopbackAppUrl(value) {
33
- try {
34
- const url = new URL(value);
35
- return (url.hostname === 'localhost' ||
36
- url.hostname === '127.0.0.1' ||
37
- url.hostname === '::1');
38
- }
39
- catch {
40
- return false;
41
- }
42
- }
43
- function getCauseMessage(err) {
44
- if (!(err instanceof Error))
45
- return null;
46
- const cause = err.cause;
47
- if (cause instanceof Error)
48
- return cause.message;
49
- if (typeof cause === 'object' && cause !== null && 'message' in cause) {
50
- const message = cause.message;
51
- return typeof message === 'string' ? message : null;
52
- }
53
- return err.message === 'fetch failed' ? null : err.message;
54
- }
55
- function formatFetchFailure(session, err) {
56
- const app = resolveAppUrl(session);
57
- const cause = getCauseMessage(err);
58
- const details = cause ? ` (${cause})` : '';
59
- if (isLoopbackAppUrl(app)) {
60
- return `could not reach ${app}${details}. start the web app or point ${dim('HACKLAB_APP_URL')} at a running backend and run ${dim('hacklab login')}`;
61
- }
62
- return `could not reach ${app}${details}. check ${dim('HACKLAB_APP_URL')} or run ${dim('hacklab login')} again`;
63
- }
64
- export async function fetchApi(session, path, init) {
65
- try {
66
- return await fetch(buildApiUrl(session, path), init);
67
- }
68
- catch (err) {
69
- throw new Error(formatFetchFailure(session, err));
70
- }
71
- }
72
- export async function checkSession(session) {
73
- let res;
74
- try {
75
- res = await fetchApi(session, '/api/xp', {
76
- headers: { Authorization: `Bearer ${session.token}` },
77
- });
78
- }
79
- catch (err) {
80
- return {
81
- status: 'failed',
82
- message: err instanceof Error ? err.message : String(err),
83
- };
84
- }
85
- if (res.status === 401)
86
- return { status: 'unauthorized' };
87
- if (res.status === 404) {
88
- const contentType = res.headers.get('content-type') ?? '';
89
- if (contentType.includes('application/json'))
90
- return { status: 'ok' };
91
- return {
92
- status: 'failed',
93
- message: `Hacklab API not found at ${resolveAppUrl(session)}. check ${dim('HACKLAB_APP_URL')} or run ${dim('hacklab login')} again`,
94
- };
95
- }
96
- if (res.status >= 500) {
97
- return {
98
- status: 'failed',
99
- message: `Hacklab API failed at ${resolveAppUrl(session)} (${res.status}). try again later`,
100
- };
101
- }
102
- return { status: 'ok' };
103
- }
104
- /**
105
- * Ask the server to mirror the user's pinned GitHub repos into their projects
106
- * (and drop ones that are no longer pinned/public). Best-effort and non-fatal —
107
- * returns null on any failure so a GitHub hiccup never fails `sync`.
108
- */
109
- export async function syncGithubRepos(session) {
110
- try {
111
- const res = await fetchApi(session, '/api/cli/github-sync', {
112
- method: 'POST',
113
- headers: { Authorization: `Bearer ${session.token}` },
114
- });
115
- if (!res.ok)
116
- return null;
117
- return (await res.json());
118
- }
119
- catch {
120
- return null;
121
- }
122
- }
123
- /** The harnesses the backend tallies, with explicit zeros so the payload shape
124
- * is stable regardless of which tools the scan actually found. */
125
- function toolTotalsRecord(scan) {
126
- return {
127
- claude_code: scan.toolTotals.claude_code ?? 0,
128
- codex: scan.toolTotals.codex ?? 0,
129
- cursor: scan.toolTotals.cursor ?? 0,
130
- openclaw: scan.toolTotals.openclaw ?? 0,
131
- hermes: scan.toolTotals.hermes ?? 0,
132
- opencode: scan.toolTotals.opencode ?? 0,
133
- grok: scan.toolTotals.grok ?? 0,
134
- github_copilot: scan.toolTotals.github_copilot ?? 0,
135
- antigravity: scan.toolTotals.antigravity ?? 0,
136
- };
137
- }
138
- /**
139
- * Upload a scan's token totals to the backend (the `/api/claim/sync` capsule).
140
- * The single place the upload payload is built and the response is checked, so
141
- * the `sync` command and the daily background job all push the exact same
142
- * shape. Throws LOGIN_EXPIRED_MESSAGE on 401 so callers can tell an expired
143
- * session apart from a transient failure. Pass `timeoutMs` to hard-cap a slow
144
- * upload; omit it for an unbounded one-shot.
145
- *
146
- * Tags the upload with this machine's stable id so the backend can sum usage
147
- * across the user's machines while keeping each machine's re-sync idempotent.
148
- */
149
- export async function uploadTokenScan(session, scan, opts = {}) {
150
- const { machineId, machineName } = await getMachineIdentity();
151
- const res = await fetchApi(session, '/api/claim/sync', {
152
- method: 'POST',
153
- headers: {
154
- 'Content-Type': 'application/json',
155
- Authorization: `Bearer ${session.token}`,
156
- // Manual `hacklab sync` counts as user activity; the automated daily job
157
- // (this same endpoint) does not. The
158
- // backend emits user_active only when this header is present, so the
159
- // shared payload stays identical otherwise.
160
- ...(opts.interactive ? { 'x-hacklab-interactive': '1' } : {}),
161
- },
162
- body: JSON.stringify({
163
- machineId,
164
- machineName,
165
- dailyTotals: scan.dailyTotals,
166
- toolTotals: toolTotalsRecord(scan),
167
- modelTotals: scan.modelTotals,
168
- // Which definition of "a prompt" produced the two blocks below. The
169
- // server drops prompt data from anything under 2, so this field is what
170
- // keeps it flowing — sent on every sync, tick and full scan alike, so
171
- // there is only ever one answer to "what built this payload".
172
- scannerVersion: PROMPT_SCANNER_VERSION,
173
- // Both blocks are absent unless consented — the backend's fields are
174
- // optional, so an opted-out sync carries token counts and nothing else.
175
- // `promptStats` rides on full scans (histogram, the exact tail of the
176
- // lengths past its axis, projects, and under the `full` tier the text
177
- // sample); `promptActivity` rides on ticks (session and per-day
178
- // metadata, no text ever).
179
- ...(opts.promptStats
180
- ? { promptStats: promptStatsPayload(opts.promptStats) }
181
- : {}),
182
- ...(scan.promptActivity ? { promptActivity: scan.promptActivity } : {}),
183
- }),
184
- ...(opts.timeoutMs ? { signal: AbortSignal.timeout(opts.timeoutMs) } : {}),
185
- });
186
- if (res.status === 401) {
187
- throw new SyncUploadError(LOGIN_EXPIRED_MESSAGE, 401);
188
- }
189
- if (!res.ok) {
190
- const data = await res.json().catch(() => null);
191
- throw new SyncUploadError(data?.error ??
192
- `sync failed (${res.status})`, res.status, res.headers.get('retry-after'));
193
- }
194
- return (await res.json());
195
- }
196
- // Refresh within the last week of the 30-day session window — frequent enough to
197
- // never lapse on a daily job, rare enough to barely touch the endpoint.
198
- const REFRESH_WHEN_WITHIN_MS = 7 * 24 * 60 * 60 * 1000;
199
- /**
200
- * Ask the backend to slide this session's expiry forward (token unchanged) and
201
- * persist the result. Returns the updated session, or null if the refresh failed
202
- * (e.g. the session already expired — that needs a fresh `hacklab login`).
203
- */
204
- export async function refreshSession(session) {
205
- let res;
206
- try {
207
- res = await fetchApi(session, '/api/cli/session/refresh', {
208
- method: 'POST',
209
- headers: { Authorization: `Bearer ${session.token}` },
210
- });
211
- }
212
- catch {
213
- return null;
214
- }
215
- if (!res.ok)
216
- return null;
217
- const data = (await res.json().catch(() => null));
218
- if (!data?.token || !data.expiresAt)
219
- return null;
220
- const updated = {
221
- ...session,
222
- token: data.token,
223
- expiresAt: data.expiresAt,
224
- savedAt: new Date().toISOString(),
225
- };
226
- await saveSession(updated);
227
- return updated;
228
- }
229
- /**
230
- * Proactively refresh the session when it's nearing expiry, so a long-running
231
- * daily background sync never lapses. A no-op (returns the session unchanged)
232
- * when there's plenty of time left or the refresh fails.
233
- */
234
- export async function ensureFreshSession(session) {
235
- const expiresAt = getSessionExpiresAt(session);
236
- if (!expiresAt)
237
- return session;
238
- if (expiresAt.getTime() - Date.now() > REFRESH_WHEN_WITHIN_MS)
239
- return session;
240
- return (await refreshSession(session)) ?? session;
241
- }
242
- export async function runSync(session, opts = {}) {
243
- const results = await collectToolScans();
244
- const scan = mergeToolScans(results);
245
- // Scanning transcripts is skipped entirely at the 'none' tier — an opted-out
246
- // user's conversations are never even read.
247
- const promptStats = await scanConsentedPromptStats(opts.promptSync);
248
- // Re-base the tick's incremental state on this scan before uploading — same
249
- // repair the daily job does, so a manual `hacklab sync` also clears any drift
250
- // (and refreshes the Cursor totals the tick can only carry over). It has to
251
- // come first because the rebuild is what works out which prompt rows are
252
- // still outstanding, and those ride along on this very upload: a machine with
253
- // no daemon has no tick to drain them.
254
- const staged = await stageFullScan(results, {
255
- scanned: promptStats?.activity ?? null,
256
- });
257
- const result = await uploadTokenScan(session, staged.promptActivity
258
- ? { ...scan, promptActivity: staged.promptActivity }
259
- : scan, { interactive: opts.interactive, promptStats });
260
- // Only now is any of it delivered. A throw above leaves the saved state
261
- // untouched, so the next run re-derives the same claim and resends it.
262
- await staged.commit();
263
- const totals = toolTotalsRecord(scan);
264
- const allEntries = scan.dailyTotals;
265
- const messagesTotal = allEntries.reduce((s, e) => s + (e.messages ?? 0), 0);
266
- const models = Object.entries(scan.modelTotals)
267
- .map(([name, tokens]) => ({ name, tokens }))
268
- .sort((a, b) => b.tokens - a.tokens);
269
- return {
270
- claudeTotal: totals.claude_code,
271
- codexTotal: totals.codex,
272
- cursorTotal: totals.cursor,
273
- openclawTotal: totals.openclaw,
274
- hermesTotal: totals.hermes,
275
- opencodeTotal: totals.opencode,
276
- grokTotal: totals.grok,
277
- copilotTotal: totals.github_copilot,
278
- antigravityTotal: totals.antigravity,
279
- messagesTotal,
280
- allEntries,
281
- cursorStats: scan.cursorStats,
282
- result,
283
- models,
284
- cursorScanStatus: scan.cursorScanStatus,
285
- promptStats,
286
- };
287
- }
288
- /**
289
- * Scan the local transcripts for the given consent tier, or return null when
290
- * there's no consent (or nothing to find). Never throws: prompt stats are an
291
- * extra on top of the token sync, so a scan failure must not cost the user
292
- * their token upload.
293
- */
294
- export async function scanConsentedPromptStats(tier) {
295
- if (!tier || tier === 'none')
296
- return null;
297
- try {
298
- return await scanPromptStats({ includeSample: tier === 'full' });
299
- }
300
- catch {
301
- return null;
302
- }
303
- }
304
- //# sourceMappingURL=sync.js.map
package/dist/sync.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
package/dist/ui.d.ts DELETED
@@ -1,33 +0,0 @@
1
- export declare const dim: import("chalk").ChalkInstance;
2
- export declare const bold: import("chalk").ChalkInstance;
3
- export declare const green: import("chalk").ChalkInstance;
4
- export declare const gray: import("chalk").ChalkInstance;
5
- export declare const red: import("chalk").ChalkInstance;
6
- export declare const yellow: import("chalk").ChalkInstance;
7
- export declare const white: import("chalk").ChalkInstance;
8
- export declare const linkBlue: import("chalk").ChalkInstance;
9
- /** Clickable OSC-8 hyperlink. Visible text is the URL so a copy still works. */
10
- export declare function link(url: string): string;
11
- export declare const mint: import("chalk").ChalkInstance;
12
- /**
13
- * Colour a string in the terminal colour for the rank at `level`. A null/unknown
14
- * level (e.g. older messages without a sender level) falls back to plain bold.
15
- */
16
- export declare function rankColor(level: number | null | undefined, text: string): string;
17
- /** Display columns a plain string occupies (ANSI stripped, CJK/emoji aware). */
18
- export declare function displayWidth(s: string): number;
19
- /**
20
- * Truncate a PLAIN string to at most `max` display columns, cutting on grapheme
21
- * boundaries (never mid-emoji / mid-surrogate) and adding a 1-column ellipsis
22
- * when anything was dropped. Must run before colorizing.
23
- */
24
- export declare function truncateToWidth(s: string, max: number): string;
25
- /** Right-pad a PLAIN string with spaces to exactly `width` display columns. */
26
- export declare function padEndTo(s: string, width: number): string;
27
- export declare function stripControl(s: string): string;
28
- export declare function banner(): void;
29
- export declare function success(msg: string): void;
30
- export declare function error(msg: string): void;
31
- export declare function info(msg: string): void;
32
- export declare function hint(msg: string): void;
33
- //# sourceMappingURL=ui.d.ts.map
package/dist/ui.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,GAAG,+BAAY,CAAA;AAC5B,eAAO,MAAM,IAAI,+BAAa,CAAA;AAC9B,eAAO,MAAM,KAAK,+BAAc,CAAA;AAGhC,eAAO,MAAM,IAAI,+BAAa,CAAA;AAC9B,eAAO,MAAM,GAAG,+BAAY,CAAA;AAC5B,eAAO,MAAM,MAAM,+BAAe,CAAA;AAClC,eAAO,MAAM,KAAK,+BAAoB,CAAA;AAGtC,eAAO,MAAM,QAAQ,+BAAuB,CAAA;AAE5C,gFAAgF;AAChF,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExC;AAID,eAAO,MAAM,IAAI,+BAAuB,CAAA;AAwBxC;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,GACX,MAAM,CAMR;AAcD,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAa9D;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAOD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED,wBAAgB,MAAM,SAIrB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,QAElC;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,QAEhC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,QAE/B;AAID,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,QAE/B"}
package/dist/ui.js DELETED
@@ -1,127 +0,0 @@
1
- import chalk from 'chalk';
2
- import stringWidth from 'string-width';
3
- import { getBeltColor } from './belt.js';
4
- export const dim = chalk.dim;
5
- export const bold = chalk.bold;
6
- export const green = chalk.green;
7
- // The colour clack paints its step rail. `setup` draws two blocks by hand
8
- // between clack widgets, and a gutter in any other colour reads as a seam.
9
- export const gray = chalk.gray;
10
- export const red = chalk.red;
11
- export const yellow = chalk.yellow;
12
- export const white = chalk.whiteBright;
13
- // GitHub's link blue. chalk degrades the hex to the nearest ANSI colour on
14
- // terminals without truecolor support.
15
- export const linkBlue = chalk.hex('#79b8ff');
16
- /** Clickable OSC-8 hyperlink. Visible text is the URL so a copy still works. */
17
- export function link(url) {
18
- return `\u001b]8;;${url}\u001b\\${linkBlue(url)}\u001b]8;;\u001b\\`;
19
- }
20
- // Phosphor Mint (DESIGN.md --primary #82F5C6): the "active and alive" signal —
21
- // the open-to-work status dot and lit activity cells. chalk degrades the hex on
22
- // terminals without truecolor.
23
- export const mint = chalk.hex('#82F5C6');
24
- // Map a belt colour to the nearest standard ANSI terminal colour name. We use
25
- // chalk's *named* colours (not the hex values from share-card-colors) on
26
- // purpose: named colours resolve to each viewer's own terminal theme, so the
27
- // rank hue approximates our brand palette while still respecting individual
28
- // colour configs. ANSI has no orange/lime/pink, so we pick the closest hue and
29
- // lean on the bright variants to keep all eleven belts visually distinct.
30
- const BELT_ANSI = {
31
- white: chalk.white,
32
- orange: chalk.yellow,
33
- red: chalk.red,
34
- blue: chalk.blue,
35
- cyan: chalk.cyan,
36
- yellow: chalk.yellowBright,
37
- lime: chalk.greenBright,
38
- green: chalk.green,
39
- pink: chalk.magentaBright,
40
- purple: chalk.magenta,
41
- // Black belt is rendered as white (#FFFFFF) in our palette; a literal black
42
- // would be invisible on a dark terminal, so bright white reads as the top rank.
43
- black: chalk.whiteBright,
44
- };
45
- /**
46
- * Colour a string in the terminal colour for the rank at `level`. A null/unknown
47
- * level (e.g. older messages without a sender level) falls back to plain bold.
48
- */
49
- export function rankColor(level, text) {
50
- // Guard non-finite levels too (NaN/Infinity): `== null` misses NaN, and
51
- // getBeltColor(NaN) would silently fall through to white. Plain bold is the
52
- // honest fallback for an unknown rank.
53
- if (level == null || !Number.isFinite(level))
54
- return bold(text);
55
- return BELT_ANSI[getBeltColor(level)].bold(text);
56
- }
57
- // --- Display-width primitives ----------------------------------------------
58
- // The hacker card has a fixed column budget, and its content is user-supplied
59
- // (handles, bios) that can contain CJK, emoji, and ANSI. `.length` is wrong for
60
- // all three. Render order everywhere is: strip → truncate → measure → colorize
61
- // LAST — colorizing before truncation would slice an ANSI escape mid-byte, and
62
- // stringWidth counts ANSI as zero so a coloured string would measure short and
63
- // truncate into corruption. These helpers therefore operate on PLAIN text.
64
- // Ambiguous-width characters (⬤, box-drawing) count as 1 column — pinned per
65
- // DESIGN.md so the card's rules and content agree with a standard terminal.
66
- const WIDTH_OPTS = { ambiguousIsNarrow: true };
67
- /** Display columns a plain string occupies (ANSI stripped, CJK/emoji aware). */
68
- export function displayWidth(s) {
69
- return stringWidth(s, WIDTH_OPTS);
70
- }
71
- const graphemeSegmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
72
- /**
73
- * Truncate a PLAIN string to at most `max` display columns, cutting on grapheme
74
- * boundaries (never mid-emoji / mid-surrogate) and adding a 1-column ellipsis
75
- * when anything was dropped. Must run before colorizing.
76
- */
77
- export function truncateToWidth(s, max) {
78
- if (max <= 0)
79
- return '';
80
- if (displayWidth(s) <= max)
81
- return s;
82
- const budget = max - 1; // reserve one column for the … ellipsis
83
- let out = '';
84
- let width = 0;
85
- for (const { segment } of graphemeSegmenter.segment(s)) {
86
- const w = displayWidth(segment);
87
- if (width + w > budget)
88
- break;
89
- out += segment;
90
- width += w;
91
- }
92
- return `${out}…`;
93
- }
94
- /** Right-pad a PLAIN string with spaces to exactly `width` display columns. */
95
- export function padEndTo(s, width) {
96
- const gap = width - displayWidth(s);
97
- return gap > 0 ? s + ' '.repeat(gap) : s;
98
- }
99
- // Strip C0 control characters + DEL from untrusted text before printing it to
100
- // the terminal. Without this, a hacker could embed ANSI escape sequences in a
101
- // handle, bio, message, or any user-supplied field to clear/garble or hijack
102
- // any viewer's terminal. Lives here (not in a command module) so every renderer
103
- // — chat, the hacker card — can reach it without a circular import.
104
- export function stripControl(s) {
105
- // biome-ignore lint/suspicious/noControlCharactersInRegex: intentionally matching control chars to remove them
106
- return s.replace(/[\x00-\x1f\x7f]/g, '');
107
- }
108
- export function banner() {
109
- console.log('');
110
- console.log(bold(' ☠︎ hacklab'));
111
- console.log(dim(' information wants to be free'));
112
- }
113
- export function success(msg) {
114
- console.log(green(' ✓ ') + msg);
115
- }
116
- export function error(msg) {
117
- console.error(red(' ✗ ') + msg);
118
- }
119
- export function info(msg) {
120
- console.log(dim(' → ') + msg);
121
- }
122
- // Like info(), but on stderr. For companion hints printed alongside an error()
123
- // so that `--json` stdout stays pure (the envelope and nothing else).
124
- export function hint(msg) {
125
- console.error(dim(' → ') + msg);
126
- }
127
- //# sourceMappingURL=ui.js.map
package/dist/ui.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
@@ -1,30 +0,0 @@
1
- import { type SpawnSyncReturns } from 'node:child_process';
2
- /**
3
- * npm's executable name. On Windows npm is a `.cmd` shim, and recent Node
4
- * refuses to spawn `.cmd`/`.bat` without a shell, so callers pass `shell: true`
5
- * on win32 (see {@link runNpm}).
6
- */
7
- export declare const NPM_BIN: string;
8
- /**
9
- * Run npm with fixed (never user-supplied) args. `capture` pipes stdout/stderr
10
- * back as strings; otherwise the child inherits the terminal so npm's own
11
- * progress shows through. `shell: true` on Windows is required to launch the
12
- * `.cmd` shim; the args here are all literals, so there's nothing to escape.
13
- */
14
- export declare function runNpm(args: string[], opts?: {
15
- capture?: boolean;
16
- }): SpawnSyncReturns<string>;
17
- /** The directory npm would drop a global package into (`npm root -g`), or ''. */
18
- export declare function npmGlobalRoot(): string;
19
- /**
20
- * Walk up from `p` to the nearest ancestor that exists on disk. We can't test
21
- * writability of a directory npm hasn't created yet (`…/lib/node_modules`
22
- * frequently doesn't exist), so we check the closest thing that does — mkdir
23
- * succeeds iff that ancestor is writable.
24
- */
25
- export declare function firstExistingAncestor(p: string): string;
26
- /** Can the current user create/write inside `dir` (probing its nearest existing ancestor)? */
27
- export declare function isWritable(dir: string): boolean;
28
- /** The user-owned prefix we reconfigure npm to when the system one is read-only. */
29
- export declare function userNpmPrefix(): string;
30
- //# sourceMappingURL=npmGlobal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"npmGlobal.d.ts","sourceRoot":"","sources":["../../src/utils/npmGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAa,MAAM,oBAAoB,CAAA;AAarE;;;;GAIG;AACH,eAAO,MAAM,OAAO,QAAmD,CAAA;AAEvE;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,gBAAgB,CAAC,MAAM,CAAC,CAM1B;AAED,iFAAiF;AACjF,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAS/C;AAED,oFAAoF;AACpF,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
@@ -1,69 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { accessSync, constants, existsSync } from 'node:fs';
3
- import { homedir } from 'node:os';
4
- import { dirname, join } from 'node:path';
5
- // Shared plumbing for the two places that shell out to `npm i -g hacklab`: the
6
- // `hacklab update` command and (conceptually) the curl|sh installer. The point
7
- // of the H1 approach is to never let npm's raw EACCES stack trace reach the
8
- // user: probe whether npm's global folder is writable up front, and if it isn't,
9
- // reconfigure npm to a user-owned prefix (npm's own documented remedy) instead
10
- // of escalating to sudo. That fix is persistent, so every future `npm i -g`
11
- // works too — which is the whole reason the update nag can safely point here.
12
- /**
13
- * npm's executable name. On Windows npm is a `.cmd` shim, and recent Node
14
- * refuses to spawn `.cmd`/`.bat` without a shell, so callers pass `shell: true`
15
- * on win32 (see {@link runNpm}).
16
- */
17
- export const NPM_BIN = process.platform === 'win32' ? 'npm.cmd' : 'npm';
18
- /**
19
- * Run npm with fixed (never user-supplied) args. `capture` pipes stdout/stderr
20
- * back as strings; otherwise the child inherits the terminal so npm's own
21
- * progress shows through. `shell: true` on Windows is required to launch the
22
- * `.cmd` shim; the args here are all literals, so there's nothing to escape.
23
- */
24
- export function runNpm(args, opts = {}) {
25
- return spawnSync(NPM_BIN, args, {
26
- stdio: opts.capture ? ['ignore', 'pipe', 'pipe'] : 'inherit',
27
- encoding: 'utf8',
28
- shell: process.platform === 'win32',
29
- });
30
- }
31
- /** The directory npm would drop a global package into (`npm root -g`), or ''. */
32
- export function npmGlobalRoot() {
33
- const res = runNpm(['root', '-g'], { capture: true });
34
- return res.status === 0 && res.stdout ? res.stdout.trim() : '';
35
- }
36
- /**
37
- * Walk up from `p` to the nearest ancestor that exists on disk. We can't test
38
- * writability of a directory npm hasn't created yet (`…/lib/node_modules`
39
- * frequently doesn't exist), so we check the closest thing that does — mkdir
40
- * succeeds iff that ancestor is writable.
41
- */
42
- export function firstExistingAncestor(p) {
43
- let d = p;
44
- while (d && !existsSync(d)) {
45
- const parent = dirname(d);
46
- if (parent === d)
47
- break; // hit the filesystem root
48
- d = parent;
49
- }
50
- return d;
51
- }
52
- /** Can the current user create/write inside `dir` (probing its nearest existing ancestor)? */
53
- export function isWritable(dir) {
54
- const target = firstExistingAncestor(dir);
55
- if (!target)
56
- return false;
57
- try {
58
- accessSync(target, constants.W_OK);
59
- return true;
60
- }
61
- catch {
62
- return false;
63
- }
64
- }
65
- /** The user-owned prefix we reconfigure npm to when the system one is read-only. */
66
- export function userNpmPrefix() {
67
- return join(homedir(), '.npm-global');
68
- }
69
- //# sourceMappingURL=npmGlobal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"npmGlobal.js","sourceRoot":"","sources":["../../src/utils/npmGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,iFAAiF;AACjF,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;AAEvE;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CACpB,IAAc,EACd,OAA8B,EAAE;IAEhC,OAAO,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QAC9B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAC5D,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;KACpC,CAAC,CAAA;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAS;IAC7C,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACzB,IAAI,MAAM,KAAK,CAAC;YAAE,MAAK,CAAC,0BAA0B;QAClD,CAAC,GAAG,MAAM,CAAA;IACZ,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACzB,IAAI,CAAC;QACH,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;QAClC,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAA;AACvC,CAAC"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Best-effort: open `url` in the user's default browser. Resolves true if the
3
- * opener launched, false otherwise (e.g. a headless host with no `xdg-open`).
4
- *
5
- * Critically, this must never crash the process. A missing opener binary is
6
- * reported by `spawn` as an asynchronous `'error'` event — NOT a thrown
7
- * exception — so a try/catch alone doesn't catch it, and with no listener Node
8
- * escalates it to a fatal unhandled error. On a headless box that would kill the
9
- * whole login flow right after we've printed the URL to visit manually.
10
- * We listen for `'error'` (failure) and `'spawn'` (success) so exactly one
11
- * settles the promise and the ENOENT is swallowed.
12
- */
13
- export declare function openBrowser(url: string): Promise<boolean>;
14
- //# sourceMappingURL=openBrowser.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"openBrowser.d.ts","sourceRoot":"","sources":["../../src/utils/openBrowser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA+B/D"}