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.
@@ -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 = "vibe_wrapper_github_session";
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.VIBE_WRAPPER_GITHUB_CLIENT_ID || DEFAULT_GITHUB_CLIENT_ID;
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.VIBE_WRAPPER_AUTH_BROKER_URL || "").replace(/\/+$/, "");
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.VIBE_WRAPPER_GITHUB_CLIENT_SECRET) {
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.VIBE_WRAPPER_GITHUB_CLIENT_SECRET,
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.VIBE_WRAPPER_GITHUB_SESSION_FILE
51
- || path.join(os.homedir(), ".vibe-wrapper", "github-auth.json");
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.VIBE_WRAPPER_GITHUB_CALLBACK_URL
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-wrapper:github-auth",
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 VIBE_WRAPPER_AUTH_BROKER_URL, or use a local VIBE_WRAPPER_GITHUB_CLIENT_SECRET for development.",
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.VIBE_WRAPPER_NO_OPEN === "1") return;
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
- process.stderr.write(`vibe-roast result → ${url}\n`);
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-wrapper");
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 `VIBE_WRAPPER_AUTH_BROKER_URL`; that variable is only an
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