@cynicalsally/cli 0.3.0 → 0.4.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 +40 -12
- package/dist/commands/roast.d.ts.map +1 -1
- package/dist/commands/roast.js +48 -11
- package/dist/commands/roast.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp-server.js +40 -16
- package/dist/mcp-server.js.map +1 -1
- package/dist/utils/api.d.ts +1 -0
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +1 -1
- package/dist/utils/api.js.map +1 -1
- package/dist/utils/card.d.ts +4 -0
- package/dist/utils/card.d.ts.map +1 -0
- package/dist/utils/card.js +151 -0
- package/dist/utils/card.js.map +1 -0
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +9 -0
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/dryrun.d.ts +38 -0
- package/dist/utils/dryrun.d.ts.map +1 -0
- package/dist/utils/dryrun.js +192 -0
- package/dist/utils/dryrun.js.map +1 -0
- package/dist/utils/files.d.ts +42 -1
- package/dist/utils/files.d.ts.map +1 -1
- package/dist/utils/files.js +100 -30
- package/dist/utils/files.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { getGitHubRemote } from "./git.js";
|
|
5
|
+
const REPORT_DIR = ".sally";
|
|
6
|
+
const INNER = 54; // inner width between the box borders
|
|
7
|
+
/** Where the repo lives, for the card footer. */
|
|
8
|
+
function repoLine() {
|
|
9
|
+
const remote = getGitHubRemote();
|
|
10
|
+
if (remote)
|
|
11
|
+
return `github.com/${remote.owner}/${remote.repo}`;
|
|
12
|
+
return "cynicalsally.com";
|
|
13
|
+
}
|
|
14
|
+
/** A 10-segment score bar using block characters (all display width 1). */
|
|
15
|
+
function scoreBar(score) {
|
|
16
|
+
const filled = Math.max(0, Math.min(10, Math.round(score)));
|
|
17
|
+
return "█".repeat(filled) + "░".repeat(10 - filled);
|
|
18
|
+
}
|
|
19
|
+
/** One savage line — the sneer if we have it, else the opening of the roast. */
|
|
20
|
+
function savageLine(response) {
|
|
21
|
+
const sneer = response.voice.hardest_sneer?.trim();
|
|
22
|
+
if (sneer)
|
|
23
|
+
return sneer;
|
|
24
|
+
const firstSentence = response.voice.roast?.split(/(?<=[.!?])\s/)[0]?.trim();
|
|
25
|
+
return firstSentence || "No notes. That's the scariest part.";
|
|
26
|
+
}
|
|
27
|
+
/** Up to two short findings: real issues first, then fixes, then observations. */
|
|
28
|
+
function topFindings(response) {
|
|
29
|
+
const { data, voice } = response;
|
|
30
|
+
if (data.issues && data.issues.length > 0) {
|
|
31
|
+
return data.issues.slice(0, 2).map((i) => i.title.trim());
|
|
32
|
+
}
|
|
33
|
+
if (data.actionable_fixes && data.actionable_fixes.length > 0) {
|
|
34
|
+
return data.actionable_fixes.slice(0, 2).map((f) => f.trim());
|
|
35
|
+
}
|
|
36
|
+
// Quick roast: pull the middle observations from the roast body.
|
|
37
|
+
const paragraphs = voice.roast.split("\n\n").map((p) => p.trim()).filter(Boolean);
|
|
38
|
+
const observations = paragraphs.slice(1).slice(0, 2);
|
|
39
|
+
return observations.map((o) => {
|
|
40
|
+
const firstSentence = o.split(/(?<=[.!?])\s/)[0].trim();
|
|
41
|
+
return firstSentence;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** Wrap plain text (no ANSI) to a width. */
|
|
45
|
+
function wrap(text, width) {
|
|
46
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
47
|
+
const lines = [];
|
|
48
|
+
let current = "";
|
|
49
|
+
for (const word of words) {
|
|
50
|
+
if (current.length + word.length + 1 > width && current) {
|
|
51
|
+
lines.push(current);
|
|
52
|
+
current = word;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
current = current ? current + " " + word : word;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (current)
|
|
59
|
+
lines.push(current);
|
|
60
|
+
return lines.length > 0 ? lines : [""];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build the inner content lines of the card (no borders), each padded to INNER.
|
|
64
|
+
* Plain strings only — alignment math depends on width-1 characters.
|
|
65
|
+
*/
|
|
66
|
+
function cardLines(response) {
|
|
67
|
+
const pad = (s) => " " + s.padEnd(INNER - 2);
|
|
68
|
+
const lines = [];
|
|
69
|
+
lines.push(pad("CYNICAL SALLY · CODE ROAST"));
|
|
70
|
+
lines.push(pad(""));
|
|
71
|
+
lines.push(pad(`Score ${response.data.score.toFixed(1)} / 10 ${scoreBar(response.data.score)}`));
|
|
72
|
+
lines.push(pad(""));
|
|
73
|
+
// Savage quote
|
|
74
|
+
const quote = wrap(`"${savageLine(response)}"`, INNER - 4);
|
|
75
|
+
for (const q of quote)
|
|
76
|
+
lines.push(pad(q));
|
|
77
|
+
lines.push(pad(""));
|
|
78
|
+
// Two findings
|
|
79
|
+
for (const finding of topFindings(response)) {
|
|
80
|
+
const wrapped = wrap(`- ${finding}`, INNER - 4);
|
|
81
|
+
wrapped.forEach((w, idx) => lines.push(pad(idx === 0 ? w : ` ${w}`)));
|
|
82
|
+
}
|
|
83
|
+
lines.push(pad(""));
|
|
84
|
+
lines.push(pad("Roasted by Cynical Sally · cynicalsally.com"));
|
|
85
|
+
lines.push(pad(repoLine()));
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
function topBorder() {
|
|
89
|
+
return "╔" + "═".repeat(INNER) + "╗";
|
|
90
|
+
}
|
|
91
|
+
function bottomBorder() {
|
|
92
|
+
return "╚" + "═".repeat(INNER) + "╝";
|
|
93
|
+
}
|
|
94
|
+
/** Plain (no-ANSI) card, for saving to a file or copy-pasting. */
|
|
95
|
+
function plainCard(response) {
|
|
96
|
+
const out = [topBorder()];
|
|
97
|
+
for (const line of cardLines(response)) {
|
|
98
|
+
out.push("║" + line + "║");
|
|
99
|
+
}
|
|
100
|
+
out.push(bottomBorder());
|
|
101
|
+
return out.join("\n");
|
|
102
|
+
}
|
|
103
|
+
/** Save the card as a screenshot/copy-friendly markdown file. Returns the path. */
|
|
104
|
+
function saveCard(response) {
|
|
105
|
+
try {
|
|
106
|
+
const dir = join(process.cwd(), REPORT_DIR);
|
|
107
|
+
if (!existsSync(dir))
|
|
108
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
109
|
+
const now = new Date();
|
|
110
|
+
const date = now.toISOString().split("T")[0];
|
|
111
|
+
const time = now.toISOString().split("T")[1].slice(0, 8).replace(/:/g, "");
|
|
112
|
+
const filename = `roast-card-${date}-${time}.md`;
|
|
113
|
+
const filepath = join(dir, filename);
|
|
114
|
+
const md = [];
|
|
115
|
+
md.push("```");
|
|
116
|
+
md.push(plainCard(response));
|
|
117
|
+
md.push("```");
|
|
118
|
+
md.push("");
|
|
119
|
+
md.push(`> "${savageLine(response)}"`);
|
|
120
|
+
md.push("");
|
|
121
|
+
md.push(`**Score:** ${response.data.score.toFixed(1)}/10`);
|
|
122
|
+
md.push("");
|
|
123
|
+
for (const finding of topFindings(response)) {
|
|
124
|
+
md.push(`- ${finding}`);
|
|
125
|
+
}
|
|
126
|
+
md.push("");
|
|
127
|
+
md.push(`— Roasted by [Cynical Sally](https://cynicalsally.com) · \`${repoLine()}\``);
|
|
128
|
+
md.push("");
|
|
129
|
+
writeFileSync(filepath, md.join("\n"), { mode: 0o600 });
|
|
130
|
+
return join(REPORT_DIR, filename);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Print the roast card to the terminal and save a shareable copy. */
|
|
137
|
+
export function printRoastCard(response) {
|
|
138
|
+
const border = chalk.magenta;
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(" " + border(topBorder()));
|
|
141
|
+
for (const line of cardLines(response)) {
|
|
142
|
+
console.log(" " + border("║") + chalk.white(line) + border("║"));
|
|
143
|
+
}
|
|
144
|
+
console.log(" " + border(bottomBorder()));
|
|
145
|
+
console.log();
|
|
146
|
+
const saved = saveCard(response);
|
|
147
|
+
if (saved) {
|
|
148
|
+
console.log(chalk.gray(" 📇 Card saved to ") + chalk.cyan(saved) + chalk.gray(" — screenshot it, share it.\n"));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/utils/card.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -10,4 +10,6 @@ export declare function clearSession(): void;
|
|
|
10
10
|
export declare function isLoggedIn(): boolean;
|
|
11
11
|
/** Show tools hint once, then never again. Returns true if this is the first time. */
|
|
12
12
|
export declare function showToolsHint(): boolean;
|
|
13
|
+
/** Show the privacy reassurance once, then never again. Returns true the first time. */
|
|
14
|
+
export declare function showPrivacyNotice(): boolean;
|
|
13
15
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAmCA,2CAA2C;AAC3C,wBAAgB,WAAW,IAAI,MAAM,CAQpC;AAED,wCAAwC;AACxC,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI7C;AAED,uBAAuB;AACvB,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7C;AAED,6BAA6B;AAC7B,wBAAgB,YAAY,IAAI,IAAI,CAInC;AAED,iCAAiC;AACjC,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,sFAAsF;AACtF,wBAAgB,aAAa,IAAI,OAAO,CAMvC;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C"}
|
package/dist/utils/config.js
CHANGED
|
@@ -62,4 +62,13 @@ export function showToolsHint() {
|
|
|
62
62
|
writeConfig(config);
|
|
63
63
|
return true;
|
|
64
64
|
}
|
|
65
|
+
/** Show the privacy reassurance once, then never again. Returns true the first time. */
|
|
66
|
+
export function showPrivacyNotice() {
|
|
67
|
+
const config = readConfig();
|
|
68
|
+
if (config.privacy_notice_shown)
|
|
69
|
+
return false;
|
|
70
|
+
config.privacy_notice_shown = true;
|
|
71
|
+
writeConfig(config);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
65
74
|
//# sourceMappingURL=config.js.map
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAc,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ReviewFile, type SkippedFile } from "./files.js";
|
|
2
|
+
/** One file as it would appear in the request payload. */
|
|
3
|
+
export interface ManifestEntry {
|
|
4
|
+
path: string;
|
|
5
|
+
bytes: number;
|
|
6
|
+
/** Rough token estimate (~4 chars/token). Clearly labelled an estimate. */
|
|
7
|
+
tokens: number;
|
|
8
|
+
sha256: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PayloadManifest {
|
|
11
|
+
entries: ManifestEntry[];
|
|
12
|
+
totalBytes: number;
|
|
13
|
+
totalTokens: number;
|
|
14
|
+
}
|
|
15
|
+
/** Build the exact payload manifest: byte size, token estimate, and SHA-256 per file. */
|
|
16
|
+
export declare function buildManifest(files: ReviewFile[]): PayloadManifest;
|
|
17
|
+
/**
|
|
18
|
+
* Format a payload preview as plain markdown (no ANSI) — used by the MCP
|
|
19
|
+
* `sally_roast` preview mode so an agent can show the user exactly what a roast
|
|
20
|
+
* would upload, without sending anything.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatManifestMarkdown(files: ReviewFile[], skipped: SkippedFile[], meta: {
|
|
23
|
+
mode: string;
|
|
24
|
+
}): string;
|
|
25
|
+
interface DryRunInput {
|
|
26
|
+
files: ReviewFile[];
|
|
27
|
+
skipped: SkippedFile[];
|
|
28
|
+
truncated: boolean;
|
|
29
|
+
mode: string;
|
|
30
|
+
source: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Print exactly what a roast would send, what's held back and why, and write a
|
|
34
|
+
* local SHA-256 receipt. Sends NOTHING to the backend.
|
|
35
|
+
*/
|
|
36
|
+
export declare function printDryRun(input: DryRunInput): void;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=dryrun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dryrun.d.ts","sourceRoot":"","sources":["../../src/utils/dryrun.ts"],"names":[],"mappings":"AAKA,OAAO,EAAsB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAmB,MAAM,YAAY,CAAC;AAIpG,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AA4BD,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,eAAe,CAgBlE;AAmED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,WAAW,EAAE,EACtB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GACrB,MAAM,CAgCR;AAED,UAAU,WAAW;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CA0FpD"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { API_BASE } from "./api.js";
|
|
6
|
+
import { describeSkipReason } from "./files.js";
|
|
7
|
+
const REPORT_DIR = ".sally";
|
|
8
|
+
/** ~4 characters per token is the common rough heuristic. */
|
|
9
|
+
function estimateTokens(content) {
|
|
10
|
+
return Math.max(1, Math.ceil(content.length / 4));
|
|
11
|
+
}
|
|
12
|
+
/** Build the exact payload manifest: byte size, token estimate, and SHA-256 per file. */
|
|
13
|
+
export function buildManifest(files) {
|
|
14
|
+
const entries = files.map((f) => {
|
|
15
|
+
const bytes = Buffer.byteLength(f.content, "utf-8");
|
|
16
|
+
return {
|
|
17
|
+
path: f.path,
|
|
18
|
+
bytes,
|
|
19
|
+
tokens: estimateTokens(f.content),
|
|
20
|
+
sha256: createHash("sha256").update(f.content, "utf-8").digest("hex"),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
entries,
|
|
25
|
+
totalBytes: entries.reduce((sum, e) => sum + e.bytes, 0),
|
|
26
|
+
totalTokens: entries.reduce((sum, e) => sum + e.tokens, 0),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function formatBytes(bytes) {
|
|
30
|
+
if (bytes < 1024)
|
|
31
|
+
return `${bytes} B`;
|
|
32
|
+
if (bytes < 1024 * 1024)
|
|
33
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
34
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
35
|
+
}
|
|
36
|
+
function formatTokens(tokens) {
|
|
37
|
+
return `~${tokens.toLocaleString("en-US")} tok`;
|
|
38
|
+
}
|
|
39
|
+
function ensureReportDir() {
|
|
40
|
+
const dir = join(process.cwd(), REPORT_DIR);
|
|
41
|
+
if (!existsSync(dir)) {
|
|
42
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
43
|
+
}
|
|
44
|
+
return dir;
|
|
45
|
+
}
|
|
46
|
+
/** Write the SHA-256 receipt to .sally/. Returns the path, or null on failure. */
|
|
47
|
+
function writeReceipt(manifest, skipped, meta) {
|
|
48
|
+
try {
|
|
49
|
+
const now = new Date();
|
|
50
|
+
const date = now.toISOString().split("T")[0];
|
|
51
|
+
const time = now.toISOString().split("T")[1].slice(0, 8).replace(/:/g, "");
|
|
52
|
+
const dir = ensureReportDir();
|
|
53
|
+
const filepath = join(dir, `dry-run-${date}-${time}.json`);
|
|
54
|
+
const receipt = {
|
|
55
|
+
tool: "cynical-sally",
|
|
56
|
+
generated_at: now.toISOString(),
|
|
57
|
+
endpoint: `POST ${API_BASE}/api/v1/review`,
|
|
58
|
+
mode: meta.mode,
|
|
59
|
+
source: meta.source,
|
|
60
|
+
note: "Dry run — nothing was sent. This receipt lists exactly what a real roast " +
|
|
61
|
+
"would upload, with a SHA-256 of each file so you can verify it yourself.",
|
|
62
|
+
would_send: {
|
|
63
|
+
file_count: manifest.entries.length,
|
|
64
|
+
total_bytes: manifest.totalBytes,
|
|
65
|
+
estimated_tokens: manifest.totalTokens,
|
|
66
|
+
files: manifest.entries,
|
|
67
|
+
},
|
|
68
|
+
held_back: {
|
|
69
|
+
count: skipped.length,
|
|
70
|
+
files: skipped.map((s) => ({
|
|
71
|
+
path: s.path,
|
|
72
|
+
reason: s.reason,
|
|
73
|
+
reason_text: describeSkipReason(s.reason),
|
|
74
|
+
...(s.detail ? { detail: s.detail } : {}),
|
|
75
|
+
})),
|
|
76
|
+
},
|
|
77
|
+
truncated: meta.truncated,
|
|
78
|
+
};
|
|
79
|
+
writeFileSync(filepath, JSON.stringify(receipt, null, 2) + "\n", { mode: 0o600 });
|
|
80
|
+
return join(REPORT_DIR, `dry-run-${date}-${time}.json`);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Format a payload preview as plain markdown (no ANSI) — used by the MCP
|
|
88
|
+
* `sally_roast` preview mode so an agent can show the user exactly what a roast
|
|
89
|
+
* would upload, without sending anything.
|
|
90
|
+
*/
|
|
91
|
+
export function formatManifestMarkdown(files, skipped, meta) {
|
|
92
|
+
const manifest = buildManifest(files);
|
|
93
|
+
const lines = [];
|
|
94
|
+
lines.push(`## Dry run — nothing sent\n`);
|
|
95
|
+
lines.push(`Endpoint that **would** receive this: \`POST ${API_BASE}/api/v1/review\` · mode: \`${meta.mode}\`\n`);
|
|
96
|
+
lines.push(`**Would send ${manifest.entries.length} file${manifest.entries.length !== 1 ? "s" : ""}** — ` +
|
|
97
|
+
`${formatBytes(manifest.totalBytes)}, ~${manifest.totalTokens.toLocaleString("en-US")} tokens (est.)\n`);
|
|
98
|
+
if (manifest.entries.length > 0) {
|
|
99
|
+
lines.push(`| File | Size | ~Tokens | SHA-256 |`);
|
|
100
|
+
lines.push(`| --- | --- | --- | --- |`);
|
|
101
|
+
for (const e of manifest.entries) {
|
|
102
|
+
lines.push(`| \`${e.path}\` | ${formatBytes(e.bytes)} | ${e.tokens.toLocaleString("en-US")} | \`${e.sha256.slice(0, 16)}…\` |`);
|
|
103
|
+
}
|
|
104
|
+
lines.push("");
|
|
105
|
+
}
|
|
106
|
+
if (skipped.length > 0) {
|
|
107
|
+
lines.push(`**Held back (${skipped.length}) — kept on your machine:**\n`);
|
|
108
|
+
for (const s of skipped) {
|
|
109
|
+
lines.push(`- \`${s.path}\` — ${describeSkipReason(s.reason)}${s.detail ? ` (${s.detail})` : ""}`);
|
|
110
|
+
}
|
|
111
|
+
lines.push("");
|
|
112
|
+
}
|
|
113
|
+
lines.push(`_Nothing was sent. Drop \`preview\` to actually roast._`);
|
|
114
|
+
return lines.join("\n");
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Print exactly what a roast would send, what's held back and why, and write a
|
|
118
|
+
* local SHA-256 receipt. Sends NOTHING to the backend.
|
|
119
|
+
*/
|
|
120
|
+
export function printDryRun(input) {
|
|
121
|
+
const { files, skipped, truncated, mode, source } = input;
|
|
122
|
+
const manifest = buildManifest(files);
|
|
123
|
+
console.log(chalk.magenta.bold(" ☢ DRY RUN") + chalk.gray(" — nothing leaves your machine"));
|
|
124
|
+
console.log();
|
|
125
|
+
console.log(chalk.gray(" This is exactly what a real roast would upload. Verify it, then run"));
|
|
126
|
+
console.log(chalk.gray(" the same command without ") + chalk.cyan("--dry-run") + chalk.gray(" to actually send it.\n"));
|
|
127
|
+
console.log(chalk.gray(" Endpoint that would receive it:"));
|
|
128
|
+
console.log(" " + chalk.white(`POST ${API_BASE}/api/v1/review`));
|
|
129
|
+
console.log(chalk.gray(` Mode: `) + chalk.white(mode) + chalk.gray(" Source: ") + chalk.white(source));
|
|
130
|
+
console.log();
|
|
131
|
+
// ── Would send ──────────────────────────────────────────────────────
|
|
132
|
+
if (manifest.entries.length > 0) {
|
|
133
|
+
console.log(chalk.green.bold(` WOULD SEND `) +
|
|
134
|
+
chalk.white(`${manifest.entries.length} file${manifest.entries.length !== 1 ? "s" : ""}`) +
|
|
135
|
+
chalk.gray(` · ${formatBytes(manifest.totalBytes)} · ~${manifest.totalTokens.toLocaleString("en-US")} tokens (est.)`));
|
|
136
|
+
console.log();
|
|
137
|
+
const pathWidth = Math.min(48, Math.max(12, ...manifest.entries.map((e) => e.path.length)));
|
|
138
|
+
for (const e of manifest.entries) {
|
|
139
|
+
const path = e.path.length > pathWidth ? "…" + e.path.slice(-(pathWidth - 1)) : e.path.padEnd(pathWidth);
|
|
140
|
+
console.log(" " +
|
|
141
|
+
chalk.white(path) +
|
|
142
|
+
chalk.gray(" " + formatBytes(e.bytes).padStart(8)) +
|
|
143
|
+
chalk.gray(" " + formatTokens(e.tokens).padStart(10)) +
|
|
144
|
+
chalk.gray(" " + e.sha256.slice(0, 12) + "…"));
|
|
145
|
+
}
|
|
146
|
+
console.log();
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(chalk.yellow(" WOULD SEND nothing") + chalk.gray(" — every file was held back. See below.\n"));
|
|
150
|
+
}
|
|
151
|
+
// ── Held back ───────────────────────────────────────────────────────
|
|
152
|
+
if (skipped.length > 0) {
|
|
153
|
+
console.log(chalk.yellow.bold(` HELD BACK `) +
|
|
154
|
+
chalk.white(`${skipped.length} item${skipped.length !== 1 ? "s" : ""}`) +
|
|
155
|
+
chalk.gray(" — kept on your machine"));
|
|
156
|
+
console.log();
|
|
157
|
+
// Group by reason so the "why" is unmistakable.
|
|
158
|
+
const byReason = new Map();
|
|
159
|
+
for (const s of skipped) {
|
|
160
|
+
const list = byReason.get(s.reason) ?? [];
|
|
161
|
+
list.push(s);
|
|
162
|
+
byReason.set(s.reason, list);
|
|
163
|
+
}
|
|
164
|
+
// Most trust-relevant reasons first.
|
|
165
|
+
const order = ["secret", "gitignored", "too-large", "binary", "skip-file", "non-reviewable", "skipped-dir", "unreadable"];
|
|
166
|
+
const reasons = [...byReason.keys()].sort((a, b) => order.indexOf(a) - order.indexOf(b));
|
|
167
|
+
for (const reason of reasons) {
|
|
168
|
+
const list = byReason.get(reason);
|
|
169
|
+
const marker = reason === "secret" ? chalk.red.bold(" ✖") : chalk.gray(" •");
|
|
170
|
+
console.log(marker + " " + chalk.white(reason) + chalk.gray(` (${list.length}) — ${describeSkipReason(reason)}`));
|
|
171
|
+
const shown = list.slice(0, 8);
|
|
172
|
+
for (const s of shown) {
|
|
173
|
+
console.log(" " + chalk.gray(s.path) + (s.detail ? chalk.gray(` (${s.detail})`) : ""));
|
|
174
|
+
}
|
|
175
|
+
if (list.length > shown.length) {
|
|
176
|
+
console.log(" " + chalk.gray(`…and ${list.length - shown.length} more`));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
console.log();
|
|
180
|
+
}
|
|
181
|
+
if (truncated) {
|
|
182
|
+
console.log(chalk.yellow(` ⚠ Stopped at the 50-file limit — a real roast would send the same first 50.\n`));
|
|
183
|
+
}
|
|
184
|
+
// ── Receipt ─────────────────────────────────────────────────────────
|
|
185
|
+
const receiptPath = writeReceipt(manifest, skipped, { mode, source, truncated });
|
|
186
|
+
if (receiptPath) {
|
|
187
|
+
console.log(chalk.gray(" 🧾 SHA-256 receipt written to ") + chalk.cyan(receiptPath));
|
|
188
|
+
console.log(chalk.gray(" Compare the hashes yourself — that's the whole point.\n"));
|
|
189
|
+
}
|
|
190
|
+
console.log(chalk.magenta(" Nothing was sent.") + chalk.gray(" Drop the ") + chalk.cyan("--dry-run") + chalk.gray(" flag when you're ready.\n"));
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=dryrun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dryrun.js","sourceRoot":"","sources":["../../src/utils/dryrun.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/files.d.ts
CHANGED
|
@@ -2,10 +2,51 @@ export interface ReviewFile {
|
|
|
2
2
|
path: string;
|
|
3
3
|
content: string;
|
|
4
4
|
}
|
|
5
|
+
/** Why a file was held back and never sent to the backend. */
|
|
6
|
+
export type SkipReason = "secret" | "binary" | "too-large" | "non-reviewable" | "gitignored" | "skip-file" | "skipped-dir" | "unreadable";
|
|
7
|
+
export interface SkippedFile {
|
|
8
|
+
path: string;
|
|
9
|
+
reason: SkipReason;
|
|
10
|
+
/** Optional human-readable extra (e.g. "142 KB", "null bytes"). */
|
|
11
|
+
detail?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Result of a directory scan: what would be sent, what was held back. */
|
|
14
|
+
export interface CollectResult {
|
|
15
|
+
files: ReviewFile[];
|
|
16
|
+
skipped: SkippedFile[];
|
|
17
|
+
/** True if the scan stopped at MAX_FILES and didn't see everything. */
|
|
18
|
+
truncated: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Discriminated result of scanning a single file. */
|
|
21
|
+
export type FileScan = {
|
|
22
|
+
ok: true;
|
|
23
|
+
file: ReviewFile;
|
|
24
|
+
} | {
|
|
25
|
+
ok: false;
|
|
26
|
+
skip: SkippedFile;
|
|
27
|
+
};
|
|
28
|
+
/** Human-readable reason for a skip, for dry-run reporting. */
|
|
29
|
+
export declare function describeSkipReason(reason: SkipReason): string;
|
|
5
30
|
/**
|
|
6
|
-
*
|
|
31
|
+
* Scan a single file, returning either the readable file or the reason it was
|
|
32
|
+
* held back. This is the single source of truth for the per-file secret/binary/
|
|
33
|
+
* size rules — `readFileForReview` and the directory walk both build on it, and
|
|
34
|
+
* the dry-run report surfaces the skip reasons to the user.
|
|
35
|
+
*
|
|
36
|
+
* @param displayPath Optional path to report (e.g. relative) instead of filePath.
|
|
37
|
+
*/
|
|
38
|
+
export declare function scanFileForReview(filePath: string, displayPath?: string): FileScan;
|
|
39
|
+
/**
|
|
40
|
+
* Read a single file for review. Returns null if the file is skipped for any
|
|
41
|
+
* reason (binary, secret, too large, unreadable).
|
|
7
42
|
*/
|
|
8
43
|
export declare function readFileForReview(filePath: string): ReviewFile | null;
|
|
44
|
+
/**
|
|
45
|
+
* Walk a directory and collect files for review, also recording every file and
|
|
46
|
+
* directory that was held back and why. Respects .gitignore, skips binaries,
|
|
47
|
+
* secrets, and known non-code dirs. This is what the `--dry-run` report reads.
|
|
48
|
+
*/
|
|
49
|
+
export declare function collectFilesDetailed(dirPath: string): CollectResult;
|
|
9
50
|
/**
|
|
10
51
|
* Walk a directory and collect files for review.
|
|
11
52
|
* Respects .gitignore, skips binaries and known non-code dirs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8DAA8D;AAC9D,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,gBAAgB,GAChB,YAAY,GACZ,WAAW,GACX,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,uEAAuE;IACvE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,sDAAsD;AACtD,MAAM,MAAM,QAAQ,GAChB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAarC,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE7D;AA+HD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,QAAQ,CAoBlF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGrE;AA6CD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAwFnE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAE1D"}
|