proofread-mcp 0.1.0 → 0.1.1

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.
Files changed (51) hide show
  1. package/README.md +31 -19
  2. package/dist/cli.js +9 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client.d.ts +14 -3
  5. package/dist/client.js +73 -16
  6. package/dist/client.js.map +1 -1
  7. package/dist/config.d.ts +1 -1
  8. package/dist/config.js +1 -1
  9. package/dist/config.js.map +1 -1
  10. package/dist/errors.d.ts +8 -4
  11. package/dist/errors.js +44 -10
  12. package/dist/errors.js.map +1 -1
  13. package/dist/format.d.ts +6 -4
  14. package/dist/format.js +86 -35
  15. package/dist/format.js.map +1 -1
  16. package/dist/http.d.ts +8 -1
  17. package/dist/http.js +43 -10
  18. package/dist/http.js.map +1 -1
  19. package/dist/index.d.ts +3 -3
  20. package/dist/index.js +2 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/server.d.ts +1 -1
  23. package/dist/server.js +3 -2
  24. package/dist/server.js.map +1 -1
  25. package/dist/sse.d.ts +1 -0
  26. package/dist/sse.js +42 -20
  27. package/dist/sse.js.map +1 -1
  28. package/dist/tools/billing_link.d.ts +8 -0
  29. package/dist/tools/billing_link.js +31 -0
  30. package/dist/tools/billing_link.js.map +1 -0
  31. package/dist/tools/check_citations.d.ts +7 -4
  32. package/dist/tools/check_citations.js +18 -12
  33. package/dist/tools/check_citations.js.map +1 -1
  34. package/dist/tools/check_document.js +22 -14
  35. package/dist/tools/check_document.js.map +1 -1
  36. package/dist/tools/index.js +3 -1
  37. package/dist/tools/index.js.map +1 -1
  38. package/dist/tools/render_report.js +4 -4
  39. package/dist/tools/render_report.js.map +1 -1
  40. package/dist/tools/resolve_citation.js +2 -2
  41. package/dist/tools/resolve_citation.js.map +1 -1
  42. package/dist/tools/resolve_citations.js +2 -2
  43. package/dist/tools/resolve_citations.js.map +1 -1
  44. package/dist/tools/sign_up.d.ts +5 -0
  45. package/dist/tools/sign_up.js +42 -0
  46. package/dist/tools/sign_up.js.map +1 -0
  47. package/dist/tools/tool.d.ts +11 -2
  48. package/dist/tools/tool.js +20 -7
  49. package/dist/tools/tool.js.map +1 -1
  50. package/dist/types.d.ts +19 -0
  51. package/package.json +2 -1
package/README.md CHANGED
@@ -6,16 +6,20 @@ proofread.law checks each citation against an open register of about 10 million
6
6
 
7
7
  ## What it does
8
8
 
9
- Six tools:
9
+ Eight tools:
10
10
 
11
11
  | Tool | Input | What comes back |
12
12
  |---|---|---|
13
- | `check_citations` | text, `deep` (optional) | The coverage statement, counts per tier, one line per row that needs a human, the number of citations found, a report id |
14
- | `check_document` | path to a `.pdf`, `.docx` or `.txt` (up to 10 MB), `deep` (optional) | The same, for a file on disk |
13
+ | `check_citations` | text, `deep` (optional) | The coverage statement, counts per tier, one line per row that needs a human (red first, then orange, then deep-check rows to review), the number of citations found, a report id |
14
+ | `check_document` | path to a `.pdf`, `.docx`, `.txt` or `.md` (up to 10 MB), `deep` (optional) | The same, for a file on disk |
15
15
  | `resolve_citation` | one citation string | The register's answer for that citation: found (case, court, date, parallel citations, link), ambiguous (candidates), not in the register, cannot verify, known citation, or no citation recognised; the coverage of that volume; the coverage statement |
16
16
  | `resolve_citations` | a list of up to 500 citation strings | Counts by status, one line per citation in input order, the coverage statement |
17
17
  | `coverage` | nothing | The coverage statement and the storage notice |
18
- | `render_report` | a report id from a previous check, or the full report JSON | A markdown diligence report |
18
+ | `render_report` | a report id from a previous check, or the full report JSON | A markdown diligence report with every row |
19
+ | `sign_up` | the account owner's email, a name for the agent | A proofread.law account and an API key (shown once); the server uses it for the rest of the session |
20
+ | `billing_link` | `payg`, `solo` or `firm` | A Stripe Checkout link for the account owner; needs an API key |
21
+
22
+ The compact result of a check is capped at about 12,000 characters; when a long brief has more flagged rows than fit, the text says how many were left out and `render_report` has them all.
19
23
 
20
24
  `check_citations` and `check_document` read prose: they compare the case name and any quotation with the register. `resolve_citation` and `resolve_citations` look the citation string up in the register (the `/v1/resolve` API) and tell you which case sits there; they do not compare it with the name you have.
21
25
 
@@ -32,9 +36,7 @@ What it cannot do: resolve Westlaw (WL) or Lexis identifiers, check statutes, re
32
36
 
33
37
  ## Install
34
38
 
35
- Needs Node 20 or newer. No install step is required; `npx` fetches it.
36
-
37
- Until the package is on npm, clone this repository, run `npm install && npm run build`, and use `node /absolute/path/to/proofread-mcp/dist/cli.js` wherever the snippets below say `npx -y proofread-mcp`.
39
+ Needs Node 20 or newer. No install step is required; `npx` fetches [proofread-mcp from npm](https://www.npmjs.com/package/proofread-mcp).
38
40
 
39
41
  ### Claude Desktop
40
42
 
@@ -60,7 +62,7 @@ Leave out `env` to use the free tier.
60
62
 
61
63
  ```bash
62
64
  claude mcp add proofread -- npx -y proofread-mcp
63
- # with a Firm key:
65
+ # with an API key:
64
66
  claude mcp add proofread -e PROOFREAD_API_KEY=pl_... -- npx -y proofread-mcp
65
67
  ```
66
68
 
@@ -95,7 +97,9 @@ Then connect from the Agents SDK:
95
97
  from agents import Agent, Runner
96
98
  from agents.mcp import MCPServerStreamableHttp
97
99
 
98
- async with MCPServerStreamableHttp(params={"url": "http://127.0.0.1:3333/mcp"}) as proofread:
100
+ # The SDK's default read timeout is 5 s. A check of a long brief takes up to 6 s and a deep check 1 to 2 s per citation,
101
+ # so give the session up to 15 minutes (the API's own deep-check limit).
102
+ async with MCPServerStreamableHttp(params={"url": "http://127.0.0.1:3333/mcp"}, client_session_timeout_seconds=900) as proofread:
99
103
  agent = Agent(name="Drafting assistant", instructions="Check every case citation before you rely on it.", mcp_servers=[proofread])
100
104
  result = await Runner.run(agent, "Check the citations in this paragraph: ...")
101
105
  ```
@@ -105,11 +109,15 @@ import { Agent, run, MCPServerStreamableHttp } from "@openai/agents";
105
109
 
106
110
  const proofread = new MCPServerStreamableHttp({ url: "http://127.0.0.1:3333/mcp", name: "proofread" });
107
111
  await proofread.connect();
108
- const agent = new Agent({ name: "Drafting assistant", mcpServers: [proofread] });
109
- const result = await run(agent, "Check the citations in this paragraph: ...");
112
+ try {
113
+ const agent = new Agent({ name: "Drafting assistant", mcpServers: [proofread] });
114
+ const result = await run(agent, "Check the citations in this paragraph: ...");
115
+ } finally {
116
+ await proofread.close();
117
+ }
110
118
  ```
111
119
 
112
- The HTTP server binds to 127.0.0.1 by default. To expose it on a network use `--host 0.0.0.0` and put it behind something that adds authentication; the server has none of its own.
120
+ The HTTP server binds to 127.0.0.1 by default and is single-tenant by design: it has no authentication of its own, report ids are shared across sessions, and a key from `sign_up` is adopted by the whole process. Sessions that stay idle for 30 minutes are closed. To expose it on a network use `--host 0.0.0.0` and put it behind something that adds authentication.
113
121
 
114
122
  ### Any MCP client
115
123
 
@@ -119,20 +127,24 @@ stdio: run `proofread-mcp`. Streamable HTTP: run `proofread-mcp --http --port 33
119
127
 
120
128
  | Variable | Default | Meaning |
121
129
  |---|---|---|
122
- | `PROOFREAD_API_KEY` | unset | A Firm plan API key (`pl_...`), sent as `Authorization: Bearer`. Without it the free tier applies |
130
+ | `PROOFREAD_API_KEY` | unset | An API key (`pl_...`), sent as `Authorization: Bearer` to `PROOFREAD_API` only. Every plan has keys (free 1, pay as you go 3, solo 3, firm 5); a paid-plan key lifts the free-tier limits. Without it the free tier applies per IP |
123
131
  | `PROOFREAD_API` | `https://proofread.law` | Base URL, for a self-hosted or test instance |
124
132
 
133
+ ## Accounts and keys
134
+
135
+ An agent can open an account itself: `sign_up` posts the owner's real email and a name to `POST /agent/signup` and gets a key back, shown once. The server uses that key for the rest of the session; put it in `PROOFREAD_API_KEY` to keep it. The owner receives one confirmation email. When a quota is used up (a tool answers "needs the ... plan" or "monthly allowance used"), `billing_link` returns a Stripe Checkout link for the owner; nothing is charged until they pay. Plans and prices: [proofread.law/pricing](https://proofread.law/pricing). The onboarding text the API publishes for agents is at [proofread.law/agent/onboarding.md](https://proofread.law/agent/onboarding.md).
136
+
125
137
  ## Free tier
126
138
 
127
- Without a key, per IP address and per month:
139
+ Per month, per IP address without a key or per account with a free-tier key:
128
140
 
129
141
  | Tools | Quota |
130
142
  |---|---|
131
143
  | `check_citations`, `check_document` | 20 checks, of which 3 may be deep checks |
132
144
  | `resolve_citation`, `resolve_citations` | 1,000 resolves (each citation in a list counts as one) |
133
- | `coverage`, `render_report` | free, not counted |
145
+ | `coverage`, `render_report`, `sign_up`, `billing_link` | free, not counted |
134
146
 
135
- There is also a limit of 20 requests an hour per IP. When a limit is reached the tool returns a plain message with the retry time or the upgrade link; nothing is thrown at the protocol level.
147
+ There is also a limit of 20 requests an hour per IP (more on paid plans). When a limit is reached the tool returns a plain message with the retry time or the upgrade link; nothing is thrown at the protocol level.
136
148
 
137
149
  `.docx` upload and unlimited checks need a paid plan. See [proofread.law/pricing](https://proofread.law/pricing).
138
150
 
@@ -140,8 +152,8 @@ There is also a limit of 20 requests an hour per IP. When a limit is reached the
140
152
 
141
153
  - The text or file goes to proofread.law, which runs on its own machine, not a cloud provider's API. It is processed in memory and discarded when the report is returned. Only counts (citations, tiers, timing) are logged, never text.
142
154
  - A citation string the local register cannot resolve may be looked up in the CourtListener citation API. Only the citation string leaves, never a party name or prose.
143
- - Deep check (`deep: true`) is opt-in. In that mode the clause before each citation (up to 700 characters) is sent to a model judge, together with the cited opinion. That is the only mode in which any of the document's prose leaves proofread.law.
144
- - This server stores nothing on disk. It keeps the last 50 reports in memory so `render_report` can be called with a short id; they are gone when the process exits.
155
+ - Deep check (`deep: true`) is opt-in. In that mode the clause before each citation (up to 700 characters) is sent to a model judge, together with the cited opinion. That is the only mode in which any of the document's prose leaves proofread.law. If the deep-check stream stops before every citation was judged, the tool answers with an error that says how many were checked; it never presents a partial deep check as a finished one.
156
+ - This server stores nothing on disk. It keeps the last 50 reports in memory so `render_report` can be called with a short id; they are gone when the process exits. A key from `sign_up` is held in memory only.
145
157
 
146
158
  ## The coverage caveat
147
159
 
@@ -184,7 +196,7 @@ Layout: `src/client.ts` is the typed HTTP client (`/verify`, `/render`, `/api/co
184
196
 
185
197
  ## Publishing
186
198
 
187
- See [RELEASE.md](RELEASE.md). The package is not on npm yet and the repository is private until the owner makes it public.
199
+ See [RELEASE.md](RELEASE.md): npm, the MCP Registry (`server.json` is in the repository), Anthropic's connector directory and OpenAI.
188
200
 
189
201
  ## License
190
202
 
package/dist/cli.js CHANGED
@@ -10,7 +10,8 @@ Usage:
10
10
  proofread-mcp --http --port N --host H
11
11
 
12
12
  Environment:
13
- PROOFREAD_API_KEY Firm plan API key (pl_...). Without it the free tier applies.
13
+ PROOFREAD_API_KEY API key (pl_...): from the sign_up tool or https://proofread.law/account. Any plan has keys;
14
+ a paid-plan key lifts the free-tier limits. Without a key the free tier applies per IP.
14
15
  PROOFREAD_API Base URL (default https://proofread.law).
15
16
  `;
16
17
  export function parseArgs(argv) {
@@ -55,7 +56,14 @@ async function main() {
55
56
  console.error(`proofread-mcp listening on ${url}`); // stderr: stdout stays clean in both modes
56
57
  return;
57
58
  }
59
+ // The client owns this process: when it goes away (stdin ends, or stdout breaks), stop, including any request still in flight.
60
+ process.stdout.on("error", (err) => {
61
+ if (err.code === "EPIPE")
62
+ process.exit(0);
63
+ throw err;
64
+ });
58
65
  const server = createServer();
66
+ server.server.onclose = () => process.exit(0);
59
67
  await server.connect(new StdioServerTransport());
60
68
  }
61
69
  main().catch((err) => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { Config } from "./config.js";
2
- import type { Coverage, Report, ResolveBatch, ResolveResult, Row } from "./types.js";
3
- export declare const USER_AGENT = "proofread-mcp/0.1.0 (+https://github.com/Data-Alchemy-Labs/proofread-mcp)";
2
+ import type { CheckoutLink, Coverage, Report, ResolveBatch, ResolveResult, Row, SignupResult } from "./types.js";
3
+ export declare const USER_AGENT = "proofread-mcp/0.1.1 (+https://github.com/Data-Alchemy-Labs/proofread-mcp)";
4
4
  export declare const MAX_UPLOAD_BYTES: number;
5
+ export declare const MAX_BATCH_CITES = 500;
5
6
  export type FetchLike = (input: string | URL, init?: RequestInit) => Promise<Response>;
6
7
  export interface VerifyOptions {
7
8
  /** Run the support check (opt-in; the clause before each citation is sent to the model judge). */
@@ -10,7 +11,7 @@ export interface VerifyOptions {
10
11
  onRow?: (row: Row, report: Report) => void;
11
12
  signal?: AbortSignal;
12
13
  }
13
- export declare const MAX_BATCH_CITES = 500;
14
+ export type Plan = "payg" | "solo" | "firm";
14
15
  export interface Client {
15
16
  verifyText(text: string, options?: VerifyOptions): Promise<Report>;
16
17
  verifyFile(bytes: Uint8Array, filename: string, options?: VerifyOptions): Promise<Report>;
@@ -20,6 +21,16 @@ export interface Client {
20
21
  resolveBatch(cites: string[], signal?: AbortSignal): Promise<ResolveBatch>;
21
22
  renderMarkdown(report: Report, signal?: AbortSignal): Promise<string>;
22
23
  coverage(signal?: AbortSignal): Promise<Coverage>;
24
+ /** POST /agent/signup: an account and a key for the owner's inbox. `created` is false when an existing unconfirmed account's key was rotated. */
25
+ signUp(email: string, agentName: string, signal?: AbortSignal): Promise<{
26
+ created: boolean;
27
+ result: SignupResult;
28
+ }>;
29
+ /** POST /agent/checkout-link with the key: a Stripe Checkout page for the owner. */
30
+ checkoutLink(plan: Plan, signal?: AbortSignal): Promise<CheckoutLink>;
31
+ hasApiKey(): boolean;
32
+ /** Adopt a key for the rest of this process (after sign_up); nothing is written to disk. */
33
+ setApiKey(key: string): void;
23
34
  }
24
35
  export declare function createClient(config: Config, fetchImpl?: FetchLike): Client;
25
36
  /** `?deep=1` streams SSE by default; `&stream=0` asks for one JSON after all checks. A default check has no query. */
package/dist/client.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import { ProofreadError } from "./errors.js";
2
2
  import { readSseReport } from "./sse.js";
3
- export const USER_AGENT = "proofread-mcp/0.1.0 (+https://github.com/Data-Alchemy-Labs/proofread-mcp)";
3
+ export const USER_AGENT = "proofread-mcp/0.1.1 (+https://github.com/Data-Alchemy-Labs/proofread-mcp)";
4
4
  export const MAX_UPLOAD_BYTES = 10 * 1024 * 1024;
5
+ export const MAX_BATCH_CITES = 500;
5
6
  /** A default check answers in seconds; a deep check runs 1 to 2 s per citation, four in parallel, up to 15 minutes server-side. */
6
7
  const DEFAULT_TIMEOUT_MS = 120_000;
7
8
  const DEEP_TIMEOUT_MS = 16 * 60_000;
8
- export const MAX_BATCH_CITES = 500;
9
9
  export function createClient(config, fetchImpl = globalThis.fetch) {
10
+ let apiKey = config.apiKey;
10
11
  const headers = (extra = {}) => ({
11
12
  "User-Agent": USER_AGENT,
12
13
  Accept: "application/json, text/event-stream",
13
- ...(config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}),
14
+ ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
14
15
  ...extra,
15
16
  });
16
17
  async function call(path, init, timeoutMs, signal) {
@@ -26,11 +27,42 @@ export function createClient(config, fetchImpl = globalThis.fetch) {
26
27
  throw ProofreadError.fromBody(res.status, await bodyAsJson(res));
27
28
  return res;
28
29
  }
30
+ /** The JSON body of a 2xx answer, or a clear error when the body is not JSON (maintenance page, WAF interstitial) or is cut. */
31
+ async function json(res, check) {
32
+ const type = res.headers.get("content-type") ?? "";
33
+ if (!type.startsWith("application/json")) {
34
+ throw new ProofreadError(res.status, "bad_content_type", `proofread.law answered HTTP ${res.status} with ${type.split(";")[0] || "no content type"} instead of JSON; the service may be behind a maintenance or challenge page. Try again in a minute.`);
35
+ }
36
+ let value;
37
+ try {
38
+ value = await res.json();
39
+ }
40
+ catch (cause) {
41
+ throw ProofreadError.fromFetchFailure(config.baseUrl, cause, true);
42
+ }
43
+ const problem = check?.(value);
44
+ if (problem)
45
+ throw new ProofreadError(res.status, "bad_shape", `proofread.law answered an unexpected shape (${problem}). Try again; if it persists the API may have changed.`);
46
+ return value;
47
+ }
29
48
  async function verify(body, contentType, options) {
30
49
  const deep = options.deep === true;
31
50
  const path = verifyPath(deep, deep && options.onRow !== undefined);
32
51
  const res = await call(path, { method: "POST", headers: headers(contentType ? { "Content-Type": contentType } : {}), body }, deep ? DEEP_TIMEOUT_MS : DEFAULT_TIMEOUT_MS, options.signal);
33
- return readReport(res, options.onRow);
52
+ const type = res.headers.get("content-type") ?? "";
53
+ if (type.startsWith("text/event-stream")) {
54
+ if (!res.body)
55
+ throw new ProofreadError(0, "stream_incomplete", "proofread.law's deep-check stream had no body. Run the check again.");
56
+ try {
57
+ return await readSseReport(res.body, options.onRow);
58
+ }
59
+ catch (cause) {
60
+ if (cause instanceof ProofreadError)
61
+ throw cause;
62
+ throw ProofreadError.fromFetchFailure(config.baseUrl, cause, true);
63
+ }
64
+ }
65
+ return json(res, checkReportShape);
34
66
  }
35
67
  return {
36
68
  verifyText: (text, options = {}) => verify(JSON.stringify({ text }), "application/json", options),
@@ -44,22 +76,42 @@ export function createClient(config, fetchImpl = globalThis.fetch) {
44
76
  },
45
77
  async resolveV1(cite, signal) {
46
78
  const res = await call(`/v1/resolve?cite=${encodeURIComponent(cite)}`, { method: "GET", headers: headers() }, DEFAULT_TIMEOUT_MS, signal);
47
- return (await res.json());
79
+ return json(res, (v) => (isObject(v) && typeof v.status === "string" ? undefined : "no status field"));
48
80
  },
49
81
  async resolveBatch(cites, signal) {
50
82
  if (cites.length > MAX_BATCH_CITES)
51
83
  throw new ProofreadError(400, "too_many", `${cites.length} citations; the cap is ${MAX_BATCH_CITES} per call`);
52
84
  const res = await call("/v1/resolve", { method: "POST", headers: headers({ "Content-Type": "application/json" }), body: JSON.stringify({ cites }) }, DEFAULT_TIMEOUT_MS, signal);
53
- return (await res.json());
85
+ return json(res, (v) => (isObject(v) && Array.isArray(v.results) ? undefined : "no results array"));
54
86
  },
55
87
  async renderMarkdown(report, signal) {
56
88
  const res = await call("/render?format=md", { method: "POST", headers: headers({ "Content-Type": "application/json", Accept: "text/markdown" }),
57
89
  body: JSON.stringify(report) }, DEFAULT_TIMEOUT_MS, signal);
58
- return res.text();
90
+ try {
91
+ return await res.text();
92
+ }
93
+ catch (cause) {
94
+ throw ProofreadError.fromFetchFailure(config.baseUrl, cause, true);
95
+ }
59
96
  },
60
97
  async coverage(signal) {
61
98
  const res = await call("/api/coverage", { method: "GET", headers: headers() }, DEFAULT_TIMEOUT_MS, signal);
62
- return (await res.json());
99
+ return json(res, (v) => (isObject(v) && typeof v.coverage === "string" ? undefined : "no coverage statement"));
100
+ },
101
+ async signUp(email, agentName, signal) {
102
+ const res = await call("/agent/signup", { method: "POST", headers: headers({ "Content-Type": "application/json" }),
103
+ body: JSON.stringify({ email, agent_name: agentName }) }, DEFAULT_TIMEOUT_MS, signal);
104
+ const result = await json(res, (v) => (isObject(v) && typeof v.api_key === "string" ? undefined : "no api_key"));
105
+ return { created: res.status === 201, result };
106
+ },
107
+ async checkoutLink(plan, signal) {
108
+ const res = await call("/agent/checkout-link", { method: "POST", headers: headers({ "Content-Type": "application/json" }),
109
+ body: JSON.stringify({ plan }) }, DEFAULT_TIMEOUT_MS, signal);
110
+ return json(res, (v) => (isObject(v) && typeof v.checkout_url === "string" ? undefined : "no checkout_url"));
111
+ },
112
+ hasApiKey: () => Boolean(apiKey),
113
+ setApiKey(key) {
114
+ apiKey = key;
63
115
  },
64
116
  };
65
117
  }
@@ -69,14 +121,19 @@ export function verifyPath(deep, stream) {
69
121
  return "/verify";
70
122
  return stream ? "/verify?deep=1" : "/verify?deep=1&stream=0";
71
123
  }
72
- async function readReport(res, onRow) {
73
- const type = res.headers.get("content-type") ?? "";
74
- if (type.startsWith("text/event-stream")) {
75
- if (!res.body)
76
- throw new ProofreadError(0, "empty_stream", "the event stream had no body");
77
- return readSseReport(res.body, onRow);
78
- }
79
- return (await res.json());
124
+ function checkReportShape(v) {
125
+ if (!isObject(v))
126
+ return "not an object";
127
+ if (!isObject(v.summary))
128
+ return "no summary";
129
+ if (!Array.isArray(v.rows))
130
+ return "rows is not a list";
131
+ if (typeof v.coverage !== "string")
132
+ return "no coverage statement";
133
+ return undefined;
134
+ }
135
+ function isObject(v) {
136
+ return typeof v === "object" && v !== null;
80
137
  }
81
138
  async function bodyAsJson(res) {
82
139
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -3,5 +3,5 @@ export interface Config {
3
3
  apiKey?: string;
4
4
  }
5
5
  export declare const DEFAULT_BASE_URL = "https://proofread.law";
6
- /** Reads PROOFREAD_API (base URL) and PROOFREAD_API_KEY (Firm plan key) from the environment. */
6
+ /** Reads PROOFREAD_API (base URL) and PROOFREAD_API_KEY (an account key, any plan) from the environment. */
7
7
  export declare function configFromEnv(env?: NodeJS.ProcessEnv): Config;
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export const DEFAULT_BASE_URL = "https://proofread.law";
2
- /** Reads PROOFREAD_API (base URL) and PROOFREAD_API_KEY (Firm plan key) from the environment. */
2
+ /** Reads PROOFREAD_API (base URL) and PROOFREAD_API_KEY (an account key, any plan) from the environment. */
3
3
  export function configFromEnv(env = process.env) {
4
4
  const baseUrl = (env.PROOFREAD_API ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
5
5
  const apiKey = env.PROOFREAD_API_KEY?.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAChE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC7C,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD,4GAA4G;AAC5G,MAAM,UAAU,aAAa,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAChE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,aAAa,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC7C,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;AACpD,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /** An error answered by proofread.law, or a failure to reach it. `status` is 0 when no HTTP answer arrived. */
1
+ /** An error answered by proofread.law, or a failure to reach or read it. `status` is 0 when no HTTP answer arrived. */
2
2
  export declare class ProofreadError extends Error {
3
3
  readonly status: number;
4
4
  readonly code: string;
@@ -6,8 +6,12 @@ export declare class ProofreadError extends Error {
6
6
  constructor(status: number, code: string, message: string, info?: Record<string, unknown>);
7
7
  static fromBody(status: number, body: unknown): ProofreadError;
8
8
  static network(baseUrl: string, cause: unknown): ProofreadError;
9
- /** fetch rejected: our timeout fired, the MCP client cancelled, or the host was not reachable. */
10
- static fromFetchFailure(baseUrl: string, cause: unknown): ProofreadError;
9
+ /** fetch or a body read rejected: our timeout fired, the MCP client cancelled, the connection dropped, or the host was not reachable. */
10
+ static fromFetchFailure(baseUrl: string, cause: unknown, reading?: boolean): ProofreadError;
11
11
  }
12
- /** One plain sentence a model can act on. Wording follows PRODUCT.md: what was checked, what was found, what to do next. */
12
+ /**
13
+ * One plain sentence a model can act on. A string is already that sentence (a deliberate local result);
14
+ * a ProofreadError is translated by code; anything else is a genuine surprise and says so.
15
+ * Wording follows PRODUCT.md: what was checked, what was found, what to do next.
16
+ */
13
17
  export declare function explain(err: unknown): string;
package/dist/errors.js CHANGED
@@ -1,4 +1,4 @@
1
- /** An error answered by proofread.law, or a failure to reach it. `status` is 0 when no HTTP answer arrived. */
1
+ /** An error answered by proofread.law, or a failure to reach or read it. `status` is 0 when no HTTP answer arrived. */
2
2
  export class ProofreadError extends Error {
3
3
  status;
4
4
  code;
@@ -19,21 +19,36 @@ export class ProofreadError extends Error {
19
19
  return new ProofreadError(status, `http_${status}`, `proofread.law answered HTTP ${status}`);
20
20
  }
21
21
  static network(baseUrl, cause) {
22
- const detail = cause instanceof Error ? cause.message : String(cause);
23
- return new ProofreadError(0, "network", `Could not reach ${baseUrl}: ${detail}`);
22
+ return new ProofreadError(0, "network", `Could not reach ${baseUrl}: ${describeCause(cause)}`);
24
23
  }
25
- /** fetch rejected: our timeout fired, the MCP client cancelled, or the host was not reachable. */
26
- static fromFetchFailure(baseUrl, cause) {
24
+ /** fetch or a body read rejected: our timeout fired, the MCP client cancelled, the connection dropped, or the host was not reachable. */
25
+ static fromFetchFailure(baseUrl, cause, reading = false) {
27
26
  const name = cause instanceof Error ? cause.name : "";
28
27
  if (name === "TimeoutError")
29
- return new ProofreadError(0, "timeout", `no answer from ${baseUrl} in time`);
28
+ return new ProofreadError(0, "timeout", `no ${reading ? "complete answer" : "answer"} from ${baseUrl} in time`);
30
29
  if (name === "AbortError")
31
30
  return new ProofreadError(0, "cancelled", "the request was cancelled by the client");
31
+ if (reading)
32
+ return new ProofreadError(0, "connection_dropped", `the connection to ${baseUrl} dropped while the answer was being read: ${describeCause(cause)}`);
32
33
  return ProofreadError.network(baseUrl, cause);
33
34
  }
34
35
  }
35
- /** One plain sentence a model can act on. Wording follows PRODUCT.md: what was checked, what was found, what to do next. */
36
+ /** undici puts the real reason (ECONNREFUSED, ENOTFOUND, ...) one level down in `cause`. */
37
+ function describeCause(cause) {
38
+ if (!(cause instanceof Error))
39
+ return String(cause);
40
+ const inner = cause.cause;
41
+ const detail = inner?.code ?? inner?.message;
42
+ return detail && detail !== cause.message ? `${cause.message} (${detail})` : cause.message;
43
+ }
44
+ /**
45
+ * One plain sentence a model can act on. A string is already that sentence (a deliberate local result);
46
+ * a ProofreadError is translated by code; anything else is a genuine surprise and says so.
47
+ * Wording follows PRODUCT.md: what was checked, what was found, what to do next.
48
+ */
36
49
  export function explain(err) {
50
+ if (typeof err === "string")
51
+ return err;
37
52
  if (!(err instanceof ProofreadError)) {
38
53
  return `Unexpected error: ${err instanceof Error ? err.message : String(err)}`;
39
54
  }
@@ -41,12 +56,16 @@ export function explain(err) {
41
56
  switch (err.code) {
42
57
  case "network":
43
58
  case "cancelled":
59
+ case "connection_dropped":
60
+ case "stream_incomplete":
61
+ case "bad_content_type":
62
+ case "bad_shape":
44
63
  return err.message;
45
64
  case "plan_required":
46
65
  return `proofread.law: this needs the ${String(i.plan ?? "paid")} plan` +
47
66
  (i.feature ? ` (${String(i.feature)})` : "") + ". " +
48
67
  (i.upgrade ? `Upgrade at ${String(i.upgrade)}. ` : "") +
49
- "A Firm API key goes in PROOFREAD_API_KEY.";
68
+ "The billing_link tool gives the account owner a checkout link; a paid-plan API key goes in PROOFREAD_API_KEY.";
50
69
  case "rate_limited":
51
70
  return `proofread.law rate limit: ${err.message}.` +
52
71
  (i.retry_after ? ` Retry after ${String(i.retry_after)} s.` : "");
@@ -54,17 +73,32 @@ export function explain(err) {
54
73
  return `proofread.law monthly allowance used` +
55
74
  (i.used !== undefined && i.limit !== undefined ? ` (${String(i.used)} of ${String(i.limit)})` : "") +
56
75
  "." + (i.upgrade ? ` Upgrade at ${String(i.upgrade)}.` : "") +
57
- " A Firm API key in PROOFREAD_API_KEY lifts the free-tier limits.";
76
+ " The billing_link tool gives the account owner a checkout link; a paid-plan API key lifts the free-tier limits.";
58
77
  case "bad_key":
59
78
  return "proofread.law rejected the API key in PROOFREAD_API_KEY (unknown or revoked).";
79
+ case "signed_out":
80
+ return "proofread.law needs an API key for this: set PROOFREAD_API_KEY, or call sign_up to create an account and key.";
60
81
  case "missing_cite":
61
82
  case "too_many":
83
+ case "bad_email":
84
+ case "bad_agent_name":
85
+ case "bad_plan":
86
+ return `proofread.law: ${err.message}.`;
87
+ case "exists":
88
+ return `proofread.law: ${err.message}.`;
89
+ case "key_limit":
90
+ return `proofread.law: ${err.message}.`;
91
+ case "already_subscribed":
62
92
  return `proofread.law: ${err.message}.`;
93
+ case "billing_off":
94
+ case "billing_failed":
95
+ return `proofread.law: ${err.message}. Try again later, or the owner can subscribe at https://proofread.law/pricing.`;
63
96
  case "too_large":
64
97
  return `proofread.law: the input is too large (${err.message}); the cap is 10 MB.`;
98
+ case "empty":
65
99
  case "unreadable":
66
100
  case "unparseable":
67
- return `proofread.law could not read the file: ${err.message}. Scanned PDFs without a text layer, encrypted PDFs and legacy .doc are not supported.`;
101
+ return `proofread.law could not read the input: ${err.message}. Scanned PDFs without a text layer, encrypted PDFs and legacy .doc are not supported.`;
68
102
  case "deep_budget_exhausted":
69
103
  return "proofread.law: the deep-check budget for today is spent. Run the check without deep=true; the default check still works.";
70
104
  case "timeout":
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/format.d.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  import type { Report, Row, Tier } from "./types.js";
2
2
  /** The words a user sees per tier (PRODUCT.md): say what was checked and what was found, never a verdict on the author. */
3
3
  export declare const TIER_WORD: Record<Tier, string>;
4
+ /** Compact output stays inside a model's budget; the full list is one render_report call away. */
5
+ export declare const MAX_COMPACT_CHARS = 12000;
4
6
  /**
5
- * A compact, model-friendly view of a report: the coverage statement first, then the counts,
6
- * then one line per row that needs a human (red, orange and, in deep mode, white), then the count of found rows.
7
- * Westlaw/Lexis identifiers are collapsed into one line, as on the site.
7
+ * A compact, model-friendly view of a report: the coverage statement first, then the counts, then one line per row that needs a human
8
+ * (red, then orange, then deep-check rows whose passage was not confirmed or states the opposite), then the count of found rows.
9
+ * Westlaw/Lexis identifiers are collapsed into one line, as on the site. Long lists are cut at MAX_COMPACT_CHARS.
8
10
  */
9
11
  export declare function formatReport(report: Report, reportId?: string): string;
10
12
  /** One line: tier word, citation (parties), headline, detail, register link. */
11
13
  export declare function formatRowLine(row: Row): string;
12
- /** A full view of one row, for resolve_citation. */
14
+ /** A full view of one row. */
13
15
  export declare function formatRowDetail(row: Row): string;