vibe-roast 0.98.0 → 0.98.2
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 +20 -13
- package/assests/README.md +0 -4
- package/assests/source/design-system.md +1 -1
- package/bin/hook.js +6 -4
- package/dashboard/dist/assets/{index-t8m64Hm9.js → index-BPhMyUU4.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/package.json +2 -3
- package/src/hooks/install.js +4 -4
- package/src/lib/terminal-ui.js +105 -0
- package/src/server.js +16 -15
- package/src/sources/vibe-tracker.js +1 -1
- package/worker/README.md +1 -1
- package/assests/live-report.html +0 -1403
- package/assests/notes/live-inspect-summary.json +0 -3487
- package/assests/scripts/live-report-boot.js +0 -2
- package/assests/scripts/roast-extras.js +0 -619
- package/bin/vibe-wrapper.js +0 -4
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const HUMOUR_LINES = Object.freeze([
|
|
2
|
+
"Your prompts have requested legal counsel.",
|
|
3
|
+
"Preparing a performance review for your autocomplete.",
|
|
4
|
+
"No code was judged. Your tab habits, however…",
|
|
5
|
+
"Turning token usage into character evidence.",
|
|
6
|
+
"Your context window left a forwarding address.",
|
|
7
|
+
"The agents have agreed to testify.",
|
|
8
|
+
"Compiling vibes. Types may be dramatically exaggerated.",
|
|
9
|
+
"Your commit history was unavailable for comment.",
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
const STATUS_LINES = Object.freeze([
|
|
13
|
+
"Dusting the fingerprints off local agent history",
|
|
14
|
+
"Arranging the evidence by dramatic potential",
|
|
15
|
+
"Preheating the roast without uploading your prompts",
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
const ANSI = Object.freeze({
|
|
19
|
+
reset: "\u001b[0m",
|
|
20
|
+
bold: "\u001b[1m",
|
|
21
|
+
dim: "\u001b[2m",
|
|
22
|
+
green: "\u001b[38;5;42m",
|
|
23
|
+
orange: "\u001b[38;5;208m",
|
|
24
|
+
cream: "\u001b[38;5;223m",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
function supportsRichOutput(stream = process.stderr, env = process.env) {
|
|
28
|
+
return Boolean(
|
|
29
|
+
stream?.isTTY
|
|
30
|
+
&& env.NO_COLOR == null
|
|
31
|
+
&& env.TERM !== "dumb"
|
|
32
|
+
&& env.CI !== "true"
|
|
33
|
+
&& env.VIBE_ROAST_PLAIN_OUTPUT !== "1",
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function pickHumour(random = Math.random) {
|
|
38
|
+
const value = Number(random());
|
|
39
|
+
const index = Number.isFinite(value)
|
|
40
|
+
? Math.min(HUMOUR_LINES.length - 1, Math.max(0, Math.floor(value * HUMOUR_LINES.length)))
|
|
41
|
+
: 0;
|
|
42
|
+
return HUMOUR_LINES[index];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function sleep(ms) {
|
|
46
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function createTerminalLaunch({
|
|
50
|
+
stream = process.stderr,
|
|
51
|
+
env = process.env,
|
|
52
|
+
random = Math.random,
|
|
53
|
+
frameDelay = 38,
|
|
54
|
+
} = {}) {
|
|
55
|
+
const rich = supportsRichOutput(stream, env);
|
|
56
|
+
|
|
57
|
+
function write(text) {
|
|
58
|
+
stream.write(text);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function intro() {
|
|
62
|
+
if (!rich) return;
|
|
63
|
+
const joke = pickHumour(random);
|
|
64
|
+
write(
|
|
65
|
+
`\n${ANSI.orange}╭─${ANSI.reset} ${ANSI.bold}${ANSI.cream}VIBE ROAST${ANSI.reset} ${ANSI.dim}· local evidence lab${ANSI.reset}\n`
|
|
66
|
+
+ `${ANSI.orange}│${ANSI.reset} ${joke}\n`
|
|
67
|
+
+ `${ANSI.orange}╰────────────────────────────────────────────${ANSI.reset}\n\n`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function animateStatus(label) {
|
|
72
|
+
if (!rich) return;
|
|
73
|
+
const frames = ["◜", "◠", "◝", "◞", "◡", "◟"];
|
|
74
|
+
for (const frame of frames) {
|
|
75
|
+
write(`\r\u001b[2K ${ANSI.orange}${frame}${ANSI.reset} ${ANSI.dim}${label}${ANSI.reset}`);
|
|
76
|
+
await sleep(frameDelay);
|
|
77
|
+
}
|
|
78
|
+
write(`\r\u001b[2K ${ANSI.green}◆${ANSI.reset} ${label}\n`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function ready(url) {
|
|
82
|
+
if (!rich) {
|
|
83
|
+
write(`vibe-roast result → ${url}\n`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (const label of STATUS_LINES) await animateStatus(label);
|
|
88
|
+
write(
|
|
89
|
+
`\n ${ANSI.green}${ANSI.bold}ROAST LAB OPEN${ANSI.reset}\n`
|
|
90
|
+
+ ` ${ANSI.dim}Local dashboard${ANSI.reset} ${ANSI.bold}${url}${ANSI.reset}\n`
|
|
91
|
+
+ ` ${ANSI.dim}Keep this terminal open. Your prompts stay on this machine.${ANSI.reset}\n\n`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { intro, ready, rich };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = {
|
|
99
|
+
ANSI,
|
|
100
|
+
HUMOUR_LINES,
|
|
101
|
+
STATUS_LINES,
|
|
102
|
+
createTerminalLaunch,
|
|
103
|
+
pickHumour,
|
|
104
|
+
supportsRichOutput,
|
|
105
|
+
};
|
package/src/server.js
CHANGED
|
@@ -5,6 +5,7 @@ const os = require("node:os");
|
|
|
5
5
|
const path = require("node:path");
|
|
6
6
|
const { createHash, randomBytes, randomUUID } = require("node:crypto");
|
|
7
7
|
const { exec } = require("node:child_process");
|
|
8
|
+
const { createTerminalLaunch } = require("./lib/terminal-ui");
|
|
8
9
|
const { inspectSources } = require("./inspect");
|
|
9
10
|
const { generateAiRoast, PROVIDERS } = require("./lib/ai-roast");
|
|
10
11
|
const { encodeRoastSnapshot } = require("./lib/roast-snapshot");
|
|
@@ -16,27 +17,27 @@ const ASSETS_DIR = path.join(ROOT_DIR, "assests");
|
|
|
16
17
|
const DEFAULT_GITHUB_CLIENT_ID = "Iv23li5jqHs7pMarqWPZ";
|
|
17
18
|
const DEFAULT_GITHUB_AUTH_BROKER_URL = "https://auth.pinktalk.online";
|
|
18
19
|
const GITHUB_OAUTH_FLOWS = new Map();
|
|
19
|
-
const GITHUB_SESSION_COOKIE = "
|
|
20
|
+
const GITHUB_SESSION_COOKIE = "vibe_roast_github_session";
|
|
20
21
|
const GITHUB_SESSION_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
21
22
|
const MAX_JSON_BODY = 64 * 1024;
|
|
22
23
|
const FREE_AI_PROVIDER = "cloudflare";
|
|
23
24
|
const FREE_AI_MODEL = "@cf/qwen/qwen3-30b-a3b-fp8";
|
|
24
25
|
|
|
25
26
|
function githubClientId() {
|
|
26
|
-
return process.env.
|
|
27
|
+
return process.env.VIBE_ROAST_GITHUB_CLIENT_ID || DEFAULT_GITHUB_CLIENT_ID;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
function githubAuthConfig() {
|
|
30
|
-
const explicitBrokerUrl = String(process.env.
|
|
31
|
+
const explicitBrokerUrl = String(process.env.VIBE_ROAST_AUTH_BROKER_URL || "").replace(/\/+$/, "");
|
|
31
32
|
if (explicitBrokerUrl) {
|
|
32
33
|
return { configured: true, mode: "broker", brokerUrl: explicitBrokerUrl };
|
|
33
34
|
}
|
|
34
|
-
if (process.env.
|
|
35
|
+
if (process.env.VIBE_ROAST_GITHUB_CLIENT_SECRET) {
|
|
35
36
|
return {
|
|
36
37
|
configured: true,
|
|
37
38
|
mode: "direct",
|
|
38
39
|
clientId: githubClientId(),
|
|
39
|
-
clientSecret: process.env.
|
|
40
|
+
clientSecret: process.env.VIBE_ROAST_GITHUB_CLIENT_SECRET,
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
return {
|
|
@@ -47,8 +48,8 @@ function githubAuthConfig() {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
function githubSessionFile() {
|
|
50
|
-
return process.env.
|
|
51
|
-
|| path.join(os.homedir(), ".vibe-
|
|
51
|
+
return process.env.VIBE_ROAST_GITHUB_SESSION_FILE
|
|
52
|
+
|| path.join(os.homedir(), ".vibe-roast", "github-auth.json");
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
function base64Url(bytes) {
|
|
@@ -64,7 +65,7 @@ function requestOrigin(req) {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
function githubCallbackUrl(req) {
|
|
67
|
-
return process.env.
|
|
68
|
+
return process.env.VIBE_ROAST_GITHUB_CALLBACK_URL
|
|
68
69
|
|| `${requestOrigin(req)}/api/auth/github/callback`;
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -307,7 +308,7 @@ function sendRedirect(res, location) {
|
|
|
307
308
|
|
|
308
309
|
function authCallbackPage(res, { ok, message, cookie }) {
|
|
309
310
|
const payload = JSON.stringify({
|
|
310
|
-
type: "vibe-
|
|
311
|
+
type: "vibe-roast:github-auth",
|
|
311
312
|
status: ok ? "connected" : "failed",
|
|
312
313
|
error: ok ? undefined : message,
|
|
313
314
|
}).replace(/</g, "\\u003c");
|
|
@@ -338,7 +339,7 @@ async function handleGithubOAuthStart(req, res) {
|
|
|
338
339
|
const config = githubAuthConfig();
|
|
339
340
|
if (!config.configured) {
|
|
340
341
|
sendJson(res, 503, {
|
|
341
|
-
error: "GitHub OAuth is not configured. Set
|
|
342
|
+
error: "GitHub OAuth is not configured. Set VIBE_ROAST_AUTH_BROKER_URL, or use a local VIBE_ROAST_GITHUB_CLIENT_SECRET for development.",
|
|
342
343
|
code: "github_not_configured",
|
|
343
344
|
});
|
|
344
345
|
return;
|
|
@@ -609,22 +610,22 @@ function createServer() {
|
|
|
609
610
|
}
|
|
610
611
|
|
|
611
612
|
function openBrowser(url) {
|
|
612
|
-
if (process.env.
|
|
613
|
+
if (process.env.VIBE_ROAST_NO_OPEN === "1") return;
|
|
613
614
|
const cmd = process.platform === "darwin" ? `open "${url}"`
|
|
614
615
|
: process.platform === "win32" ? `start "" "${url}"`
|
|
615
616
|
: `xdg-open "${url}"`;
|
|
616
617
|
exec(cmd, () => {});
|
|
617
618
|
}
|
|
618
619
|
|
|
619
|
-
function start() {
|
|
620
|
+
function start({ terminal = createTerminalLaunch() } = {}) {
|
|
621
|
+
terminal.intro();
|
|
620
622
|
const server = createServer();
|
|
621
623
|
return new Promise((resolve) => {
|
|
622
|
-
server.listen(PORT, () => {
|
|
624
|
+
server.listen(PORT, async () => {
|
|
623
625
|
const address = server.address();
|
|
624
626
|
const port = typeof address === "object" && address ? address.port : PORT;
|
|
625
627
|
const url = `http://localhost:${port}`;
|
|
626
|
-
|
|
627
|
-
process.stderr.write(`static live report → ${url}/assests/live-report.html\n`);
|
|
628
|
+
await terminal.ready(url);
|
|
628
629
|
openBrowser(url);
|
|
629
630
|
resolve(server);
|
|
630
631
|
});
|
|
@@ -3,7 +3,7 @@ const path = require("node:path");
|
|
|
3
3
|
const os = require("node:os");
|
|
4
4
|
const { createInterface } = require("node:readline");
|
|
5
5
|
|
|
6
|
-
const STORE_DIR = path.join(os.homedir(), ".vibe-
|
|
6
|
+
const STORE_DIR = path.join(os.homedir(), ".vibe-roast");
|
|
7
7
|
|
|
8
8
|
async function inspectVibeTracker({ range } = {}) {
|
|
9
9
|
const storeFile = path.join(STORE_DIR, "sessions.jsonl");
|
package/worker/README.md
CHANGED
|
@@ -46,7 +46,7 @@ https://auth.pinktalk.online/oauth/github/callback
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
The public npm app uses `https://auth.pinktalk.online` automatically. Users do
|
|
49
|
-
not need to configure `
|
|
49
|
+
not need to configure `VIBE_ROAST_AUTH_BROKER_URL`; that variable is only an
|
|
50
50
|
override for local development or a self-hosted broker.
|
|
51
51
|
|
|
52
52
|
`AUTH_BROKER_PUBLIC_URL` pins OAuth redirects to the Custom Domain even when
|