@mossbear/eval-core 0.1.0-alpha.26

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 @@
1
+ {"version":3,"file":"redact-prose.test.js","sourceRoot":"","sources":["../src/redact-prose.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Secret redaction and length-capping for shell command text.
3
+ *
4
+ * Command text can embed secrets or whole file bodies (heredocs, inline env
5
+ * vars). The CLI runs every logged command through this before it becomes an
6
+ * action summary, so nothing that leaves the machine carries credentials or
7
+ * bulk file content (`packages/cli/src/action-queue.ts`). File contents are
8
+ * never read or included in the first place.
9
+ *
10
+ * Lives in eval-core rather than the CLI because grading is what consumes the
11
+ * result: this is the boundary that decides what a grader may ever see of a
12
+ * command.
13
+ */
14
+ /**
15
+ * Redact common secret shapes from a shell command and cap its length so
16
+ * command text never carries credentials or bulk file content off-box.
17
+ *
18
+ * Pure function — no I/O.
19
+ */
20
+ export declare function sanitizeCommand(command: string): string;
21
+ //# sourceMappingURL=sanitize-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-command.d.ts","sourceRoot":"","sources":["../src/sanitize-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAkEH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASvD"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Secret redaction and length-capping for shell command text.
3
+ *
4
+ * Command text can embed secrets or whole file bodies (heredocs, inline env
5
+ * vars). The CLI runs every logged command through this before it becomes an
6
+ * action summary, so nothing that leaves the machine carries credentials or
7
+ * bulk file content (`packages/cli/src/action-queue.ts`). File contents are
8
+ * never read or included in the first place.
9
+ *
10
+ * Lives in eval-core rather than the CLI because grading is what consumes the
11
+ * result: this is the boundary that decides what a grader may ever see of a
12
+ * command.
13
+ */
14
+ /**
15
+ * Maximum characters of a single command string that survive redaction.
16
+ * Short commands convey which tools the agent invoked — which is all a grader
17
+ * needs; anything longer is bulk payload (heredocs, inline file writes) that
18
+ * must not leave the machine.
19
+ */
20
+ const MAX_COMMAND_CHARS = 200;
21
+ /**
22
+ * Redactions applied to command text, in order: heredoc bodies (bulk inline
23
+ * file content), private-key blocks, URL userinfo credentials, Authorization
24
+ * headers, sensitive key=value / key: value pairs (quoted values with spaces
25
+ * included), then well-known bare token prefixes (OpenAI/Anthropic sk-,
26
+ * GitHub ghp_/github_pat_, Slack xox*, AWS AKIA). Redaction is best-effort —
27
+ * the length cap below is the backstop for anything these patterns miss.
28
+ */
29
+ const COMMAND_REDACTIONS = [
30
+ // Heredoc: `cmd <<[-]['"]?WORD['"]? \n <body> \n WORD`. The body is inline
31
+ // file content (secrets, source) that must never leave the machine — replace
32
+ // it wholesale, keeping only the delimiters. Runs first so a heredoc'd
33
+ // private key / token is gone before the narrower patterns below even scan.
34
+ // Terminates on the closing delimiter line or end-of-input (unterminated
35
+ // capture). Over-matching a rare `a << B` bit-shift only over-redacts, which
36
+ // is the safe failure mode here.
37
+ [/(<<-?\s*['"]?)([A-Za-z_]\w*)(['"]?)[\s\S]*?(\n[ \t]*\2\b|$)/g, '$1$2$3 [redacted]$4'],
38
+ [
39
+ /-----BEGIN[A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END[A-Z ]*PRIVATE KEY-----|$)/g,
40
+ '[redacted]',
41
+ ],
42
+ [/\b([a-z][a-z0-9+.-]*:\/\/[^/\s:@]+:)[^@\s]+@/gi, '$1[redacted]@'],
43
+ [/\b(authorization\s*:\s*)(?:bearer\s+)?\S+/gi, '$1[redacted]'],
44
+ // Sensitive assignment: an env-var-ish key (the sensitive word optionally
45
+ // wrapped in `DB_…` / `…_FILE` segments, so `DB_PASSWORD`/`OPENAI_API_KEY`
46
+ // match, not just a bare word) followed by `=`/`:` and a value that is a
47
+ // double/single-quoted string (spaces and all) or an unquoted run up to the
48
+ // next whitespace. Anchored at a shell-token boundary ($1, preserved) so it
49
+ // never fires mid-word; the whole value — quotes included — is redacted so
50
+ // whitespace-containing passphrases can't slip through.
51
+ [
52
+ /(^|[\s;&|(])([\w.-]*(?:api[_-]?key|access[_-]?key|secret[_-]?key|client[_-]?secret|token|secret|passw(?:or)?d|credentials?)[\w.-]*\s*[=:]\s*)(?:"[^"]*"|'[^']*'|[^\s]+)/gi,
53
+ '$1$2[redacted]',
54
+ ],
55
+ // Our own CLI token (`API_KEY_PREFIX`, apps/dashboard/src/features/auth
56
+ // /constants.ts). Listed with the third-party prefixes because the documented
57
+ // setup path — `mossbear sync --token auden_…` — is a *space-separated* flag,
58
+ // so the `key=value` rule above never sees it: without this, the hook logs
59
+ // that command and the next sync uploads a live dashboard credential in an
60
+ // action summary. The product's own secret shape is the one most likely to
61
+ // appear in a command a user runs.
62
+ //
63
+ // Still `auden_`, and deliberately: the prefix is baked into every token
64
+ // already issued, and it is what the dashboard routes on
65
+ // (`validateAuthHeader.ts`, `writeAuthor.ts`), so the rename cannot change it
66
+ // without invalidating live credentials. Whatever prefix a future re-mint
67
+ // uses has to be added here at the same time — a token this rule does not
68
+ // match is one the action log keeps in plaintext.
69
+ [/\bauden_[A-Za-z0-9_-]{8,}/g, '[redacted]'],
70
+ [/\bsk-[A-Za-z0-9_-]{8,}/g, '[redacted]'],
71
+ [/\bgh[pousr]_[A-Za-z0-9]{8,}/g, '[redacted]'],
72
+ [/\bgithub_pat_[A-Za-z0-9_]{8,}/g, '[redacted]'],
73
+ [/\bxox[baprs]-[A-Za-z0-9-]{8,}/g, '[redacted]'],
74
+ [/\bAKIA[0-9A-Z]{16}\b/g, '[redacted]'],
75
+ ];
76
+ /**
77
+ * Redact common secret shapes from a shell command and cap its length so
78
+ * command text never carries credentials or bulk file content off-box.
79
+ *
80
+ * Pure function — no I/O.
81
+ */
82
+ export function sanitizeCommand(command) {
83
+ let out = command;
84
+ for (const [pattern, replacement] of COMMAND_REDACTIONS) {
85
+ out = out.replace(pattern, replacement);
86
+ }
87
+ if (out.length > MAX_COMMAND_CHARS) {
88
+ out = `${out.slice(0, MAX_COMMAND_CHARS)} [... truncated, ${out.length - MAX_COMMAND_CHARS} characters omitted]`;
89
+ }
90
+ return out;
91
+ }
92
+ //# sourceMappingURL=sanitize-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-command.js","sourceRoot":"","sources":["../src/sanitize-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAE7B;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAgC;IACtD,2EAA2E;IAC3E,6EAA6E;IAC7E,uEAAuE;IACvE,4EAA4E;IAC5E,yEAAyE;IACzE,6EAA6E;IAC7E,iCAAiC;IACjC,CAAC,8DAA8D,EAAE,qBAAqB,CAAC;IACvF;QACE,iFAAiF;QACjF,YAAY;KACb;IACD,CAAC,gDAAgD,EAAE,eAAe,CAAC;IACnE,CAAC,6CAA6C,EAAE,cAAc,CAAC;IAC/D,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,wDAAwD;IACxD;QACE,2KAA2K;QAC3K,gBAAgB;KACjB;IACD,wEAAwE;IACxE,8EAA8E;IAC9E,8EAA8E;IAC9E,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,mCAAmC;IACnC,EAAE;IACF,yEAAyE;IACzE,yDAAyD;IACzD,8EAA8E;IAC9E,0EAA0E;IAC1E,0EAA0E;IAC1E,kDAAkD;IAClD,CAAC,4BAA4B,EAAE,YAAY,CAAC;IAC5C,CAAC,yBAAyB,EAAE,YAAY,CAAC;IACzC,CAAC,8BAA8B,EAAE,YAAY,CAAC;IAC9C,CAAC,gCAAgC,EAAE,YAAY,CAAC;IAChD,CAAC,gCAAgC,EAAE,YAAY,CAAC;IAChD,CAAC,uBAAuB,EAAE,YAAY,CAAC;CACxC,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,GAAG,GAAG,OAAO,CAAA;IACjB,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,kBAAkB,EAAE,CAAC;QACxD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IACzC,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACnC,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,oBAAoB,GAAG,CAAC,MAAM,GAAG,iBAAiB,sBAAsB,CAAA;IAClH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sanitize-command.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-command.test.d.ts","sourceRoot":"","sources":["../src/sanitize-command.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { sanitizeCommand } from './sanitize-command.js';
3
+ describe('sanitizeCommand', () => {
4
+ it('leaves short benign commands untouched', () => {
5
+ expect(sanitizeCommand('bun test')).toBe('bun test');
6
+ expect(sanitizeCommand('git commit -m "fix: thing"')).toBe('git commit -m "fix: thing"');
7
+ });
8
+ it('redacts our own CLI token, including the space-separated flag form', () => {
9
+ // The documented setup command puts a live dashboard credential on the
10
+ // command line, where PostToolUse logs it and the next sync would upload
11
+ // it in an action summary. The `key=value` rule never sees a
12
+ // space-separated flag, so the token prefix has to be matched directly.
13
+ // The prefix stays `auden_` after the rename because it is what every
14
+ // issued token carries (`API_KEY_PREFIX`).
15
+ expect(sanitizeCommand('mossbear sync --token auden_tPtcsSvXyRxygMSkBjjDpBKz')).toBe('mossbear sync --token [redacted]');
16
+ expect(sanitizeCommand('mossbear init --token=auden_abcdefgh12345678')).toBe('mossbear init --token=[redacted]');
17
+ });
18
+ it('does not redact ordinary words that merely start with the prefix', () => {
19
+ expect(sanitizeCommand('cd auden_repo && ls')).toBe('cd auden_repo && ls');
20
+ });
21
+ it('redacts bearer tokens in Authorization headers', () => {
22
+ const out = sanitizeCommand('curl -H "Authorization: Bearer sk-abc123def456ghi789" https://api.example.com');
23
+ expect(out).not.toContain('sk-abc123def456ghi789');
24
+ expect(out).toContain('[redacted]');
25
+ expect(out).toContain('https://api.example.com');
26
+ });
27
+ it('redacts credentials in connection-string URLs', () => {
28
+ const out = sanitizeCommand('psql postgres://auden:s3cretpw@db.host:5432/mossbear');
29
+ expect(out).not.toContain('s3cretpw');
30
+ expect(out).toContain('postgres://auden:[redacted]@db.host:5432/mossbear');
31
+ });
32
+ it('redacts sensitive key=value assignments', () => {
33
+ const out = sanitizeCommand('OPENAI_API_KEY=sk-live-abcdef123456 bun run eval');
34
+ expect(out).not.toContain('abcdef123456');
35
+ expect(out).toContain('bun run eval');
36
+ });
37
+ it('redacts quoted secret values that contain spaces', () => {
38
+ const out = sanitizeCommand('PASSWORD="correct horse battery staple" deploy');
39
+ expect(out).not.toContain('correct horse battery staple');
40
+ expect(out).toContain('PASSWORD=[redacted]');
41
+ expect(out).toContain('deploy');
42
+ const single = sanitizeCommand("DB_PASSWORD='a b c d' run");
43
+ expect(single).not.toContain('a b c d');
44
+ expect(single).toContain('run');
45
+ });
46
+ it('strips heredoc bodies, keeping only the delimiters', () => {
47
+ const out = sanitizeCommand("cat > src/config.ts <<EOF\nexport const KEY = 'sk-verysecret12345'\nmore lines\nEOF");
48
+ expect(out).not.toContain('sk-verysecret12345');
49
+ expect(out).not.toContain('more lines');
50
+ expect(out).toContain('[redacted]');
51
+ expect(out).toContain('EOF');
52
+ });
53
+ it('redacts well-known token prefixes standing alone', () => {
54
+ for (const secret of [
55
+ 'ghp_16C7e42F292c6912E7710c838347Ae178B4a',
56
+ 'github_pat_11ABCDEFG_abcdefghij',
57
+ 'xoxb-1234567890-abcdefghijk',
58
+ 'AKIAIOSFODNN7EXAMPLE',
59
+ ]) {
60
+ const out = sanitizeCommand(`deploy --with ${secret}`);
61
+ expect(out).not.toContain(secret);
62
+ }
63
+ });
64
+ it('redacts private key blocks even without an END marker', () => {
65
+ const out = sanitizeCommand('cat > key.pem <<EOF\n-----BEGIN RSA PRIVATE KEY-----\nMIIEow\nEOF');
66
+ expect(out).not.toContain('MIIEow');
67
+ });
68
+ it('truncates long commands and notes omitted length', () => {
69
+ const long = `echo ${'x'.repeat(500)}`;
70
+ const out = sanitizeCommand(long);
71
+ expect(out.length).toBeLessThan(300);
72
+ expect(out).toContain('[... truncated,');
73
+ });
74
+ });
75
+ //# sourceMappingURL=sanitize-command.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-command.test.js","sourceRoot":"","sources":["../src/sanitize-command.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACpD,MAAM,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CACxD,4BAA4B,CAC7B,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,uEAAuE;QACvE,yEAAyE;QACzE,6DAA6D;QAC7D,wEAAwE;QACxE,sEAAsE;QACtE,2CAA2C;QAC3C,MAAM,CAAC,eAAe,CAAC,sDAAsD,CAAC,CAAC,CAAC,IAAI,CAClF,kCAAkC,CACnC,CAAA;QACD,MAAM,CAAC,eAAe,CAAC,8CAA8C,CAAC,CAAC,CAAC,IAAI,CAC1E,kCAAkC,CACnC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,GAAG,GAAG,eAAe,CACzB,+EAA+E,CAChF,CAAA;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QAClD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,GAAG,GAAG,eAAe,CAAC,sDAAsD,CAAC,CAAA;QACnF,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QACrC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,mDAAmD,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,GAAG,GAAG,eAAe,CAAC,kDAAkD,CAAC,CAAA;QAC/E,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;QACzC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,GAAG,GAAG,eAAe,CAAC,gDAAgD,CAAC,CAAA;QAC7E,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAA;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAA;QAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QAE/B,MAAM,MAAM,GAAG,eAAe,CAAC,2BAA2B,CAAC,CAAA;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,GAAG,GAAG,eAAe,CACzB,qFAAqF,CACtF,CAAA;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;QACvC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,KAAK,MAAM,MAAM,IAAI;YACnB,0CAA0C;YAC1C,iCAAiC;YACjC,6BAA6B;YAC7B,sBAAsB;SACvB,EAAE,CAAC;YACF,MAAM,GAAG,GAAG,eAAe,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAA;YACtD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QACnC,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,GAAG,GAAG,eAAe,CACzB,mEAAmE,CACpE,CAAA;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,IAAI,GAAG,QAAQ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;QACtC,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Structural removal of Markdown code blocks from an assistant message, ahead
3
+ * of any redaction.
4
+ *
5
+ * `transcript-content-classes-plan.md` puts assistant code blocks in the
6
+ * highest-risk row it still syncs anything from — "it is the user's code" — and
7
+ * decides they are **stripped by default**, leaving a language-and-line-count
8
+ * placeholder. The same plan is explicit about *how*: "a regex over prose must
9
+ * never be what stands between a code block and the wire". So this walks the
10
+ * message by Markdown block structure and removes whole blocks, and the prose
11
+ * redactor (`./redact-prose.ts`) runs afterwards on what is left — never
12
+ * instead of this.
13
+ *
14
+ * It lives here rather than in the CLI for the reason the plan gives for
15
+ * `redactProse`: shared, so the CLI and any future server-side path cannot
16
+ * drift into different strengths of the same protection.
17
+ *
18
+ * **This deliberately over-strips, and that asymmetry is the design.** Every
19
+ * ambiguous case below resolves toward "treat it as code". Stripping a line of
20
+ * prose costs the grader a sentence; failing to strip a line of code puts the
21
+ * user's source on the wire, which is the one outcome the class table exists to
22
+ * prevent. Two places where that shows:
23
+ *
24
+ * - **Indented blocks are stripped regardless of what precedes them.**
25
+ * CommonMark says an indented chunk cannot interrupt a paragraph, so
26
+ * `Here is the code:\n const key = 'sk-live-…'` is officially a lazy
27
+ * paragraph continuation, not a code block. Following the spec there would
28
+ * leak exactly the text a reader would call code. Any line indented four
29
+ * spaces or a tab outside a fence is therefore code here. The cost is that
30
+ * a hanging-indented prose line, or a list nested four spaces deep, is
31
+ * stripped too.
32
+ * - **An unterminated fence eats the rest of the message.** A message that
33
+ * opens ``` and never closes it is truncated at the fence rather than
34
+ * recovered from, because the alternative is guessing where the author
35
+ * meant the code to end.
36
+ */
37
+ /** What a stripped block leaves behind, and what it cost. */
38
+ export type CodeBlockStripResult = {
39
+ /** The message with every code block replaced by a placeholder. */
40
+ text: string;
41
+ /** How many blocks were removed. */
42
+ blocks: number;
43
+ /** How many lines those blocks contained, excluding fence lines. */
44
+ lines: number;
45
+ };
46
+ /**
47
+ * Replace every fenced and indented code block in `message` with a placeholder.
48
+ *
49
+ * Pure and total: any string is valid input, and the result never contains a
50
+ * line that was inside a code block.
51
+ */
52
+ export declare function stripCodeBlocks(message: string): CodeBlockStripResult;
53
+ //# sourceMappingURL=strip-code-blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip-code-blocks.d.ts","sourceRoot":"","sources":["../src/strip-code-blocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAqBH,6DAA6D;AAC7D,MAAM,MAAM,oBAAoB,GAAG;IACjC,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAmFD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,CA+DrE"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Structural removal of Markdown code blocks from an assistant message, ahead
3
+ * of any redaction.
4
+ *
5
+ * `transcript-content-classes-plan.md` puts assistant code blocks in the
6
+ * highest-risk row it still syncs anything from — "it is the user's code" — and
7
+ * decides they are **stripped by default**, leaving a language-and-line-count
8
+ * placeholder. The same plan is explicit about *how*: "a regex over prose must
9
+ * never be what stands between a code block and the wire". So this walks the
10
+ * message by Markdown block structure and removes whole blocks, and the prose
11
+ * redactor (`./redact-prose.ts`) runs afterwards on what is left — never
12
+ * instead of this.
13
+ *
14
+ * It lives here rather than in the CLI for the reason the plan gives for
15
+ * `redactProse`: shared, so the CLI and any future server-side path cannot
16
+ * drift into different strengths of the same protection.
17
+ *
18
+ * **This deliberately over-strips, and that asymmetry is the design.** Every
19
+ * ambiguous case below resolves toward "treat it as code". Stripping a line of
20
+ * prose costs the grader a sentence; failing to strip a line of code puts the
21
+ * user's source on the wire, which is the one outcome the class table exists to
22
+ * prevent. Two places where that shows:
23
+ *
24
+ * - **Indented blocks are stripped regardless of what precedes them.**
25
+ * CommonMark says an indented chunk cannot interrupt a paragraph, so
26
+ * `Here is the code:\n const key = 'sk-live-…'` is officially a lazy
27
+ * paragraph continuation, not a code block. Following the spec there would
28
+ * leak exactly the text a reader would call code. Any line indented four
29
+ * spaces or a tab outside a fence is therefore code here. The cost is that
30
+ * a hanging-indented prose line, or a list nested four spaces deep, is
31
+ * stripped too.
32
+ * - **An unterminated fence eats the rest of the message.** A message that
33
+ * opens ``` and never closes it is truncated at the fence rather than
34
+ * recovered from, because the alternative is guessing where the author
35
+ * meant the code to end.
36
+ */
37
+ /** Longest info-string word accepted as a language label. */
38
+ const MAX_LANGUAGE_LENGTH = 20;
39
+ /**
40
+ * Characters a language label may contain.
41
+ *
42
+ * The info string is author-controlled free text sitting on the same line as
43
+ * the fence — ```` ```ts title="~/.aws/credentials" ```` is well-formed
44
+ * Markdown. Copying it into the placeholder verbatim would hand back a
45
+ * free-text channel out of the very block this function just removed, so only
46
+ * the first whitespace-delimited word is considered and it must match this
47
+ * shape; anything else yields a placeholder with no language rather than a
48
+ * sanitized approximation of one.
49
+ */
50
+ const LANGUAGE_PATTERN = /^[A-Za-z0-9_+#-]+$/;
51
+ /** Columns a tab advances to, for deciding whether a line is indented code. */
52
+ const TAB_WIDTH = 4;
53
+ /**
54
+ * Render the placeholder that stands in for a removed block.
55
+ *
56
+ * Line count and language only: the plan's class table specifies exactly this
57
+ * pair, and anything more (a first line, a hash, a length in characters) is a
58
+ * fingerprint of the code rather than a description of it. Whether a hash
59
+ * *should* ride along is an open question on the plan and is deliberately not
60
+ * answered here.
61
+ */
62
+ function placeholder(language, lines) {
63
+ const unit = lines === 1 ? 'line' : 'lines';
64
+ return language
65
+ ? `[code block: ${language}, ${lines} ${unit}]`
66
+ : `[code block: ${lines} ${unit}]`;
67
+ }
68
+ /** First word of a fence's info string, when it is a plausible language. */
69
+ function parseLanguage(infoString) {
70
+ const first = infoString.trim().split(/\s+/)[0];
71
+ if (!first || first.length > MAX_LANGUAGE_LENGTH)
72
+ return null;
73
+ return LANGUAGE_PATTERN.test(first) ? first : null;
74
+ }
75
+ /**
76
+ * A Markdown blockquote prefix: up to three spaces, then one or more `>`
77
+ * markers, each optionally followed by a space.
78
+ *
79
+ * Stripped before the fence and indent tests run, because a code block nested
80
+ * in a container is still a code block. Without this, ``` > ```ts ``` matches
81
+ * neither branch — the `>` defeats the fence pattern and the line is only two
82
+ * columns in, so the indent branch misses it too — and every line of the block
83
+ * is copied out verbatim, leaving the prose redactor as the only thing between
84
+ * the user's source and the wire. That is precisely the arrangement the plan
85
+ * forbids ("a regex over prose must never be what stands between a code block
86
+ * and the wire"), and an assistant quoting code back to a user is an ordinary
87
+ * thing to do.
88
+ *
89
+ * Nested quotes (`> > `) collapse the same way, since the test is applied to
90
+ * what remains after the whole prefix.
91
+ */
92
+ const QUOTE_PREFIX_PATTERN = /^ {0,3}(?:>[ \t]?)+/;
93
+ /** The line with any blockquote markers removed, for structural tests. */
94
+ function unquote(line) {
95
+ return line.replace(QUOTE_PREFIX_PATTERN, '');
96
+ }
97
+ /** Leading indentation in columns, counting a tab as up to {@link TAB_WIDTH}. */
98
+ function indentColumns(line) {
99
+ let columns = 0;
100
+ for (const char of line) {
101
+ if (char === ' ')
102
+ columns += 1;
103
+ else if (char === '\t')
104
+ columns += TAB_WIDTH - (columns % TAB_WIDTH);
105
+ else
106
+ break;
107
+ }
108
+ return columns;
109
+ }
110
+ /**
111
+ * A fence opener: up to three spaces of indent, then three or more backticks or
112
+ * tildes. Four spaces would make it indented code instead, which the caller
113
+ * handles.
114
+ */
115
+ const FENCE_PATTERN = /^ {0,3}(`{3,}|~{3,})(.*)$/;
116
+ /**
117
+ * Whether `line` closes a fence opened with `marker`.
118
+ *
119
+ * CommonMark's rule, and it matters: a closing fence must be at least as long
120
+ * as its opener and carry no info string, so ``` inside a ````-fenced block
121
+ * does not end it. Getting this wrong in the lenient direction would end the
122
+ * block early and emit its remaining lines as prose.
123
+ */
124
+ function closesFence(line, marker) {
125
+ const match = FENCE_PATTERN.exec(unquote(line));
126
+ if (!match)
127
+ return false;
128
+ const [, fence, rest] = match;
129
+ if (!fence || fence[0] !== marker[0])
130
+ return false;
131
+ return fence.length >= marker.length && rest !== undefined && rest.trim() === '';
132
+ }
133
+ /**
134
+ * Replace every fenced and indented code block in `message` with a placeholder.
135
+ *
136
+ * Pure and total: any string is valid input, and the result never contains a
137
+ * line that was inside a code block.
138
+ */
139
+ export function stripCodeBlocks(message) {
140
+ const source = message.split('\n');
141
+ const out = [];
142
+ let blocks = 0;
143
+ let lines = 0;
144
+ let index = 0;
145
+ while (index < source.length) {
146
+ const line = source[index] ?? '';
147
+ // Structural tests run on the line with any container prefix removed; the
148
+ // *original* line is what gets emitted when it turns out to be prose.
149
+ const bare = unquote(line);
150
+ const fence = indentColumns(bare) < 4 ? FENCE_PATTERN.exec(bare) : null;
151
+ if (fence) {
152
+ const marker = fence[1] ?? '```';
153
+ const language = parseLanguage(fence[2] ?? '');
154
+ let cursor = index + 1;
155
+ let body = 0;
156
+ while (cursor < source.length && !closesFence(source[cursor] ?? '', marker)) {
157
+ body += 1;
158
+ cursor += 1;
159
+ }
160
+ out.push(placeholder(language, body));
161
+ blocks += 1;
162
+ lines += body;
163
+ // Past the closing fence, or past the end when there was none — an
164
+ // unterminated fence consumes the remainder rather than recovering.
165
+ index = cursor + 1;
166
+ continue;
167
+ }
168
+ if (indentColumns(bare) >= 4 && bare.trim() !== '') {
169
+ let cursor = index;
170
+ let body = 0;
171
+ // Blank lines *inside* an indented run belong to the block, so a chunk
172
+ // separated by an empty line is one placeholder rather than two. A blank
173
+ // line is only a terminator once a non-indented line follows it.
174
+ while (cursor < source.length) {
175
+ const current = unquote(source[cursor] ?? '');
176
+ if (current.trim() === '') {
177
+ const next = unquote(source[cursor + 1] ?? '');
178
+ if (next.trim() === '' || indentColumns(next) < 4)
179
+ break;
180
+ cursor += 1;
181
+ body += 1;
182
+ continue;
183
+ }
184
+ if (indentColumns(current) < 4)
185
+ break;
186
+ cursor += 1;
187
+ body += 1;
188
+ }
189
+ out.push(placeholder(null, body));
190
+ blocks += 1;
191
+ lines += body;
192
+ index = cursor;
193
+ continue;
194
+ }
195
+ out.push(line);
196
+ index += 1;
197
+ }
198
+ return { text: out.join('\n'), blocks, lines };
199
+ }
200
+ //# sourceMappingURL=strip-code-blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip-code-blocks.js","sourceRoot":"","sources":["../src/strip-code-blocks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=strip-code-blocks.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip-code-blocks.test.d.ts","sourceRoot":"","sources":["../src/strip-code-blocks.test.ts"],"names":[],"mappings":""}