@profullstack/readm3 0.11.0 → 0.12.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 +54 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/cloud-cli.d.ts +1 -1
- package/dist/cloud-cli.d.ts.map +1 -1
- package/dist/cloud-cli.js +30 -7
- package/dist/cloud-cli.js.map +1 -1
- package/dist/diff.d.ts +31 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +83 -0
- package/dist/diff.js.map +1 -0
- package/dist/mcp.js +2 -2
- package/dist/mcp.js.map +1 -1
- package/dist/sensitive.d.ts +34 -0
- package/dist/sensitive.d.ts.map +1 -0
- package/dist/sensitive.js +123 -0
- package/dist/sensitive.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -299,6 +299,23 @@ JSON without saying so; `--language` (or `language` in the API) forces one. The
|
|
|
299
299
|
and `DELETE /api/v1/pastes/<token>`, and the `paste_create`, `paste_get` and
|
|
300
300
|
`paste_delete` MCP tools; each answer carries `language` and `mime`.
|
|
301
301
|
|
|
302
|
+
### Is it safe to share?
|
|
303
|
+
|
|
304
|
+
Every way of making a link checks the file first: the paste page, the editor's Paste
|
|
305
|
+
link and Share dialogs, `readm3 paste`, `readm3 share` and the API. A **secret** (a
|
|
306
|
+
private key, an OpenAI, Anthropic, GitHub, AWS, Stripe, Slack or npm token, a JWT, a
|
|
307
|
+
password in a URL or in a `PASSWORD=` style setting) gets a red "Not safe to share"
|
|
308
|
+
notice, and the button waits until you tick "I know, share it anyway"; the CLI stops
|
|
309
|
+
and needs `--force`. **Personal details** (an email address, a public IP, a home
|
|
310
|
+
directory that names your account) get a caution and nothing stops. Matches are
|
|
311
|
+
reported with their line, and secrets are masked (`sk-p…N4`), so the warning never
|
|
312
|
+
repeats the secret.
|
|
313
|
+
|
|
314
|
+
`POST /api/v1/pastes` and `shares_create` answer with a `sensitive` report of the
|
|
315
|
+
same scan (`level` is `"secret"`, `"personal"` or `null`, plus `findings`); the API
|
|
316
|
+
reports and never refuses, so a script decides for itself. A clean scan is not a
|
|
317
|
+
guarantee: the check knows common shapes, not every secret.
|
|
318
|
+
|
|
302
319
|
## Editor
|
|
303
320
|
|
|
304
321
|
Open https://readm3.com/viewer for a plain, fast text editor in your browser, with the
|
|
@@ -353,13 +370,49 @@ directly with no credentials or server proxy. Local files are uploaded only when
|
|
|
353
370
|
|
|
354
371
|
Imports are limited to 4 MB per file, 20 MB per workspace, and 1,000 files.
|
|
355
372
|
|
|
373
|
+
### File history and AI summaries
|
|
374
|
+
|
|
375
|
+
Every file on the device keeps a rolling history (History in the toolbar, or
|
|
376
|
+
`File: History` in the palette): a version each time it is opened, saved, restored,
|
|
377
|
+
or **changes on disk underneath the editor**. A file opened from disk is checked
|
|
378
|
+
every few seconds and on window focus, so a generated file (a build's `output.json`,
|
|
379
|
+
a log, a lockfile) that is rewritten by something else shows up as a new version; with
|
|
380
|
+
no local edits it is reloaded, with local edits the disk version waits in History. The
|
|
381
|
+
newest 50 versions are kept, up to 8 MB per file. Each version shows when and why it
|
|
382
|
+
was recorded, `+added −removed` against the one before, and the changed lines, and can
|
|
383
|
+
be restored. All of that is free and never leaves the device.
|
|
384
|
+
|
|
385
|
+
**AI summaries** are the paid part: one click writes a short abstract of a version's
|
|
386
|
+
change plus the specific edits. They are pay as you go from a prepaid balance (top up
|
|
387
|
+
$5, $10 or $25 through CoinPay, in USDC, USDT, BTC, ETH, SOL or POL; the balance never
|
|
388
|
+
expires). Only the changed lines are sent, never the whole file. Each summary is charged
|
|
389
|
+
at a multiple of what the model call cost; the multiple is a two-arm price experiment
|
|
390
|
+
(2x or 4x), assigned once per account. A refused or failed call is not charged.
|
|
391
|
+
|
|
392
|
+
| Endpoint | |
|
|
393
|
+
| --- | --- |
|
|
394
|
+
| `GET /api/v1/billing` | balance, price arm and multiplier, recent ledger |
|
|
395
|
+
| `POST /api/v1/billing/topups` `{ amountUsd, chain? }` | starts a CoinPay payment, returns `payUrl` |
|
|
396
|
+
| `GET /api/v1/billing/topups/<id>` | `pending` or `paid` |
|
|
397
|
+
| `POST /api/v1/summaries` `{ path, before, after }` | the abstract, `chargedMicros`, new balance |
|
|
398
|
+
| `GET /api/v1/billing/experiment` | admins: per arm accounts, payers, top-ups, summaries, revenue, model cost |
|
|
399
|
+
| `POST /api/v1/billing/coinpay/webhook` | CoinPay's signed webhook (`t=…,v1=` HMAC-SHA256) |
|
|
400
|
+
|
|
401
|
+
Server configuration: `ANTHROPIC_API_KEY` turns summaries on (`READM3_SUMMARY_MODEL`,
|
|
402
|
+
default `claude-opus-5-5`, run at low effort); `COINPAY_API_KEY`, `COINPAY_BUSINESS_ID`
|
|
403
|
+
and `COINPAY_WEBHOOK_SECRET` open top-ups (`COINPAY_API_URL` defaults to
|
|
404
|
+
coinpayportal.com). Without them the history still works and the paid parts say so.
|
|
405
|
+
|
|
356
406
|
### Desktop app
|
|
357
407
|
|
|
358
408
|
The same editor in its own window, for Linux x64, from the
|
|
359
409
|
[latest release](https://github.com/profullstack/readm3/releases/latest):
|
|
360
410
|
`readm3-linux-x86_64.AppImage` (`chmod +x`, run it) or `readm3-linux-x86_64.flatpak`
|
|
361
411
|
(`flatpak install --user readm3-linux-x86_64.flatpak`), checksums in `SHA256SUMS`.
|
|
362
|
-
`install.sh --desktop` installs the AppImage with a menu entry
|
|
412
|
+
`install.sh --desktop` installs the AppImage with a menu entry; on a system without
|
|
413
|
+
libfuse2 (Ubuntu 26.04 ships only fuse3), it unpacks the app instead, since an AppImage
|
|
414
|
+
cannot mount itself there. Running a downloaded AppImage by hand on such a system needs
|
|
415
|
+
`--appimage-extract-and-run` or `sudo apt install libfuse2t64`.
|
|
363
416
|
|
|
364
417
|
```sh
|
|
365
418
|
readm3-desktop notes.md src/app.ts # opens them as tabs; Ctrl+S saves back
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ColorMode } from "./print.ts";
|
|
2
2
|
import { type ViewerOptions } from "./viewer.ts";
|
|
3
|
-
export declare const VERSION = "0.
|
|
3
|
+
export declare const VERSION = "0.12.0";
|
|
4
4
|
/** The help text, exported so a test can hold it to the flags it documents. */
|
|
5
5
|
export declare const USAGE: string;
|
|
6
6
|
export interface ParsedArgs extends ViewerOptions {
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import { FLAVORS, isFlavor } from "./flavors.js";
|
|
|
9
9
|
import { printDocument, COLOR_MODES } from "./print.js";
|
|
10
10
|
import { run } from "./viewer.js";
|
|
11
11
|
import { isCloudCommand, cloudMain, CLOUD_USAGE } from "./cloud-cli.js";
|
|
12
|
-
export const VERSION = "0.
|
|
12
|
+
export const VERSION = "0.12.0";
|
|
13
13
|
/** The help text, exported so a test can hold it to the flags it documents. */
|
|
14
14
|
export const USAGE = `readm3 — a terminal markdown reader and editor
|
|
15
15
|
|
package/dist/cloud-cli.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const CLOUD_USAGE = "Shared Markdown\n readm3 login --token-stdin Save a personal API token securely\n readm3 login --coinpay Sign in with CoinPay in the browser; saves a token\n readm3 logout Remove the local token\n readm3 share FILE [--org ID] [--role view|edit]\n readm3 docs list [--org ID] [--search TEXT] [--limit N] [--offset N]\n readm3 docs get ID [--raw]\n readm3 docs create FILE [--org ID] [--title NAME]\n readm3 docs update ID FILE --base VERSION\n readm3 docs delete ID\n readm3 docs history ID\n readm3 docs restore ID --version VERSION --base CURRENT\n readm3 docs share ID [--role view|edit] [--version VERSION]\n readm3 docs revoke ID --share SHARE_ID\n readm3 docs transfer ID --username USERNAME\n readm3 shared get URL [--raw]\n readm3 paste [FILE] [--title NAME] [--expires 1h|1d|7d|30d] [--language ID]\n Private link, no account; prints the URL.\n Any text: Markdown renders, code is highlighted.\n The language is detected from the name or content.\n readm3 paste get URL [--raw] | delete URL\n readm3 shared update URL FILE --base VERSION\n readm3 orgs list | create --name NAME | update ID --name NAME | delete ID\n readm3 teams list --org ID | create --org ID --name NAME\n readm3 members list --org ID\n readm3 cloud OPERATION --args '{\"key\":\"value\"}'\n readm3 mcp Start the stdio MCP server\n\nWithout --org a document goes to your personal workspace.\nFILE may be - for stdin. --raw prints the source text; other results are JSON.\nREADM3_URL selects a self-hosted server; READM3_TOKEN supplies an API token.\nView links cannot write. Edit links can save versions. Owners administer files.\nUse readm3 cloud for the full API, including team membership and permissions.\n";
|
|
1
|
+
export declare const CLOUD_USAGE = "Shared Markdown\n readm3 login --token-stdin Save a personal API token securely\n readm3 login --coinpay Sign in with CoinPay in the browser; saves a token\n readm3 logout Remove the local token\n readm3 share FILE [--org ID] [--role view|edit] [--force]\n readm3 docs list [--org ID] [--search TEXT] [--limit N] [--offset N]\n readm3 docs get ID [--raw]\n readm3 docs create FILE [--org ID] [--title NAME]\n readm3 docs update ID FILE --base VERSION\n readm3 docs delete ID\n readm3 docs history ID\n readm3 docs restore ID --version VERSION --base CURRENT\n readm3 docs share ID [--role view|edit] [--version VERSION]\n readm3 docs revoke ID --share SHARE_ID\n readm3 docs transfer ID --username USERNAME\n readm3 shared get URL [--raw]\n readm3 paste [FILE] [--title NAME] [--expires 1h|1d|7d|30d] [--language ID] [--force]\n Private link, no account; prints the URL.\n Any text: Markdown renders, code is highlighted.\n The language is detected from the name or content.\n readm3 paste get URL [--raw] | delete URL\n readm3 shared update URL FILE --base VERSION\n readm3 orgs list | create --name NAME | update ID --name NAME | delete ID\n readm3 teams list --org ID | create --org ID --name NAME\n readm3 members list --org ID\n readm3 cloud OPERATION --args '{\"key\":\"value\"}'\n readm3 mcp Start the stdio MCP server\n\nWithout --org a document goes to your personal workspace.\nFILE may be - for stdin. --raw prints the source text; other results are JSON.\nREADM3_URL selects a self-hosted server; READM3_TOKEN supplies an API token.\nView links cannot write. Edit links can save versions. Owners administer files.\npaste and share check the file first: a key, token or password stops them unless\n--force is given; an email, IP or home directory is only pointed out.\nUse readm3 cloud for the full API, including team membership and permissions.\n";
|
|
2
2
|
export declare function isCloudCommand(command: string | undefined): boolean;
|
|
3
3
|
export declare function cloudMain(argv: string[]): Promise<void>;
|
|
4
4
|
//# sourceMappingURL=cloud-cli.d.ts.map
|
package/dist/cloud-cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-cli.d.ts","sourceRoot":"","sources":["../src/cloud-cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloud-cli.d.ts","sourceRoot":"","sources":["../src/cloud-cli.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,WAAW,+iEAmCvB,CAAC;AAcF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,WAEzD;AACD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,iBAkM7C"}
|
package/dist/cloud-cli.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { pasteLocation } from "./cloud-client.js";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { basename } from "node:path";
|
|
4
|
+
import { describeSensitive, scanSensitive } from "./sensitive.js";
|
|
4
5
|
import { cloudAction, cloudConfig, cloudRequest, clearCloudConfig, saveCloudConfig, sharedLocation, } from "./cloud-client.js";
|
|
5
6
|
export const CLOUD_USAGE = `Shared Markdown
|
|
6
7
|
readm3 login --token-stdin Save a personal API token securely
|
|
7
8
|
readm3 login --coinpay Sign in with CoinPay in the browser; saves a token
|
|
8
9
|
readm3 logout Remove the local token
|
|
9
|
-
readm3 share FILE [--org ID] [--role view|edit]
|
|
10
|
+
readm3 share FILE [--org ID] [--role view|edit] [--force]
|
|
10
11
|
readm3 docs list [--org ID] [--search TEXT] [--limit N] [--offset N]
|
|
11
12
|
readm3 docs get ID [--raw]
|
|
12
13
|
readm3 docs create FILE [--org ID] [--title NAME]
|
|
@@ -18,7 +19,7 @@ export const CLOUD_USAGE = `Shared Markdown
|
|
|
18
19
|
readm3 docs revoke ID --share SHARE_ID
|
|
19
20
|
readm3 docs transfer ID --username USERNAME
|
|
20
21
|
readm3 shared get URL [--raw]
|
|
21
|
-
readm3 paste [FILE] [--title NAME] [--expires 1h|1d|7d|30d] [--language ID]
|
|
22
|
+
readm3 paste [FILE] [--title NAME] [--expires 1h|1d|7d|30d] [--language ID] [--force]
|
|
22
23
|
Private link, no account; prints the URL.
|
|
23
24
|
Any text: Markdown renders, code is highlighted.
|
|
24
25
|
The language is detected from the name or content.
|
|
@@ -34,6 +35,8 @@ Without --org a document goes to your personal workspace.
|
|
|
34
35
|
FILE may be - for stdin. --raw prints the source text; other results are JSON.
|
|
35
36
|
READM3_URL selects a self-hosted server; READM3_TOKEN supplies an API token.
|
|
36
37
|
View links cannot write. Edit links can save versions. Owners administer files.
|
|
38
|
+
paste and share check the file first: a key, token or password stops them unless
|
|
39
|
+
--force is given; an email, IP or home directory is only pointed out.
|
|
37
40
|
Use readm3 cloud for the full API, including team membership and permissions.
|
|
38
41
|
`;
|
|
39
42
|
const commands = new Set([
|
|
@@ -69,7 +72,7 @@ export async function cloudMain(argv) {
|
|
|
69
72
|
const value = argv[i];
|
|
70
73
|
if (value.startsWith("--")) {
|
|
71
74
|
const name = value.slice(2);
|
|
72
|
-
if (["raw", "token-stdin", "json", "coinpay"].includes(name))
|
|
75
|
+
if (["raw", "token-stdin", "json", "coinpay", "force"].includes(name))
|
|
73
76
|
flags[name] = "true";
|
|
74
77
|
else {
|
|
75
78
|
if (!argv[i + 1] || argv[i + 1].startsWith("--"))
|
|
@@ -81,6 +84,18 @@ export async function cloudMain(argv) {
|
|
|
81
84
|
positional.push(value);
|
|
82
85
|
}
|
|
83
86
|
const output = (value) => process.stdout.write(JSON.stringify(value, null, 2) + "\n");
|
|
87
|
+
// Is it safe to share? Asked before anything leaves the machine. A secret stops the
|
|
88
|
+
// command unless --force; personal details are only pointed out, on stderr.
|
|
89
|
+
const warn = (report) => {
|
|
90
|
+
for (const line of describeSensitive(report))
|
|
91
|
+
process.stderr.write(`readm3: ${line}\n`);
|
|
92
|
+
};
|
|
93
|
+
const checkSensitive = (source) => {
|
|
94
|
+
const report = scanSensitive(source);
|
|
95
|
+
warn(report);
|
|
96
|
+
if (report.level === "secret" && !flags.force)
|
|
97
|
+
throw new Error("This looks like it holds a secret, and anyone with the link could read it. Remove it, or pass --force to share anyway.");
|
|
98
|
+
};
|
|
84
99
|
const fileSource = (file) => {
|
|
85
100
|
if (!file)
|
|
86
101
|
throw new Error("A Markdown file is required.");
|
|
@@ -124,6 +139,7 @@ export async function cloudMain(argv) {
|
|
|
124
139
|
throw new Error("Give a file, or pipe one in.");
|
|
125
140
|
const file = positional[0] ?? "-";
|
|
126
141
|
const source = fileSource(file);
|
|
142
|
+
checkSensitive(source);
|
|
127
143
|
// The file name carries the language; stdin has none, so the server sniffs the content.
|
|
128
144
|
const title = flags.title || (file === "-" ? undefined : basename(file));
|
|
129
145
|
const paste = await cloudRequest("pastes", "POST", { source, title, expiresIn: flags.expires, language: flags.language }, cloudConfig());
|
|
@@ -176,19 +192,22 @@ export async function cloudMain(argv) {
|
|
|
176
192
|
user: "userId",
|
|
177
193
|
};
|
|
178
194
|
for (const [name, value] of Object.entries(flags))
|
|
179
|
-
if (!["raw", "json", "coinpay"].includes(name))
|
|
195
|
+
if (!["raw", "json", "coinpay", "force"].includes(name))
|
|
180
196
|
args[names[name] || name] = value;
|
|
181
197
|
if (command === "share") {
|
|
182
198
|
const file = positional[0];
|
|
199
|
+
const source = fileSource(file);
|
|
200
|
+
checkSensitive(source);
|
|
183
201
|
const doc = await cloudAction("documents_create", {
|
|
184
202
|
...args,
|
|
185
203
|
title: flags.title || basename(file || "Document.md"),
|
|
186
|
-
source
|
|
204
|
+
source,
|
|
187
205
|
});
|
|
188
|
-
|
|
206
|
+
const { sensitive: _, ...link } = await cloudAction("shares_create", {
|
|
189
207
|
documentId: doc.id,
|
|
190
208
|
role: flags.role || "view",
|
|
191
|
-
})
|
|
209
|
+
});
|
|
210
|
+
output(link);
|
|
192
211
|
return;
|
|
193
212
|
}
|
|
194
213
|
const [verb, identifier, file] = positional;
|
|
@@ -217,6 +236,10 @@ export async function cloudMain(argv) {
|
|
|
217
236
|
if (verb === "update")
|
|
218
237
|
args.source = fileSource(file);
|
|
219
238
|
const result = await cloudAction(op, args);
|
|
239
|
+
if (result.sensitive?.level) {
|
|
240
|
+
warn(result.sensitive);
|
|
241
|
+
process.stderr.write("readm3: the link is live; readm3 docs revoke ID --share SHARE_ID takes it back.\n");
|
|
242
|
+
}
|
|
220
243
|
if (flags.raw && result.version)
|
|
221
244
|
process.stdout.write(result.version.source);
|
|
222
245
|
else
|
package/dist/cloud-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-cli.js","sourceRoot":"","sources":["../src/cloud-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,MAAM,CAAC,MAAM,WAAW,GAAG
|
|
1
|
+
{"version":3,"file":"cloud-cli.js","sourceRoot":"","sources":["../src/cloud-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AACxF,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmC1B,CAAC;AACF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC;IACvB,OAAO;IACP,QAAQ;IACR,OAAO;IACP,MAAM;IACN,QAAQ;IACR,OAAO;IACP,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,KAAK;CACN,CAAC,CAAC;AACH,MAAM,UAAU,cAAc,CAAC,OAA2B;IACxD,OAAO,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,MAAM,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;iBACvF,CAAC;gBACJ,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,UAAU,CAAC,IAAI,CAAC;oBAC/C,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,iBAAiB,CAAC,CAAC;gBAC7C,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAE,CAAC;YAC3B,CAAC;QACH,CAAC;;YAAM,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE,CAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9D,oFAAoF;IACpF,4EAA4E;IAC5E,MAAM,IAAI,GAAG,CAAC,MAAuB,EAAE,EAAE;QACvC,KAAK,MAAM,IAAI,IAAI,iBAAiB,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC;IAC1F,CAAC,CAAC;IACF,MAAM,cAAc,GAAG,CAAC,MAAc,EAAE,EAAE;QACxC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,CAAC;QACb,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,KAAK;YAC3C,MAAM,IAAI,KAAK,CAAC,wHAAwH,CAAC,CAAC;IAC9I,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,IAAwB,EAAE,EAAE;QAC9C,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5D,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI;YACxC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;YACzC,MAAM,IAAI,KAAK,CACb,yIAAyI,CAC1I,CAAC;QACJ,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO;YACzB,CAAC,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC3E,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,YAAY,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACzD,eAAe,CAAC,MAAM,CAAC,CAAC;QACxB,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC1D,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAChE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,YAAY,CAAC,UAAU,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;gBACnE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAqB,UAAU,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;YAClG,IAAI,KAAK,CAAC,GAAG;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;;gBAC7C,MAAM,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK;YACvC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QAClC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,wFAAwF;QACxF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B,QAAQ,EACR,MAAM,EACN,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,EACrE,WAAW,EAAE,CACd,CAAC;QACF,IAAI,KAAK,CAAC,IAAI;YAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,gBAAgB,EAAE,CAAC;QACnB,MAAM,CAAC;YACL,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,wDAAwD;SAC/D,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,CAAC,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC;QACrC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAK,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAChE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,UAAU,KAAK,EAAE,EACjB,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EACnC,IAAI,KAAK,QAAQ;YACf,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE;YACvD,CAAC,CAAC,SAAS,EACb,MAAM,CACP,CAAC;QACF,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAK,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,IAAI,KAAK,CAAC,GAAG;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;;YACtD,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,MAAM,KAAK,GAA2B;QACpC,GAAG,EAAE,OAAO;QACZ,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,WAAW;QACpB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,QAAQ;KACf,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;QAC/C,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC;IAC7F,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,MAAM,GAAG,GAAG,MAAM,WAAW,CAAiB,kBAAkB,EAAE;YAChE,GAAG,IAAI;YACP,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,IAAI,aAAa,CAAC;YACrD,MAAM;SACP,CAAC,CAAC;QACH,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,WAAW,CAAiC,eAAe,EAAE;YACnG,UAAU,EAAE,GAAG,CAAC,EAAE;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,MAAM;SAC3B,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,CAAC;QACb,OAAO;IACT,CAAC;IACD,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC;IAC5C,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,UAAU,GAA2B;YACzC,IAAI,EAAE,gBAAgB;YACtB,GAAG,EAAE,eAAe;YACpB,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,kBAAkB;YAC1B,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,kBAAkB;YAC3B,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,eAAe;YACvB,QAAQ,EAAE,oBAAoB;SAC/B,CAAC;QACF,MAAM,EAAE,GAAG,UAAU,CAAC,IAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,IAAI,aAAa,CAAC,CAAC;QACpE,CAAC;aAAM,IAAI,IAAI,KAAK,MAAM;YAAE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QACzD,IAAI,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,EAAE,EACF,IAAI,CACL,CAAC;QACF,IAAI,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mFAAmF,CAAC,CAAC;QAC5G,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO;YAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;;YACzC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAK,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/B,IAAI,UAAU;QACZ,IAAI,CACF,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CACzE,GAAG,UAAU,CAAC;IACjB,MAAM,CAAC,MAAM,WAAW,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;AACvD,CAAC"}
|
package/dist/diff.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A line diff for file history: what changed between two versions, as hunks of
|
|
3
|
+
* removed and added lines with their positions. Shared by the browser (change counts
|
|
4
|
+
* and snippets in the history panel) and the server (the AI summary is asked about
|
|
5
|
+
* the hunks, not the whole file).
|
|
6
|
+
*
|
|
7
|
+
* The common head and tail are trimmed first, which is most of any real edit; the
|
|
8
|
+
* changed middle is aligned by longest common subsequence. A middle too large to
|
|
9
|
+
* align cheaply is reported as replaced wholesale, which is still the truth.
|
|
10
|
+
*/
|
|
11
|
+
export interface Hunk {
|
|
12
|
+
/** 1-based line in the old version where the hunk starts. */
|
|
13
|
+
oldStart: number;
|
|
14
|
+
/** 1-based line in the new version where the hunk starts. */
|
|
15
|
+
newStart: number;
|
|
16
|
+
removed: string[];
|
|
17
|
+
added: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface Diff {
|
|
20
|
+
hunks: Hunk[];
|
|
21
|
+
added: number;
|
|
22
|
+
removed: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const lines: (text: string) => string[];
|
|
25
|
+
export declare function diffLines(before: string, after: string): Diff;
|
|
26
|
+
/**
|
|
27
|
+
* A few changed lines to show for a version, removals first in each hunk, each
|
|
28
|
+
* marked + or -, trimmed to a readable width. Empty when nothing changed.
|
|
29
|
+
*/
|
|
30
|
+
export declare function snippet(diff: Diff, maxLines?: number, width?: number): string[];
|
|
31
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,IAAI;IACnB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AACD,MAAM,WAAW,IAAI;IAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;CAAE;AAKxE,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MAAM,EAAiE,CAAC;AAE7G,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAsB7D;AA6BD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,SAAI,EAAE,KAAK,SAAM,GAAG,MAAM,EAAE,CAQvE"}
|
package/dist/diff.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** Cells in the alignment table; past this the middle is reported as replaced. */
|
|
2
|
+
const MAX_CELLS = 4_000_000;
|
|
3
|
+
export const lines = (text) => text === "" ? [] : text.replace(/\r\n?/g, "\n").split("\n");
|
|
4
|
+
export function diffLines(before, after) {
|
|
5
|
+
const a = lines(before);
|
|
6
|
+
const b = lines(after);
|
|
7
|
+
let head = 0;
|
|
8
|
+
while (head < a.length && head < b.length && a[head] === b[head])
|
|
9
|
+
head++;
|
|
10
|
+
let tail = 0;
|
|
11
|
+
while (tail < a.length - head && tail < b.length - head && a[a.length - 1 - tail] === b[b.length - 1 - tail])
|
|
12
|
+
tail++;
|
|
13
|
+
const oldMiddle = a.slice(head, a.length - tail);
|
|
14
|
+
const newMiddle = b.slice(head, b.length - tail);
|
|
15
|
+
const hunks = [];
|
|
16
|
+
if (oldMiddle.length || newMiddle.length) {
|
|
17
|
+
if (!oldMiddle.length || !newMiddle.length || (oldMiddle.length + 1) * (newMiddle.length + 1) > MAX_CELLS) {
|
|
18
|
+
hunks.push({ oldStart: head + 1, newStart: head + 1, removed: oldMiddle, added: newMiddle });
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
hunks.push(...align(oldMiddle, newMiddle, head));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
hunks,
|
|
26
|
+
added: hunks.reduce((sum, hunk) => sum + hunk.added.length, 0),
|
|
27
|
+
removed: hunks.reduce((sum, hunk) => sum + hunk.removed.length, 0),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** LCS over the changed middle; lines are interned to numbers so comparisons are cheap. */
|
|
31
|
+
function align(a, b, offset) {
|
|
32
|
+
const ids = new Map();
|
|
33
|
+
const intern = (line) => { let n = ids.get(line); if (n === undefined)
|
|
34
|
+
ids.set(line, n = ids.size); return n; };
|
|
35
|
+
const x = a.map(intern);
|
|
36
|
+
const y = b.map(intern);
|
|
37
|
+
const width = y.length + 1;
|
|
38
|
+
// table[i][j] = LCS length of x[i..] and y[j..], filled from the end.
|
|
39
|
+
const table = new Uint32Array((x.length + 1) * width);
|
|
40
|
+
for (let i = x.length - 1; i >= 0; i--) {
|
|
41
|
+
for (let j = y.length - 1; j >= 0; j--) {
|
|
42
|
+
table[i * width + j] = x[i] === y[j] ? table[(i + 1) * width + j + 1] + 1 : Math.max(table[(i + 1) * width + j], table[i * width + j + 1]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const hunks = [];
|
|
46
|
+
let open = null;
|
|
47
|
+
let i = 0;
|
|
48
|
+
let j = 0;
|
|
49
|
+
const start = () => open ??= (hunks.push({ oldStart: offset + i + 1, newStart: offset + j + 1, removed: [], added: [] }), hunks.at(-1));
|
|
50
|
+
while (i < x.length || j < y.length) {
|
|
51
|
+
if (i < x.length && j < y.length && x[i] === y[j]) {
|
|
52
|
+
open = null;
|
|
53
|
+
i++;
|
|
54
|
+
j++;
|
|
55
|
+
}
|
|
56
|
+
else if (j < y.length && (i === x.length || table[i * width + j + 1] >= table[(i + 1) * width + j])) {
|
|
57
|
+
start().added.push(b[j]);
|
|
58
|
+
j++;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
start().removed.push(a[i]);
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return hunks;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A few changed lines to show for a version, removals first in each hunk, each
|
|
69
|
+
* marked + or -, trimmed to a readable width. Empty when nothing changed.
|
|
70
|
+
*/
|
|
71
|
+
export function snippet(diff, maxLines = 6, width = 120) {
|
|
72
|
+
const out = [];
|
|
73
|
+
for (const hunk of diff.hunks) {
|
|
74
|
+
for (const line of hunk.removed)
|
|
75
|
+
out.push(`- ${line}`);
|
|
76
|
+
for (const line of hunk.added)
|
|
77
|
+
out.push(`+ ${line}`);
|
|
78
|
+
if (out.length >= maxLines)
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
return out.slice(0, maxLines).map((line) => line.length > width ? `${line.slice(0, width - 1)}…` : line);
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=diff.js.map
|
package/dist/diff.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp.js
CHANGED
|
@@ -5,7 +5,7 @@ import { cloudAction, cloudRequest, pasteLocation, sharedLocation } from "./clou
|
|
|
5
5
|
const string = { type: "string" };
|
|
6
6
|
const role = { type: "string", enum: ["view", "edit"] };
|
|
7
7
|
const definitions = [
|
|
8
|
-
["paste_create", "Create an anonymous paste: any text file behind a secret link, no account needed. Markdown renders as a document; code (JSON, JavaScript, Python, YAML, SQL and 30 more) is highlighted with folding. The language is detected from the title's extension, else from the content; pass language to force one. Expires after 7 days by default (1h, 1d, 7d or 30d), 256 KB at most. Returns the URL and a raw URL; keep them, the server cannot show them again.", { source: string, title: { type: "string", description: "A file name; its extension decides the language." }, language: { type: "string", description: "A highlight.js name such as json, javascript, python, bash, yaml or markdown. Detected when omitted." }, expiresIn: { type: "string", enum: ["1h", "1d", "7d", "30d"] } }, ["source"]],
|
|
8
|
+
["paste_create", "Create an anonymous paste: any text file behind a secret link, no account needed. Markdown renders as a document; code (JSON, JavaScript, Python, YAML, SQL and 30 more) is highlighted with folding. The language is detected from the title's extension, else from the content; pass language to force one. Expires after 7 days by default (1h, 1d, 7d or 30d), 256 KB at most. Returns the URL and a raw URL; keep them, the server cannot show them again. The result's sensitive field lists any key, token, password, email address, public IP or named home directory in what the link exposes (secrets masked); when its level is \"secret\", tell the user before passing the link on.", { source: string, title: { type: "string", description: "A file name; its extension decides the language." }, language: { type: "string", description: "A highlight.js name such as json, javascript, python, bash, yaml or markdown. Detected when omitted." }, expiresIn: { type: "string", enum: ["1h", "1d", "7d", "30d"] } }, ["source"]],
|
|
9
9
|
["paste_get", "Read an anonymous paste by its URL. Returns the source with its title, language and mime type.", { url: string }, ["url"]],
|
|
10
10
|
["paste_delete", "Delete an anonymous paste by its URL. The link stops working for everyone.", { url: string }, ["url"]],
|
|
11
11
|
["settings_get", "Read the verified account's latest settings and Markdown workspace snapshot, including its revision.", {}, []],
|
|
@@ -185,7 +185,7 @@ const definitions = [
|
|
|
185
185
|
],
|
|
186
186
|
[
|
|
187
187
|
"shares_create",
|
|
188
|
-
"Create a bearer link granting view (default) or edit access. Owners only. Pinned versions are view-only.",
|
|
188
|
+
"Create a bearer link granting view (default) or edit access. Owners only. Pinned versions are view-only. The result's sensitive field lists any key, token, password, email address, public IP or named home directory in what the link exposes (secrets masked); when its level is \"secret\", tell the user before passing the link on.",
|
|
189
189
|
{
|
|
190
190
|
documentId: string,
|
|
191
191
|
role,
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC7F,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAClC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AACxD,MAAM,WAAW,GAA0D;IACzE,CAAC,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is this safe to share? A scan for what should not leave the machine.
|
|
3
|
+
*
|
|
4
|
+
* Two levels. A secret (a private key, an API token, a password, a JWT, a URL with
|
|
5
|
+
* credentials in it) lets whoever reads the link act as you, so every surface stops
|
|
6
|
+
* and asks before it shares one. Personal details (an email address, a public IP, a
|
|
7
|
+
* home directory that names your account) only identify you, so they are pointed out
|
|
8
|
+
* and nothing stops.
|
|
9
|
+
*
|
|
10
|
+
* The page, the API, the CLI and MCP all run this same scan, so they agree. It is a
|
|
11
|
+
* warning, never a guarantee: a clean scan does not prove a file is safe, and every
|
|
12
|
+
* match comes back masked, so the warning itself never repeats a secret.
|
|
13
|
+
*/
|
|
14
|
+
export type SensitiveLevel = "secret" | "personal";
|
|
15
|
+
export type SensitiveFinding = {
|
|
16
|
+
level: SensitiveLevel;
|
|
17
|
+
/** What was found, as a phrase: "an OpenAI API key". */
|
|
18
|
+
label: string;
|
|
19
|
+
/** The first line it is on, from 1. */
|
|
20
|
+
line: number;
|
|
21
|
+
/** How many times it occurs. */
|
|
22
|
+
count: number;
|
|
23
|
+
/** The first match, masked when it is a secret. */
|
|
24
|
+
sample: string;
|
|
25
|
+
};
|
|
26
|
+
export type SensitiveReport = {
|
|
27
|
+
/** The worst level found, or null when nothing was. */
|
|
28
|
+
level: SensitiveLevel | null;
|
|
29
|
+
findings: SensitiveFinding[];
|
|
30
|
+
};
|
|
31
|
+
export declare function scanSensitive(source: string): SensitiveReport;
|
|
32
|
+
/** One line per finding, for a terminal or a tool result. */
|
|
33
|
+
export declare function describeSensitive(report: SensitiveReport): string[];
|
|
34
|
+
//# sourceMappingURL=sensitive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitive.d.ts","sourceRoot":"","sources":["../src/sensitive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEnD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,uDAAuD;IACvD,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B,CAAC;AAqFF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CA8B7D;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAInE"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is this safe to share? A scan for what should not leave the machine.
|
|
3
|
+
*
|
|
4
|
+
* Two levels. A secret (a private key, an API token, a password, a JWT, a URL with
|
|
5
|
+
* credentials in it) lets whoever reads the link act as you, so every surface stops
|
|
6
|
+
* and asks before it shares one. Personal details (an email address, a public IP, a
|
|
7
|
+
* home directory that names your account) only identify you, so they are pointed out
|
|
8
|
+
* and nothing stops.
|
|
9
|
+
*
|
|
10
|
+
* The page, the API, the CLI and MCP all run this same scan, so they agree. It is a
|
|
11
|
+
* warning, never a guarantee: a clean scan does not prove a file is safe, and every
|
|
12
|
+
* match comes back masked, so the warning itself never repeats a secret.
|
|
13
|
+
*/
|
|
14
|
+
// Words that sit where a secret would but are not one: placeholders, booleans,
|
|
15
|
+
// variable references and the redactions tools already applied.
|
|
16
|
+
const PLACEHOLDER = /^(?:x+|\*+|\.+|-+|<.*>|\[.*\]|\{.*\}|\$.*|%.*%|changeme|password|secret|token|redacted|hidden|masked|null|none|nil|undefined|true|false|yes|no|present|missing|set|unset|example.*|sample.*|dummy.*|test.*|your[_-].*|my[_-].*|todo|tbd)$/i;
|
|
17
|
+
const PRIVATE_IP = /^(?:0|10|127)\.|^169\.254\.|^172\.(?:1[6-9]|2\d|3[01])\.|^192\.168\.|^255\./;
|
|
18
|
+
const DOCUMENTATION_IP = /^(?:192\.0\.2|198\.51\.100|203\.0\.113)\./;
|
|
19
|
+
const GENERIC_ACCOUNT = /^(?:user|username|users|runner|ubuntu|debian|admin|you|me|name|your[-_]?name|yourname|someone|example|shared|public|default|guest|vagrant|node|app|www|\$\w+|%\w+%|<.*>|\{.*\}|\*)$/i;
|
|
20
|
+
const EXAMPLE_EMAIL = /@(?:example\.(?:com|org|net)|[\w.-]+\.(?:test|example|invalid|localhost))$|^(?:no-?reply|do-?not-?reply|git|noreply\+?.*)@|@users\.noreply\.github\.com$/i;
|
|
21
|
+
const RULES = [
|
|
22
|
+
{ level: "secret", label: "a private key", pattern: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----/g },
|
|
23
|
+
{ level: "secret", label: "an Anthropic API key", pattern: /\bsk-ant-[A-Za-z0-9_-]{20,}/g },
|
|
24
|
+
{ level: "secret", label: "an OpenAI API key", pattern: /\bsk-(?:proj-|svcacct-|admin-)?[A-Za-z0-9_-]{20,}/g, keep: (v) => !v.startsWith("sk-ant-") && /\d/.test(v) },
|
|
25
|
+
{ level: "secret", label: "an AWS access key", pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g },
|
|
26
|
+
{ level: "secret", label: "a GitHub token", pattern: /\b(?:gh[pousr]_[A-Za-z0-9]{36,}|github_pat_[A-Za-z0-9_]{60,})\b/g },
|
|
27
|
+
{ level: "secret", label: "a GitLab token", pattern: /\bglpat-[A-Za-z0-9_-]{20,}/g },
|
|
28
|
+
{ level: "secret", label: "an npm token", pattern: /\bnpm_[A-Za-z0-9]{36}\b/g },
|
|
29
|
+
{ level: "secret", label: "a Stripe secret key", pattern: /\b[rs]k_live_[A-Za-z0-9]{20,}/g },
|
|
30
|
+
{ level: "secret", label: "a Slack token", pattern: /\bxox[abposr]-[A-Za-z0-9-]{10,}/g },
|
|
31
|
+
{ level: "secret", label: "a Slack webhook", pattern: /https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9/]{20,}/g },
|
|
32
|
+
{ level: "secret", label: "a Discord webhook", pattern: /https:\/\/(?:\w+\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_-]{20,}/g },
|
|
33
|
+
{ level: "secret", label: "a Google API key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g },
|
|
34
|
+
{ level: "secret", label: "a SendGrid key", pattern: /\bSG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}\b/g },
|
|
35
|
+
{ level: "secret", label: "a Twilio key", pattern: /\bSK[0-9a-f]{32}\b/g },
|
|
36
|
+
{ level: "secret", label: "a JSON Web Token", pattern: /\beyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g },
|
|
37
|
+
{
|
|
38
|
+
level: "secret",
|
|
39
|
+
label: "a password in a URL",
|
|
40
|
+
pattern: /\b[a-z][a-z0-9+.-]*:\/\/[^\s:/?#@"'<>]+:([^\s/?#@"'<>]+)@[\w.-]+/gi,
|
|
41
|
+
group: 0,
|
|
42
|
+
keep: (v) => !PLACEHOLDER.test(v.match(/:\/\/[^:]+:([^@]+)@/)?.[1] ?? ""),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
// NAME=value, "name": "value", name: value, where the name says it is a secret.
|
|
46
|
+
level: "secret",
|
|
47
|
+
label: "a password or key in a setting",
|
|
48
|
+
pattern: /["']?\b([A-Za-z0-9_.-]*(?:secret|token|passw(?:or)?d|passwd|pwd|api[_-]?key|apikey|private[_-]?key|access[_-]?key|auth[_-]?key|client[_-]?secret|credentials?)[A-Za-z0-9_.-]*)["']?\s*[:=]\s*["']?([A-Za-z0-9_\-+/=.~!@#%^&*]{8,})/gi,
|
|
49
|
+
group: 2,
|
|
50
|
+
keep: (v) => !PLACEHOLDER.test(v) && /\d/.test(v) && /[A-Za-z]/.test(v) && !/^\d+(?:\.\d+)*$/.test(v),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
level: "personal",
|
|
54
|
+
label: "an email address",
|
|
55
|
+
pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}\b/g,
|
|
56
|
+
keep: (v) => !EXAMPLE_EMAIL.test(v),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
level: "personal",
|
|
60
|
+
label: "a public IP address",
|
|
61
|
+
pattern: /(?<![\w.])(?:25[0-5]|2[0-4]\d|1?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|1?\d?\d)){3}(?![\w.])/g,
|
|
62
|
+
keep: (v) => !PRIVATE_IP.test(v) && !DOCUMENTATION_IP.test(v),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
level: "personal",
|
|
66
|
+
label: "a home directory with your account name",
|
|
67
|
+
pattern: /(?:\/home\/|\/Users\/|[A-Za-z]:\\Users\\)([A-Za-z0-9._-]+)/g,
|
|
68
|
+
group: 1,
|
|
69
|
+
keep: (v) => !GENERIC_ACCOUNT.test(v),
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
/** The start and end of a secret, enough to recognise it and not enough to use it. */
|
|
73
|
+
function mask(value) {
|
|
74
|
+
if (value.length <= 8)
|
|
75
|
+
return "•".repeat(value.length);
|
|
76
|
+
return `${value.slice(0, 4)}…${value.slice(-2)}`;
|
|
77
|
+
}
|
|
78
|
+
function lineOf(source, index) {
|
|
79
|
+
let line = 1;
|
|
80
|
+
for (let i = source.indexOf("\n"); i !== -1 && i < index; i = source.indexOf("\n", i + 1))
|
|
81
|
+
line++;
|
|
82
|
+
return line;
|
|
83
|
+
}
|
|
84
|
+
export function scanSensitive(source) {
|
|
85
|
+
const findings = [];
|
|
86
|
+
// Text one rule reported as a secret is not reported again by a looser rule, nor as
|
|
87
|
+
// the email address a password-in-a-URL looks like.
|
|
88
|
+
const claimed = [];
|
|
89
|
+
const overlaps = (start, end) => claimed.some(([a, b]) => start < b && end > a);
|
|
90
|
+
for (const rule of RULES) {
|
|
91
|
+
let first = null;
|
|
92
|
+
const seen = new Set();
|
|
93
|
+
for (const match of source.matchAll(rule.pattern)) {
|
|
94
|
+
const value = match[rule.group ?? 0] ?? match[0];
|
|
95
|
+
const start = match.index;
|
|
96
|
+
const end = start + match[0].length;
|
|
97
|
+
if (rule.keep && !rule.keep(value))
|
|
98
|
+
continue;
|
|
99
|
+
if (overlaps(start, end))
|
|
100
|
+
continue;
|
|
101
|
+
if (rule.level === "secret")
|
|
102
|
+
claimed.push([start, end]);
|
|
103
|
+
seen.add(value);
|
|
104
|
+
first ??= { index: start, value };
|
|
105
|
+
}
|
|
106
|
+
if (!first)
|
|
107
|
+
continue;
|
|
108
|
+
findings.push({
|
|
109
|
+
level: rule.level,
|
|
110
|
+
label: rule.label,
|
|
111
|
+
line: lineOf(source, first.index),
|
|
112
|
+
count: seen.size,
|
|
113
|
+
sample: rule.level === "secret" ? mask(first.value) : first.value,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const level = findings.some((f) => f.level === "secret") ? "secret" : findings.length ? "personal" : null;
|
|
117
|
+
return { level, findings };
|
|
118
|
+
}
|
|
119
|
+
/** One line per finding, for a terminal or a tool result. */
|
|
120
|
+
export function describeSensitive(report) {
|
|
121
|
+
return report.findings.map((f) => `${f.level === "secret" ? "secret" : "personal"}: ${f.label} on line ${f.line}${f.count > 1 ? ` (${f.count} different)` : ""}: ${f.sample}`);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=sensitive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitive.js","sourceRoot":"","sources":["../src/sensitive.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/readm3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Markdown editing and sharing for people and teams. Web/PWA, CLI, API and MCP with version history, view/edit links, and a terminal reader.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"marked": "^18.0.11"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
+
"@anthropic-ai/sdk": "^0.135.0",
|
|
53
54
|
"@codemirror/autocomplete": "^6.20.3",
|
|
54
55
|
"@codemirror/commands": "^6.11.1",
|
|
55
56
|
"@codemirror/language": "^6.13.1",
|