hacklab 0.0.1 → 0.3.0
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 +48 -8
- package/bin/ddd +19 -0
- package/dist/commands/brag.d.ts +3 -6
- package/dist/commands/brag.d.ts.map +1 -1
- package/dist/commands/brag.js +68 -299
- package/dist/commands/brag.js.map +1 -1
- package/dist/commands/claim.d.ts +2 -0
- package/dist/commands/claim.d.ts.map +1 -0
- package/dist/commands/claim.js +534 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +48 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/dojo-init.d.ts +2 -0
- package/dist/commands/dojo-init.d.ts.map +1 -0
- package/dist/commands/dojo-init.js +75 -0
- package/dist/commands/dojo-init.js.map +1 -0
- package/dist/commands/drop.d.ts +2 -0
- package/dist/commands/drop.d.ts.map +1 -0
- package/dist/commands/drop.js +29 -0
- package/dist/commands/drop.js.map +1 -0
- package/dist/commands/exam.d.ts +5 -0
- package/dist/commands/exam.d.ts.map +1 -0
- package/dist/commands/exam.js +224 -0
- package/dist/commands/exam.js.map +1 -0
- package/dist/commands/login.d.ts +1 -14
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +70 -102
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/scan-profile.d.ts +33 -0
- package/dist/commands/scan-profile.d.ts.map +1 -0
- package/dist/commands/scan-profile.js +279 -0
- package/dist/commands/scan-profile.js.map +1 -0
- package/dist/commands/signup.d.ts +11 -0
- package/dist/commands/signup.d.ts.map +1 -0
- package/dist/commands/signup.js +242 -0
- package/dist/commands/signup.js.map +1 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +55 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/whoami.d.ts +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +10 -16
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +18 -0
- package/dist/config.js.map +1 -0
- package/dist/dd.d.ts +3 -0
- package/dist/dd.d.ts.map +1 -0
- package/dist/dd.js +28 -0
- package/dist/dd.js.map +1 -0
- package/dist/index.js +125 -134
- package/dist/index.js.map +1 -1
- package/dist/project-brag.d.ts +58 -0
- package/dist/project-brag.d.ts.map +1 -0
- package/dist/project-brag.js +270 -0
- package/dist/project-brag.js.map +1 -0
- package/dist/scanners/index.d.ts +24 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +543 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/util.d.ts +83 -0
- package/dist/scanners/util.d.ts.map +1 -0
- package/dist/scanners/util.js +129 -0
- package/dist/scanners/util.js.map +1 -0
- package/dist/session.d.ts +17 -12
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +46 -141
- package/dist/session.js.map +1 -1
- package/dist/share-card.d.ts +29 -0
- package/dist/share-card.d.ts.map +1 -0
- package/dist/share-card.js +401 -0
- package/dist/share-card.js.map +1 -0
- package/dist/sync.d.ts +64 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +805 -0
- package/dist/sync.js.map +1 -0
- package/dist/ui.d.ts +10 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +21 -0
- package/dist/ui.js.map +1 -0
- package/dist/utils/openBrowser.js.map +1 -1
- package/package.json +36 -27
- package/dist/api/client.d.ts +0 -118
- package/dist/api/client.d.ts.map +0 -1
- package/dist/api/client.js +0 -214
- package/dist/api/client.js.map +0 -1
- package/dist/commands/brag.utils.d.ts +0 -12
- package/dist/commands/brag.utils.d.ts.map +0 -1
- package/dist/commands/brag.utils.js +0 -43
- package/dist/commands/brag.utils.js.map +0 -1
- package/dist/commands/essay.d.ts +0 -18
- package/dist/commands/essay.d.ts.map +0 -1
- package/dist/commands/essay.js +0 -117
- package/dist/commands/essay.js.map +0 -1
- package/dist/commands/init.d.ts +0 -16
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -237
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/join.d.ts +0 -10
- package/dist/commands/join.d.ts.map +0 -1
- package/dist/commands/join.js +0 -314
- package/dist/commands/join.js.map +0 -1
- package/dist/commands/link.d.ts +0 -17
- package/dist/commands/link.d.ts.map +0 -1
- package/dist/commands/link.js +0 -36
- package/dist/commands/link.js.map +0 -1
- package/dist/commands/login.utils.d.ts +0 -3
- package/dist/commands/login.utils.d.ts.map +0 -1
- package/dist/commands/login.utils.js +0 -13
- package/dist/commands/login.utils.js.map +0 -1
- package/dist/commands/new.d.ts +0 -15
- package/dist/commands/new.d.ts.map +0 -1
- package/dist/commands/new.js +0 -172
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/new.utils.d.ts +0 -7
- package/dist/commands/new.utils.d.ts.map +0 -1
- package/dist/commands/new.utils.js +0 -50
- package/dist/commands/new.utils.js.map +0 -1
- package/dist/commands/onboard.d.ts +0 -10
- package/dist/commands/onboard.d.ts.map +0 -1
- package/dist/commands/onboard.js +0 -93
- package/dist/commands/onboard.js.map +0 -1
- package/dist/commands/tui.d.ts +0 -12
- package/dist/commands/tui.d.ts.map +0 -1
- package/dist/commands/tui.js +0 -112
- package/dist/commands/tui.js.map +0 -1
- package/dist/help-format.d.ts +0 -4
- package/dist/help-format.d.ts.map +0 -1
- package/dist/help-format.js +0 -30
- package/dist/help-format.js.map +0 -1
- package/dist/lab/config.d.ts +0 -32
- package/dist/lab/config.d.ts.map +0 -1
- package/dist/lab/config.js +0 -148
- package/dist/lab/config.js.map +0 -1
- package/dist/lab/contentStatus.d.ts +0 -6
- package/dist/lab/contentStatus.d.ts.map +0 -1
- package/dist/lab/contentStatus.js +0 -19
- package/dist/lab/contentStatus.js.map +0 -1
- package/dist/ui/banner.d.ts +0 -2
- package/dist/ui/banner.d.ts.map +0 -1
- package/dist/ui/banner.js +0 -22
- package/dist/ui/banner.js.map +0 -1
- package/dist/utils/findRepoRoot.d.ts +0 -2
- package/dist/utils/findRepoRoot.d.ts.map +0 -1
- package/dist/utils/findRepoRoot.js +0 -17
- package/dist/utils/findRepoRoot.js.map +0 -1
- package/dist/utils/pathExists.d.ts +0 -2
- package/dist/utils/pathExists.d.ts.map +0 -1
- package/dist/utils/pathExists.js +0 -11
- package/dist/utils/pathExists.js.map +0 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export function emptyResult(tool) {
|
|
4
|
+
return { tool, daily: [], hourly: [], models: {} };
|
|
5
|
+
}
|
|
6
|
+
export const HOURLY_WINDOW_DAYS = 90;
|
|
7
|
+
export function toDateStr(ts) {
|
|
8
|
+
const v = typeof ts === 'string' && /^\d+$/.test(ts) ? Number(ts) : ts;
|
|
9
|
+
const d = new Date(v);
|
|
10
|
+
return d.toISOString().slice(0, 10);
|
|
11
|
+
}
|
|
12
|
+
export function hourlyCutoff() {
|
|
13
|
+
const d = new Date();
|
|
14
|
+
d.setUTCDate(d.getUTCDate() - HOURLY_WINDOW_DAYS);
|
|
15
|
+
return d.toISOString().slice(0, 10);
|
|
16
|
+
}
|
|
17
|
+
export function formatTokens(n) {
|
|
18
|
+
if (n >= 1_000_000_000)
|
|
19
|
+
return `${(n / 1_000_000_000).toFixed(1)}B`;
|
|
20
|
+
if (n >= 1_000_000)
|
|
21
|
+
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
22
|
+
if (n >= 1_000)
|
|
23
|
+
return `${(n / 1_000).toFixed(0)}K`;
|
|
24
|
+
return String(n);
|
|
25
|
+
}
|
|
26
|
+
export function formatBytes(n) {
|
|
27
|
+
if (n >= 1_073_741_824)
|
|
28
|
+
return `${(n / 1_073_741_824).toFixed(1)}GB`;
|
|
29
|
+
if (n >= 1_048_576)
|
|
30
|
+
return `${(n / 1_048_576).toFixed(1)}MB`;
|
|
31
|
+
if (n >= 1_024)
|
|
32
|
+
return `${(n / 1_024).toFixed(0)}KB`;
|
|
33
|
+
return `${n}B`;
|
|
34
|
+
}
|
|
35
|
+
/** Recursively collect files with a given extension; unreadable dirs are skipped. */
|
|
36
|
+
export async function findFiles(dir, ext) {
|
|
37
|
+
const results = [];
|
|
38
|
+
async function walk(current) {
|
|
39
|
+
try {
|
|
40
|
+
const entries = await readdir(current, { withFileTypes: true });
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
const fullPath = join(current, entry.name);
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
await walk(fullPath);
|
|
45
|
+
}
|
|
46
|
+
else if (entry.name.endsWith(ext)) {
|
|
47
|
+
results.push(fullPath);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// skip unreadable directories
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
await walk(dir);
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Per-scanner accumulator. Replaces the old module-level modelAccumulator /
|
|
60
|
+
* hourlyAccumulator globals — each scanner instantiates its own, so there is no
|
|
61
|
+
* cross-scan state to clear and concurrent runs can't clobber each other.
|
|
62
|
+
*/
|
|
63
|
+
export class TokenCollector {
|
|
64
|
+
tool;
|
|
65
|
+
dailyByModel = new Map();
|
|
66
|
+
hourly = new Map();
|
|
67
|
+
models = new Map();
|
|
68
|
+
cutoff = hourlyCutoff();
|
|
69
|
+
constructor(tool) {
|
|
70
|
+
this.tool = tool;
|
|
71
|
+
}
|
|
72
|
+
addDaily(date, model, tokens, messages = 1) {
|
|
73
|
+
const key = `${date}|${model}`;
|
|
74
|
+
const existing = this.dailyByModel.get(key);
|
|
75
|
+
if (existing) {
|
|
76
|
+
existing.tokens += tokens;
|
|
77
|
+
existing.messages += messages;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.dailyByModel.set(key, { tokens, messages });
|
|
81
|
+
}
|
|
82
|
+
if (model)
|
|
83
|
+
this.models.set(model, (this.models.get(model) ?? 0) + tokens);
|
|
84
|
+
}
|
|
85
|
+
addHourly(date, hour, model, tokens, messages = 1) {
|
|
86
|
+
if (date < this.cutoff)
|
|
87
|
+
return;
|
|
88
|
+
const key = `${date}|${hour}|${model ?? ''}`;
|
|
89
|
+
const existing = this.hourly.get(key);
|
|
90
|
+
if (existing) {
|
|
91
|
+
existing.tokens += tokens;
|
|
92
|
+
existing.messages += messages;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.hourly.set(key, { tokens, messages });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
result(extra) {
|
|
99
|
+
const daily = Array.from(this.dailyByModel.entries()).map(([key, { tokens, messages }]) => {
|
|
100
|
+
const [date, model] = key.split('|');
|
|
101
|
+
return {
|
|
102
|
+
date: date ?? '',
|
|
103
|
+
tool: this.tool,
|
|
104
|
+
tokens,
|
|
105
|
+
messages,
|
|
106
|
+
model: model || undefined,
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
const hourly = Array.from(this.hourly.entries()).map(([key, { tokens, messages }]) => {
|
|
110
|
+
const [date, hourStr, model] = key.split('|');
|
|
111
|
+
return {
|
|
112
|
+
date: date ?? '',
|
|
113
|
+
hour: Number(hourStr),
|
|
114
|
+
tool: this.tool,
|
|
115
|
+
model: model || undefined,
|
|
116
|
+
tokens,
|
|
117
|
+
messages,
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
tool: this.tool,
|
|
122
|
+
daily,
|
|
123
|
+
hourly,
|
|
124
|
+
models: Object.fromEntries(this.models),
|
|
125
|
+
...extra,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/scanners/util.ts"],"names":[],"mappings":"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"}
|
package/dist/session.d.ts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
export type Session = {
|
|
2
|
-
email: string;
|
|
3
2
|
token: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
email: string;
|
|
4
|
+
handle?: string;
|
|
5
|
+
appUrl: string;
|
|
6
|
+
savedAt: string;
|
|
7
|
+
expiresAt?: string;
|
|
7
8
|
};
|
|
8
|
-
export type
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
export type LoadSessionState = {
|
|
10
|
+
status: 'ok';
|
|
11
|
+
session: Session;
|
|
12
|
+
} | {
|
|
13
|
+
status: 'missing' | 'invalid' | 'expired';
|
|
14
|
+
session: null;
|
|
11
15
|
};
|
|
12
16
|
export declare function getSessionPath(): string;
|
|
13
|
-
export declare function
|
|
14
|
-
export declare function
|
|
15
|
-
export declare function
|
|
16
|
-
export declare function
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function saveSession(session: Session): Promise<void>;
|
|
18
|
+
export declare function getSessionExpiresAt(session: Pick<Session, 'expiresAt' | 'savedAt'>): Date | null;
|
|
19
|
+
export declare function isSessionExpired(session: Pick<Session, 'expiresAt' | 'savedAt'>, now?: Date): boolean;
|
|
20
|
+
export declare function loadSessionState(): Promise<LoadSessionState>;
|
|
21
|
+
export declare function loadSession(): Promise<Session | null>;
|
|
22
|
+
export declare function getAppUrl(): string;
|
|
18
23
|
//# sourceMappingURL=session.d.ts.map
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAKD,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAAA;AAEhE,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjE;AASD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC,GAC9C,IAAI,GAAG,IAAI,CAQb;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC,EAC/C,GAAG,OAAa,GACf,OAAO,CAGT;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAyBlE;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAE3D;AAED,wBAAgB,SAAS,IAAI,MAAM,CAIlC"}
|
package/dist/session.js
CHANGED
|
@@ -1,158 +1,63 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const SESSION_PATH = join(homedir(), '.hacklab', 'session.json');
|
|
5
|
+
const LEGACY_SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
6
6
|
export function getSessionPath() {
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
async function loadAccountState(accountsPath = getAccountsPath()) {
|
|
7
|
+
return process.env.HACKLAB_SESSION_PATH ?? SESSION_PATH;
|
|
8
|
+
}
|
|
9
|
+
export async function saveSession(session) {
|
|
10
|
+
const path = getSessionPath();
|
|
11
|
+
await mkdir(dirname(path), { recursive: true });
|
|
12
|
+
await writeFile(path, `${JSON.stringify(session, null, 2)}\n`, 'utf8');
|
|
13
|
+
}
|
|
14
|
+
function parseDate(value) {
|
|
15
|
+
if (!value)
|
|
16
|
+
return null;
|
|
17
|
+
const date = new Date(value);
|
|
18
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
19
|
+
}
|
|
20
|
+
export function getSessionExpiresAt(session) {
|
|
21
|
+
const explicit = parseDate(session.expiresAt);
|
|
22
|
+
if (explicit)
|
|
23
|
+
return explicit;
|
|
24
|
+
const savedAt = parseDate(session.savedAt);
|
|
25
|
+
if (!savedAt)
|
|
26
|
+
return null;
|
|
27
|
+
return new Date(savedAt.getTime() + LEGACY_SESSION_TTL_MS);
|
|
28
|
+
}
|
|
29
|
+
export function isSessionExpired(session, now = new Date()) {
|
|
30
|
+
const expiresAt = getSessionExpiresAt(session);
|
|
31
|
+
return expiresAt ? expiresAt.getTime() <= now.getTime() : false;
|
|
32
|
+
}
|
|
33
|
+
export async function loadSessionState() {
|
|
34
|
+
let raw;
|
|
38
35
|
try {
|
|
39
|
-
|
|
40
|
-
const parsed = JSON.parse(raw);
|
|
41
|
-
return normalizeAccountState(parsed);
|
|
36
|
+
raw = await readFile(getSessionPath(), 'utf8');
|
|
42
37
|
}
|
|
43
|
-
catch
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
accounts: [],
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
if (error instanceof SyntaxError) {
|
|
50
|
-
return {
|
|
51
|
-
accounts: [],
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
throw error;
|
|
38
|
+
catch {
|
|
39
|
+
return { status: 'missing', session: null };
|
|
55
40
|
}
|
|
56
|
-
|
|
57
|
-
async function saveAccountState(state, accountsPath = getAccountsPath()) {
|
|
58
|
-
await mkdir(dirname(accountsPath), { recursive: true });
|
|
59
|
-
await writeFile(accountsPath, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
|
60
|
-
}
|
|
61
|
-
export async function saveSession(session, sessionPath = getSessionPath()) {
|
|
62
|
-
await mkdir(dirname(sessionPath), { recursive: true });
|
|
63
|
-
await writeFile(sessionPath, `${JSON.stringify(session, null, 2)}\n`, 'utf8');
|
|
41
|
+
let data;
|
|
64
42
|
try {
|
|
65
|
-
|
|
66
|
-
const existing = state.accounts.find((account) => account.email === session.email);
|
|
67
|
-
const nextAccount = {
|
|
68
|
-
...existing,
|
|
69
|
-
...session,
|
|
70
|
-
hqPaths: existing?.hqPaths ?? [],
|
|
71
|
-
activeHqPath: existing?.activeHqPath,
|
|
72
|
-
};
|
|
73
|
-
const accounts = state.accounts.filter((account) => account.email !== session.email);
|
|
74
|
-
accounts.push(nextAccount);
|
|
75
|
-
await saveAccountState({
|
|
76
|
-
activeEmail: session.email,
|
|
77
|
-
accounts,
|
|
78
|
-
});
|
|
43
|
+
data = JSON.parse(raw);
|
|
79
44
|
}
|
|
80
45
|
catch {
|
|
81
|
-
|
|
46
|
+
return { status: 'invalid', session: null };
|
|
82
47
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const raw = await readFile(sessionPath, 'utf8');
|
|
87
|
-
const parsed = JSON.parse(raw);
|
|
88
|
-
if (!parsed.email || !parsed.token || !parsed.loggedInAt) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
email: parsed.email,
|
|
93
|
-
token: parsed.token,
|
|
94
|
-
loggedInAt: parsed.loggedInAt,
|
|
95
|
-
appUrl: parsed.appUrl,
|
|
96
|
-
nickname: parsed.nickname,
|
|
97
|
-
};
|
|
48
|
+
if (!data.token || !data.email || !data.appUrl) {
|
|
49
|
+
return { status: 'invalid', session: null };
|
|
98
50
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
if (error instanceof SyntaxError) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
throw error;
|
|
51
|
+
const session = data;
|
|
52
|
+
if (isSessionExpired(session)) {
|
|
53
|
+
return { status: 'expired', session: null };
|
|
107
54
|
}
|
|
55
|
+
return { status: 'ok', session };
|
|
108
56
|
}
|
|
109
|
-
export async function
|
|
110
|
-
|
|
111
|
-
if (state.accounts.length > 0) {
|
|
112
|
-
return state.accounts;
|
|
113
|
-
}
|
|
114
|
-
const session = await loadSession();
|
|
115
|
-
if (!session) {
|
|
116
|
-
return [];
|
|
117
|
-
}
|
|
118
|
-
return [
|
|
119
|
-
{
|
|
120
|
-
...session,
|
|
121
|
-
hqPaths: [],
|
|
122
|
-
},
|
|
123
|
-
];
|
|
57
|
+
export async function loadSession() {
|
|
58
|
+
return (await loadSessionState()).session;
|
|
124
59
|
}
|
|
125
|
-
export
|
|
126
|
-
|
|
127
|
-
let account = state.accounts.find((item) => item.email === email);
|
|
128
|
-
if (!account) {
|
|
129
|
-
const session = await loadSession();
|
|
130
|
-
if (!session || session.email !== email) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
account = {
|
|
134
|
-
...session,
|
|
135
|
-
hqPaths: [],
|
|
136
|
-
};
|
|
137
|
-
state.accounts.push(account);
|
|
138
|
-
}
|
|
139
|
-
const existingPaths = account.hqPaths ?? [];
|
|
140
|
-
const nextPaths = existingPaths.includes(hqPath)
|
|
141
|
-
? existingPaths
|
|
142
|
-
: [...existingPaths, hqPath];
|
|
143
|
-
const nextAccounts = state.accounts.map((item) => {
|
|
144
|
-
if (item.email !== email) {
|
|
145
|
-
return item;
|
|
146
|
-
}
|
|
147
|
-
return {
|
|
148
|
-
...item,
|
|
149
|
-
hqPaths: nextPaths,
|
|
150
|
-
activeHqPath: hqPath,
|
|
151
|
-
};
|
|
152
|
-
});
|
|
153
|
-
await saveAccountState({
|
|
154
|
-
activeEmail: state.activeEmail || email,
|
|
155
|
-
accounts: nextAccounts,
|
|
156
|
-
});
|
|
60
|
+
export function getAppUrl() {
|
|
61
|
+
return (process.env.HACKLAB_APP_URL?.replace(/\/$/, '') ?? 'http://localhost:3000');
|
|
157
62
|
}
|
|
158
63
|
//# sourceMappingURL=session.js.map
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type ShareCardData = {
|
|
2
|
+
handle: string;
|
|
3
|
+
level: number;
|
|
4
|
+
title: string;
|
|
5
|
+
beltColor: string;
|
|
6
|
+
tokensTotal: number;
|
|
7
|
+
rank: number;
|
|
8
|
+
streak: number;
|
|
9
|
+
longestStreak: number;
|
|
10
|
+
progressPercent: number;
|
|
11
|
+
estimatedCost: number;
|
|
12
|
+
toolBreakdown: {
|
|
13
|
+
claudeCode: number;
|
|
14
|
+
codex: number;
|
|
15
|
+
cursor: number;
|
|
16
|
+
};
|
|
17
|
+
models: Array<{
|
|
18
|
+
name: string;
|
|
19
|
+
tokens: number;
|
|
20
|
+
}>;
|
|
21
|
+
dailyActivity: Array<{
|
|
22
|
+
date: string;
|
|
23
|
+
tokens: number;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
export declare function generateShareCard(data: ShareCardData): Promise<string>;
|
|
27
|
+
export declare function displayInTerminal(pngBuffer: Buffer): boolean;
|
|
28
|
+
export declare function copyToClipboard(imagePath: string): Promise<boolean>;
|
|
29
|
+
//# sourceMappingURL=share-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-card.d.ts","sourceRoot":"","sources":["../src/share-card.tsx"],"names":[],"mappings":"AA0CA,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/C,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACvD,CAAA;AAmfD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC5E;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CA4C5D;AAED,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASzE"}
|