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/commands/sync.js
DELETED
|
@@ -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 +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"}
|
package/dist/commands/update.js
DELETED
|
@@ -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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAmBA,wBAAsB,MAAM,kBAsB3B"}
|
package/dist/commands/whoami.js
DELETED
|
@@ -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
|
package/dist/config.d.ts.map
DELETED
|
@@ -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"}
|