standout 0.5.34 → 0.5.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/cli.js +7435 -565
  2. package/package.json +9 -3
  3. package/dist/ai-usage.d.ts +0 -164
  4. package/dist/ai-usage.js +0 -1306
  5. package/dist/api.d.ts +0 -10
  6. package/dist/api.js +0 -94
  7. package/dist/browser-session.d.ts +0 -3
  8. package/dist/browser-session.js +0 -227
  9. package/dist/cli.d.ts +0 -2
  10. package/dist/cursor.d.ts +0 -57
  11. package/dist/cursor.js +0 -562
  12. package/dist/dev-env.d.ts +0 -28
  13. package/dist/dev-env.js +0 -264
  14. package/dist/gather.d.ts +0 -82
  15. package/dist/gather.js +0 -922
  16. package/dist/heap.d.ts +0 -1
  17. package/dist/heap.js +0 -25
  18. package/dist/identity.d.ts +0 -8
  19. package/dist/identity.js +0 -29
  20. package/dist/linkedin-scrape.d.ts +0 -2
  21. package/dist/linkedin-scrape.js +0 -56
  22. package/dist/mcp.d.ts +0 -1
  23. package/dist/mcp.js +0 -25
  24. package/dist/payload.d.ts +0 -8
  25. package/dist/payload.js +0 -163
  26. package/dist/prompt.d.ts +0 -1
  27. package/dist/prompt.js +0 -247
  28. package/dist/proxy.d.ts +0 -1
  29. package/dist/proxy.js +0 -27
  30. package/dist/redact.d.ts +0 -1
  31. package/dist/redact.js +0 -37
  32. package/dist/tools.d.ts +0 -4
  33. package/dist/tools.js +0 -182
  34. package/dist/twitter-scrape.d.ts +0 -1
  35. package/dist/twitter-scrape.js +0 -48
  36. package/dist/wrapped/aggregate.d.ts +0 -6
  37. package/dist/wrapped/aggregate.js +0 -811
  38. package/dist/wrapped/chrono-critters.d.ts +0 -8
  39. package/dist/wrapped/chrono-critters.js +0 -32
  40. package/dist/wrapped/index.d.ts +0 -3
  41. package/dist/wrapped/index.js +0 -2
  42. package/dist/wrapped/mascots.d.ts +0 -2
  43. package/dist/wrapped/mascots.js +0 -35
  44. package/dist/wrapped/preview.d.ts +0 -1
  45. package/dist/wrapped/preview.js +0 -97
  46. package/dist/wrapped/render.d.ts +0 -14
  47. package/dist/wrapped/render.js +0 -1025
  48. package/dist/wrapped/tiers.d.ts +0 -9
  49. package/dist/wrapped/tiers.js +0 -73
  50. package/dist/wrapped/types.d.ts +0 -189
  51. package/dist/wrapped/types.js +0 -4
  52. package/dist/wrapped-client.d.ts +0 -16
  53. package/dist/wrapped-client.js +0 -166
  54. package/dist/wrapped-share.d.ts +0 -1
  55. package/dist/wrapped-share.js +0 -6
package/dist/api.d.ts DELETED
@@ -1,10 +0,0 @@
1
- export declare const STANDOUT_API_URL: string;
2
- export declare function enrichProfile(type: string, value: string): Promise<string>;
3
- export interface SubmitProfileOptions {
4
- prefetchedProfile?: Record<string, unknown>;
5
- wrappedId?: string | null;
6
- }
7
- export declare function mergeSubmissionProfile(profileData: Record<string, unknown>, prefetchedProfile?: Record<string, unknown>): Record<string, unknown>;
8
- export declare function linkWrappedToSubmission(wrappedId: string, submissionId: string): Promise<void>;
9
- export declare function markWrappedShared(wrappedId: string): Promise<void>;
10
- export declare function submitProfile(profile: string, options?: SubmitProfileOptions): Promise<string>;
package/dist/api.js DELETED
@@ -1,94 +0,0 @@
1
- import { capPayload } from "./payload.js";
2
- export const STANDOUT_API_URL = process.env.STANDOUT_API_URL || "https://standout.work";
3
- // Matches the server's request budget so the client doesn't hang forever (the
4
- // submit handler has no client timeout otherwise) nor abort a still-valid run.
5
- const SUBMIT_TIMEOUT_MS = 300000;
6
- export async function enrichProfile(type, value) {
7
- try {
8
- const res = await fetch(`${STANDOUT_API_URL}/api/public/agent-enrich`, {
9
- method: "POST",
10
- headers: { "Content-Type": "application/json" },
11
- body: JSON.stringify({ type, value }),
12
- });
13
- if (!res.ok) {
14
- const error = await res.text();
15
- return `Enrichment failed (${res.status}): ${error}`;
16
- }
17
- return JSON.stringify(await res.json(), null, 2);
18
- }
19
- catch (error) {
20
- return `Enrichment error: ${error instanceof Error ? error.message : String(error)}`;
21
- }
22
- }
23
- export function mergeSubmissionProfile(profileData, prefetchedProfile) {
24
- if (!prefetchedProfile)
25
- return profileData;
26
- return {
27
- ...profileData,
28
- // The LLM compiles a recruiter-facing profile and can accidentally omit
29
- // raw gathered datasets. Preserve the authoritative local scan payloads.
30
- ai_usage: profileData.ai_usage ?? prefetchedProfile.ai_usage,
31
- readiness: profileData.readiness ?? prefetchedProfile.readiness,
32
- local: profileData.local ?? prefetchedProfile.local,
33
- twitter: profileData.twitter ?? prefetchedProfile.twitter,
34
- linkedin: profileData.linkedin ?? prefetchedProfile.linkedin,
35
- ai_coding: {
36
- ...(prefetchedProfile.ai_coding ?? {}),
37
- ...(profileData.ai_coding ?? {}),
38
- },
39
- dev_environment: profileData.dev_environment ?? prefetchedProfile.dev_environment,
40
- };
41
- }
42
- export async function linkWrappedToSubmission(wrappedId, submissionId) {
43
- try {
44
- await fetch(`${STANDOUT_API_URL}/api/public/wrapped/${wrappedId}`, {
45
- method: "PATCH",
46
- headers: { "Content-Type": "application/json" },
47
- body: JSON.stringify({ submission_id: submissionId }),
48
- });
49
- }
50
- catch {
51
- // Non-critical: the profile submission already succeeded.
52
- }
53
- }
54
- export async function markWrappedShared(wrappedId) {
55
- try {
56
- await fetch(`${STANDOUT_API_URL}/api/public/wrapped/${wrappedId}`, {
57
- method: "PATCH",
58
- headers: { "Content-Type": "application/json" },
59
- body: JSON.stringify({ shared: true }),
60
- });
61
- }
62
- catch {
63
- // Non-critical analytics signal.
64
- }
65
- }
66
- export async function submitProfile(profile, options = {}) {
67
- try {
68
- const profileData = JSON.parse(profile);
69
- const jobId = process.env.STANDOUT_JOB_ID;
70
- const mergedProfile = mergeSubmissionProfile(profileData, options.prefetchedProfile);
71
- const payload = jobId ? { ...mergedProfile, jobId } : mergedProfile;
72
- // Trim under Vercel's 4.5MB body cap so a heavy history can't 413 the core
73
- // submission before the handler runs.
74
- const { payload: capped } = capPayload(payload);
75
- const res = await fetch(`${STANDOUT_API_URL}/api/public/agent-submit`, {
76
- method: "POST",
77
- headers: { "Content-Type": "application/json" },
78
- body: JSON.stringify(capped),
79
- signal: AbortSignal.timeout(SUBMIT_TIMEOUT_MS),
80
- });
81
- if (!res.ok) {
82
- const error = await res.text();
83
- return `Submission failed (${res.status}): ${error}`;
84
- }
85
- const result = (await res.json());
86
- if (options.wrappedId && result.id) {
87
- await linkWrappedToSubmission(options.wrappedId, result.id);
88
- }
89
- return `Profile submitted successfully! ID: ${result.id}`;
90
- }
91
- catch (error) {
92
- return `Submission error: ${error instanceof Error ? error.message : String(error)}`;
93
- }
94
- }
@@ -1,3 +0,0 @@
1
- import { type BrowserContext } from "playwright-core";
2
- export declare const NAV_TIMEOUT_MS = 20000;
3
- export declare function scrapeFromChromeSession<T>(extract: (context: BrowserContext) => Promise<T | null>): Promise<T | null>;
@@ -1,227 +0,0 @@
1
- import { chromium } from "playwright-core";
2
- import { existsSync, readdirSync, statSync, mkdtempSync, mkdirSync, copyFileSync, rmSync, readFileSync, } from "fs";
3
- import { homedir, platform, tmpdir } from "os";
4
- import { join } from "path";
5
- import { spawn } from "child_process";
6
- const DEBUG_PORT_WAIT_MS = 10000;
7
- export const NAV_TIMEOUT_MS = 20000;
8
- const TOTAL_TIMEOUT_MS = 40000;
9
- function wait(ms) {
10
- return new Promise((r) => setTimeout(r, ms));
11
- }
12
- function findChromeExecutable() {
13
- const os = platform();
14
- const candidates = os === "darwin"
15
- ? [
16
- "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
17
- "/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta",
18
- "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
19
- "/Applications/Chromium.app/Contents/MacOS/Chromium",
20
- ]
21
- : os === "linux"
22
- ? [
23
- "/usr/bin/google-chrome",
24
- "/usr/bin/google-chrome-stable",
25
- "/usr/bin/chromium",
26
- "/usr/bin/chromium-browser",
27
- "/snap/bin/chromium",
28
- ]
29
- : os === "win32"
30
- ? [
31
- "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
32
- "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
33
- ]
34
- : [];
35
- for (const path of candidates) {
36
- if (existsSync(path))
37
- return path;
38
- }
39
- return null;
40
- }
41
- function findChromeProfileRoot() {
42
- const os = platform();
43
- const home = homedir();
44
- const candidates = os === "darwin"
45
- ? [
46
- join(home, "Library", "Application Support", "Google", "Chrome"),
47
- join(home, "Library", "Application Support", "Chromium"),
48
- ]
49
- : os === "linux"
50
- ? [
51
- join(home, ".config", "google-chrome"),
52
- join(home, ".config", "chromium"),
53
- ]
54
- : os === "win32"
55
- ? [join(home, "AppData", "Local", "Google", "Chrome", "User Data")]
56
- : [];
57
- for (const path of candidates) {
58
- if (existsSync(path) && existsSync(join(path, "Local State")))
59
- return path;
60
- }
61
- return null;
62
- }
63
- function listProfilesByMtime(profileRoot) {
64
- try {
65
- return readdirSync(profileRoot)
66
- .filter((d) => existsSync(join(profileRoot, d, "Cookies")))
67
- .map((d) => ({
68
- name: d,
69
- mtime: statSync(join(profileRoot, d, "Cookies")).mtimeMs,
70
- }))
71
- .sort((a, b) => b.mtime - a.mtime)
72
- .map((p) => p.name);
73
- }
74
- catch {
75
- return [];
76
- }
77
- }
78
- function prepareProfileCopy(profileRoot, profileName) {
79
- try {
80
- const tempRoot = mkdtempSync(join(tmpdir(), "standout-chrome-"));
81
- mkdirSync(join(tempRoot, "Default"), { recursive: true });
82
- const localState = join(profileRoot, "Local State");
83
- if (existsSync(localState)) {
84
- copyFileSync(localState, join(tempRoot, "Local State"));
85
- }
86
- const sourceDir = join(profileRoot, profileName);
87
- for (const name of ["Cookies", "Cookies-journal", "Preferences"]) {
88
- const src = join(sourceDir, name);
89
- if (existsSync(src)) {
90
- copyFileSync(src, join(tempRoot, "Default", name));
91
- }
92
- }
93
- return tempRoot;
94
- }
95
- catch {
96
- return null;
97
- }
98
- }
99
- async function waitForDebugPort(userDataDir, timeoutMs) {
100
- const deadline = Date.now() + timeoutMs;
101
- const portFile = join(userDataDir, "DevToolsActivePort");
102
- while (Date.now() < deadline) {
103
- if (existsSync(portFile)) {
104
- try {
105
- const [port] = readFileSync(portFile, "utf-8").trim().split("\n");
106
- if (port && /^\d+$/.test(port))
107
- return parseInt(port, 10);
108
- }
109
- catch {
110
- // keep polling
111
- }
112
- }
113
- await wait(200);
114
- }
115
- return null;
116
- }
117
- async function spawnChrome(executablePath, userDataDir) {
118
- const os = platform();
119
- const args = [
120
- "--headless=new",
121
- `--user-data-dir=${userDataDir}`,
122
- "--remote-debugging-port=0",
123
- "--no-first-run",
124
- "--no-default-browser-check",
125
- "--disable-sync",
126
- "--disable-features=AutofillServerCommunication",
127
- ];
128
- const cleanupFns = [];
129
- if (os === "darwin") {
130
- // Use `open -n -a` to force a new Chrome process instance on macOS
131
- // (direct binary launch gets intercepted by the singleton running Chrome).
132
- const appBundle = executablePath.replace(/\.app\/Contents\/MacOS\/.*$/, ".app");
133
- const child = spawn("open", ["-n", "-a", appBundle, "--args", ...args], {
134
- detached: true,
135
- stdio: "ignore",
136
- });
137
- child.unref();
138
- cleanupFns.push(() => {
139
- try {
140
- spawn("pkill", ["-f", `user-data-dir=${userDataDir}`]);
141
- }
142
- catch {
143
- // skip
144
- }
145
- });
146
- }
147
- else {
148
- const child = spawn(executablePath, args, {
149
- detached: true,
150
- stdio: "ignore",
151
- });
152
- child.unref();
153
- cleanupFns.push(() => {
154
- try {
155
- if (child.pid)
156
- process.kill(child.pid);
157
- }
158
- catch {
159
- // skip
160
- }
161
- });
162
- }
163
- const port = await waitForDebugPort(userDataDir, DEBUG_PORT_WAIT_MS);
164
- return {
165
- port,
166
- cleanup: () => cleanupFns.forEach((fn) => fn()),
167
- };
168
- }
169
- async function withTimeout(promise, ms) {
170
- return Promise.race([
171
- promise,
172
- new Promise((resolve) => setTimeout(() => resolve(null), ms)),
173
- ]);
174
- }
175
- async function withProfileContext(executablePath, profileRoot, profileName, extract) {
176
- const tempProfile = prepareProfileCopy(profileRoot, profileName);
177
- if (!tempProfile)
178
- return null;
179
- const { port, cleanup } = await spawnChrome(executablePath, tempProfile);
180
- let browser = null;
181
- try {
182
- if (!port)
183
- return null;
184
- browser = await chromium.connectOverCDP(`http://localhost:${port}`);
185
- const contexts = browser.contexts();
186
- const context = contexts[0] ?? (await browser.newContext());
187
- return await extract(context);
188
- }
189
- catch {
190
- return null;
191
- }
192
- finally {
193
- if (browser)
194
- await browser.close().catch(() => undefined);
195
- cleanup();
196
- await wait(500);
197
- try {
198
- rmSync(tempProfile, { recursive: true, force: true });
199
- }
200
- catch {
201
- // skip
202
- }
203
- }
204
- }
205
- // Headless, silent read of the user's logged-in Chrome session. Copies each
206
- // Chrome profile (newest-cookie first) into a throwaway dir, opens it headless,
207
- // and hands the browser context to `extract`. Returns the first non-null result;
208
- // any failure (no Chrome, no session, checkpoint, timeout) resolves to null.
209
- export async function scrapeFromChromeSession(extract) {
210
- const executablePath = findChromeExecutable();
211
- if (!executablePath)
212
- return null;
213
- const profileRoot = findChromeProfileRoot();
214
- if (!profileRoot)
215
- return null;
216
- const profiles = listProfilesByMtime(profileRoot);
217
- if (profiles.length === 0)
218
- return null;
219
- return withTimeout((async () => {
220
- for (const profile of profiles) {
221
- const result = await withProfileContext(executablePath, profileRoot, profile, extract).catch(() => null);
222
- if (result)
223
- return result;
224
- }
225
- return null;
226
- })(), TOTAL_TIMEOUT_MS);
227
- }
package/dist/cli.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/cursor.d.ts DELETED
@@ -1,57 +0,0 @@
1
- import type { ConversationExchange, InteractionSignals, PromptFrequency } from "./ai-usage.js";
2
- export interface CursorStats {
3
- total_sessions: number;
4
- active_days: number;
5
- first_session: string | null;
6
- last_session: string | null;
7
- total_duration_hours: number;
8
- message_counts: {
9
- user: number;
10
- assistant: number;
11
- total: number;
12
- };
13
- models: string[];
14
- model_session_counts: Record<string, number>;
15
- tool_call_counts: Record<string, number>;
16
- hour_buckets: number[];
17
- weekend_ratio: number;
18
- languages: Record<string, number>;
19
- prompt_samples: string[];
20
- prompt_frequency: PromptFrequency[];
21
- exchanges: ConversationExchange[];
22
- interaction: InteractionSignals;
23
- total_input_tokens: number;
24
- total_output_tokens: number;
25
- total_cache_read_tokens: number;
26
- total_cache_write_tokens: number;
27
- tokens_estimated: true;
28
- monthly_buckets: CursorMonthlyBucket[];
29
- all_time?: {
30
- total_sessions: number;
31
- active_days: number;
32
- first_session: string | null;
33
- last_session: string | null;
34
- total_duration_hours: number;
35
- total_input_tokens: number;
36
- total_output_tokens: number;
37
- total_cache_read_tokens: number;
38
- total_cache_write_tokens: number;
39
- monthly_buckets: CursorMonthlyBucket[];
40
- };
41
- }
42
- interface CursorMonthlyBucket {
43
- month: string;
44
- sessions: number;
45
- duration_hours: number;
46
- input_tokens: number;
47
- output_tokens: number;
48
- cache_read_tokens: number;
49
- cache_write_tokens: number;
50
- cache_tokens: number;
51
- primary_model: string | null;
52
- }
53
- export declare function gatherCursor(opts?: {
54
- dbPath?: string;
55
- windowStartMs?: number;
56
- }): Promise<CursorStats | null>;
57
- export {};