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.
- package/README.md +23 -430
- package/dist/index.js +132 -23
- package/package.json +20 -42
- package/LICENSE +0 -21
- package/dist/agent-handoff.d.ts +0 -51
- package/dist/agent-handoff.d.ts.map +0 -1
- package/dist/agent-handoff.js +0 -91
- package/dist/agent-handoff.js.map +0 -1
- package/dist/api-client.d.ts +0 -18
- package/dist/api-client.d.ts.map +0 -1
- package/dist/api-client.js +0 -40
- package/dist/api-client.js.map +0 -1
- package/dist/belt.d.ts +0 -25
- package/dist/belt.d.ts.map +0 -1
- package/dist/belt.js +0 -113
- package/dist/belt.js.map +0 -1
- package/dist/card.d.ts +0 -66
- package/dist/card.d.ts.map +0 -1
- package/dist/card.js +0 -151
- package/dist/card.js.map +0 -1
- package/dist/cli.d.ts +0 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -238
- package/dist/cli.js.map +0 -1
- package/dist/commands/book.d.ts +0 -14
- package/dist/commands/book.d.ts.map +0 -1
- package/dist/commands/book.js +0 -90
- package/dist/commands/book.js.map +0 -1
- package/dist/commands/chat.d.ts +0 -36
- package/dist/commands/chat.d.ts.map +0 -1
- package/dist/commands/chat.js +0 -642
- package/dist/commands/chat.js.map +0 -1
- package/dist/commands/config.d.ts +0 -2
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js +0 -84
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/daemon.d.ts +0 -19
- package/dist/commands/daemon.d.ts.map +0 -1
- package/dist/commands/daemon.js +0 -72
- package/dist/commands/daemon.js.map +0 -1
- package/dist/commands/drop.d.ts +0 -12
- package/dist/commands/drop.d.ts.map +0 -1
- package/dist/commands/drop.js +0 -103
- package/dist/commands/drop.js.map +0 -1
- package/dist/commands/drops.d.ts +0 -9
- package/dist/commands/drops.d.ts.map +0 -1
- package/dist/commands/drops.js +0 -96
- package/dist/commands/drops.js.map +0 -1
- package/dist/commands/essay.d.ts +0 -40
- package/dist/commands/essay.d.ts.map +0 -1
- package/dist/commands/essay.js +0 -651
- package/dist/commands/essay.js.map +0 -1
- package/dist/commands/hackathon.d.ts +0 -2
- package/dist/commands/hackathon.d.ts.map +0 -1
- package/dist/commands/hackathon.js +0 -893
- package/dist/commands/hackathon.js.map +0 -1
- package/dist/commands/hacker.d.ts +0 -2
- package/dist/commands/hacker.d.ts.map +0 -1
- package/dist/commands/hacker.js +0 -87
- package/dist/commands/hacker.js.map +0 -1
- package/dist/commands/jobs.d.ts +0 -18
- package/dist/commands/jobs.d.ts.map +0 -1
- package/dist/commands/jobs.js +0 -138
- package/dist/commands/jobs.js.map +0 -1
- package/dist/commands/keys.d.ts +0 -2
- package/dist/commands/keys.d.ts.map +0 -1
- package/dist/commands/keys.js +0 -138
- package/dist/commands/keys.js.map +0 -1
- package/dist/commands/login.d.ts +0 -83
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js +0 -236
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.d.ts +0 -2
- package/dist/commands/logout.d.ts.map +0 -1
- package/dist/commands/logout.js +0 -22
- package/dist/commands/logout.js.map +0 -1
- package/dist/commands/org-jobs.d.ts +0 -50
- package/dist/commands/org-jobs.d.ts.map +0 -1
- package/dist/commands/org-jobs.js +0 -383
- package/dist/commands/org-jobs.js.map +0 -1
- package/dist/commands/org.d.ts +0 -67
- package/dist/commands/org.d.ts.map +0 -1
- package/dist/commands/org.js +0 -1244
- package/dist/commands/org.js.map +0 -1
- package/dist/commands/ping.d.ts +0 -2
- package/dist/commands/ping.d.ts.map +0 -1
- package/dist/commands/ping.js +0 -50
- package/dist/commands/ping.js.map +0 -1
- package/dist/commands/profile.d.ts +0 -72
- package/dist/commands/profile.d.ts.map +0 -1
- package/dist/commands/profile.js +0 -672
- package/dist/commands/profile.js.map +0 -1
- package/dist/commands/project.d.ts +0 -2
- package/dist/commands/project.d.ts.map +0 -1
- package/dist/commands/project.js +0 -583
- package/dist/commands/project.js.map +0 -1
- package/dist/commands/referral.d.ts +0 -6
- package/dist/commands/referral.d.ts.map +0 -1
- package/dist/commands/referral.js +0 -93
- package/dist/commands/referral.js.map +0 -1
- package/dist/commands/rtfm.d.ts +0 -9
- package/dist/commands/rtfm.d.ts.map +0 -1
- package/dist/commands/rtfm.js +0 -114
- package/dist/commands/rtfm.js.map +0 -1
- package/dist/commands/scan.d.ts +0 -13
- package/dist/commands/scan.d.ts.map +0 -1
- package/dist/commands/scan.js +0 -286
- package/dist/commands/scan.js.map +0 -1
- package/dist/commands/scout.d.ts +0 -18
- package/dist/commands/scout.d.ts.map +0 -1
- package/dist/commands/scout.js +0 -232
- package/dist/commands/scout.js.map +0 -1
- package/dist/commands/setup-rail.d.ts +0 -58
- package/dist/commands/setup-rail.d.ts.map +0 -1
- package/dist/commands/setup-rail.js +0 -135
- package/dist/commands/setup-rail.js.map +0 -1
- package/dist/commands/setup.d.ts +0 -29
- package/dist/commands/setup.d.ts.map +0 -1
- package/dist/commands/setup.js +0 -442
- package/dist/commands/setup.js.map +0 -1
- package/dist/commands/sync.d.ts +0 -9
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js +0 -345
- package/dist/commands/sync.js.map +0 -1
- package/dist/commands/update.d.ts +0 -2
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js +0 -92
- package/dist/commands/update.js.map +0 -1
- package/dist/commands/whoami.d.ts +0 -2
- package/dist/commands/whoami.d.ts.map +0 -1
- package/dist/commands/whoami.js +0 -41
- package/dist/commands/whoami.js.map +0 -1
- package/dist/config.d.ts +0 -78
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -93
- package/dist/config.js.map +0 -1
- package/dist/daily-sync.d.ts +0 -150
- package/dist/daily-sync.d.ts.map +0 -1
- package/dist/daily-sync.js +0 -665
- package/dist/daily-sync.js.map +0 -1
- package/dist/dossier.d.ts +0 -73
- package/dist/dossier.d.ts.map +0 -1
- package/dist/dossier.js +0 -141
- package/dist/dossier.js.map +0 -1
- package/dist/field-normalize.d.ts +0 -4
- package/dist/field-normalize.d.ts.map +0 -1
- package/dist/field-normalize.js +0 -8
- package/dist/field-normalize.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/job-fields.d.ts +0 -47
- package/dist/job-fields.d.ts.map +0 -1
- package/dist/job-fields.js +0 -148
- package/dist/job-fields.js.map +0 -1
- package/dist/machine.d.ts +0 -15
- package/dist/machine.d.ts.map +0 -1
- package/dist/machine.js +0 -64
- package/dist/machine.js.map +0 -1
- package/dist/org-fields.d.ts +0 -57
- package/dist/org-fields.d.ts.map +0 -1
- package/dist/org-fields.js +0 -167
- package/dist/org-fields.js.map +0 -1
- package/dist/posthog.d.ts +0 -38
- package/dist/posthog.d.ts.map +0 -1
- package/dist/posthog.js +0 -224
- package/dist/posthog.js.map +0 -1
- package/dist/project-fields.d.ts +0 -40
- package/dist/project-fields.d.ts.map +0 -1
- package/dist/project-fields.js +0 -79
- package/dist/project-fields.js.map +0 -1
- package/dist/prompt-consent.d.ts +0 -73
- package/dist/prompt-consent.d.ts.map +0 -1
- package/dist/prompt-consent.js +0 -191
- package/dist/prompt-consent.js.map +0 -1
- package/dist/prompt-stats.d.ts +0 -226
- package/dist/prompt-stats.d.ts.map +0 -1
- package/dist/prompt-stats.js +0 -561
- package/dist/prompt-stats.js.map +0 -1
- package/dist/referral.d.ts +0 -14
- package/dist/referral.d.ts.map +0 -1
- package/dist/referral.js +0 -28
- package/dist/referral.js.map +0 -1
- package/dist/registry.d.ts +0 -15
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -180
- package/dist/registry.js.map +0 -1
- package/dist/resolve-command.d.ts +0 -20
- package/dist/resolve-command.d.ts.map +0 -1
- package/dist/resolve-command.js +0 -21
- package/dist/resolve-command.js.map +0 -1
- package/dist/scanners/antigravity.d.ts +0 -41
- package/dist/scanners/antigravity.d.ts.map +0 -1
- package/dist/scanners/antigravity.js +0 -210
- package/dist/scanners/antigravity.js.map +0 -1
- package/dist/scanners/github-copilot-telemetry.d.ts +0 -23
- package/dist/scanners/github-copilot-telemetry.d.ts.map +0 -1
- package/dist/scanners/github-copilot-telemetry.js +0 -220
- package/dist/scanners/github-copilot-telemetry.js.map +0 -1
- package/dist/scanners/github-copilot.d.ts +0 -68
- package/dist/scanners/github-copilot.d.ts.map +0 -1
- package/dist/scanners/github-copilot.js +0 -262
- package/dist/scanners/github-copilot.js.map +0 -1
- package/dist/scanners/incremental.d.ts +0 -282
- package/dist/scanners/incremental.d.ts.map +0 -1
- package/dist/scanners/incremental.js +0 -788
- package/dist/scanners/incremental.js.map +0 -1
- package/dist/scanners/index.d.ts +0 -116
- package/dist/scanners/index.d.ts.map +0 -1
- package/dist/scanners/index.js +0 -726
- package/dist/scanners/index.js.map +0 -1
- package/dist/scanners/sqlite.d.ts +0 -18
- package/dist/scanners/sqlite.d.ts.map +0 -1
- package/dist/scanners/sqlite.js +0 -63
- package/dist/scanners/sqlite.js.map +0 -1
- package/dist/scanners/util.d.ts +0 -112
- package/dist/scanners/util.d.ts.map +0 -1
- package/dist/scanners/util.js +0 -167
- package/dist/scanners/util.js.map +0 -1
- package/dist/session.d.ts +0 -106
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -191
- package/dist/session.js.map +0 -1
- package/dist/share-card-colors.d.ts +0 -19
- package/dist/share-card-colors.d.ts.map +0 -1
- package/dist/share-card-colors.js +0 -36
- package/dist/share-card-colors.js.map +0 -1
- package/dist/share-card.d.ts +0 -32
- package/dist/share-card.d.ts.map +0 -1
- package/dist/share-card.js +0 -420
- package/dist/share-card.js.map +0 -1
- package/dist/share.d.ts +0 -17
- package/dist/share.d.ts.map +0 -1
- package/dist/share.js +0 -77
- package/dist/share.js.map +0 -1
- package/dist/sync.d.ts +0 -100
- package/dist/sync.d.ts.map +0 -1
- package/dist/sync.js +0 -304
- package/dist/sync.js.map +0 -1
- package/dist/ui.d.ts +0 -33
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js +0 -127
- package/dist/ui.js.map +0 -1
- package/dist/utils/npmGlobal.d.ts +0 -30
- package/dist/utils/npmGlobal.d.ts.map +0 -1
- package/dist/utils/npmGlobal.js +0 -69
- package/dist/utils/npmGlobal.js.map +0 -1
- package/dist/utils/openBrowser.d.ts +0 -14
- package/dist/utils/openBrowser.d.ts.map +0 -1
- package/dist/utils/openBrowser.js +0 -47
- package/dist/utils/openBrowser.js.map +0 -1
- package/dist/utils/updateCheck.d.ts +0 -16
- package/dist/utils/updateCheck.d.ts.map +0 -1
- package/dist/utils/updateCheck.js +0 -111
- package/dist/utils/updateCheck.js.map +0 -1
- package/dist/utils/waitForEnter.d.ts +0 -12
- package/dist/utils/waitForEnter.d.ts.map +0 -1
- package/dist/utils/waitForEnter.js +0 -43
- package/dist/utils/waitForEnter.js.map +0 -1
package/dist/sync.d.ts.map
DELETED
|
@@ -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"}
|
package/dist/utils/npmGlobal.js
DELETED
|
@@ -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"}
|