@echofiles/echo-pdf 0.4.3 → 0.6.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.
Files changed (55) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +85 -562
  3. package/bin/echo-pdf.js +130 -525
  4. package/dist/file-utils.d.ts +0 -3
  5. package/dist/file-utils.js +0 -18
  6. package/dist/local/document.d.ts +10 -0
  7. package/dist/local/document.js +133 -0
  8. package/dist/local/index.d.ts +3 -135
  9. package/dist/local/index.js +2 -555
  10. package/dist/local/semantic.d.ts +2 -0
  11. package/dist/local/semantic.js +231 -0
  12. package/dist/local/shared.d.ts +50 -0
  13. package/dist/local/shared.js +173 -0
  14. package/dist/local/types.d.ts +183 -0
  15. package/dist/local/types.js +2 -0
  16. package/dist/node/pdfium-local.js +30 -6
  17. package/dist/pdf-config.js +2 -65
  18. package/dist/pdf-types.d.ts +1 -58
  19. package/dist/types.d.ts +1 -87
  20. package/echo-pdf.config.json +1 -21
  21. package/package.json +25 -22
  22. package/bin/lib/http.js +0 -97
  23. package/bin/lib/mcp-stdio.js +0 -99
  24. package/dist/auth.d.ts +0 -18
  25. package/dist/auth.js +0 -36
  26. package/dist/core/index.d.ts +0 -50
  27. package/dist/core/index.js +0 -7
  28. package/dist/file-ops.d.ts +0 -11
  29. package/dist/file-ops.js +0 -36
  30. package/dist/file-store-do.d.ts +0 -36
  31. package/dist/file-store-do.js +0 -298
  32. package/dist/http-error.d.ts +0 -9
  33. package/dist/http-error.js +0 -14
  34. package/dist/index.d.ts +0 -1
  35. package/dist/index.js +0 -1
  36. package/dist/mcp-server.d.ts +0 -3
  37. package/dist/mcp-server.js +0 -124
  38. package/dist/node/semantic-local.d.ts +0 -16
  39. package/dist/node/semantic-local.js +0 -113
  40. package/dist/pdf-agent.d.ts +0 -18
  41. package/dist/pdf-agent.js +0 -217
  42. package/dist/pdf-storage.d.ts +0 -8
  43. package/dist/pdf-storage.js +0 -86
  44. package/dist/pdfium-engine.d.ts +0 -9
  45. package/dist/pdfium-engine.js +0 -180
  46. package/dist/r2-file-store.d.ts +0 -20
  47. package/dist/r2-file-store.js +0 -176
  48. package/dist/response-schema.d.ts +0 -15
  49. package/dist/response-schema.js +0 -159
  50. package/dist/tool-registry.d.ts +0 -16
  51. package/dist/tool-registry.js +0 -175
  52. package/dist/worker.d.ts +0 -7
  53. package/dist/worker.js +0 -386
  54. package/scripts/export-fixtures.sh +0 -204
  55. package/wrangler.toml +0 -19
package/README.md CHANGED
@@ -1,86 +1,82 @@
1
1
  # echo-pdf
2
2
 
3
- `echo-pdf` 当前阶段定位为本地优先的 PDF context engine for AI agents
3
+ `echo-pdf` is a local-first, vision-language-first PDF context engine for AI agents.
4
4
 
5
- 一句话定义:
5
+ It turns a local PDF into reusable CLI outputs, Node/Bun library primitives, and inspectable workspace artifacts for page rendering, page understanding, semantic structure, and downstream local reuse.
6
6
 
7
- - 把本地 PDF 处理成可复用的 CLI outputs、library primitives 和 workspace artifacts,供本机 agent/app 继续消费。
7
+ ## What It Is
8
8
 
9
- 当前主线产品形态:
9
+ Primary product surfaces:
10
10
 
11
- - npm package:`@echofiles/echo-pdf`
12
- - CLI:`echo-pdf ...`
13
- - 本地 workspace artifacts:`.echo-pdf-workspace/...`
14
- - 文档站:仅用于说明安装、CLI、artifacts 和集成契约,不提供在线处理服务
11
+ - npm package: `@echofiles/echo-pdf`
12
+ - local CLI: `echo-pdf ...`
13
+ - local workspace artifacts: `.echo-pdf-workspace/...`
14
+ - docs site: [pdf.echofile.ai](https://pdf.echofile.ai/)
15
15
 
16
- 目标用户与主要用法:
16
+ Current focus:
17
17
 
18
- - 需要在本机或本地开发环境处理 PDF 的 agent / IDE / app 开发者
19
- - 需要稳定页级 primitives、document context 和可缓存 artifacts 的下游集成方
20
- - 需要 clean consumer import + CLI workflow 的本地组件使用方
18
+ - local-first workflows
19
+ - VL-first page understanding
20
+ - stable page-level document primitives
21
+ - reusable workspace artifacts
22
+ - clean package entrypoints for downstream consumers
21
23
 
22
- 当前阶段能力:
24
+ Non-goals for this phase:
23
25
 
24
- - 页面提取:把 PDF 指定页渲染为图片
25
- - OCR:识别页面文本
26
- - 表格识别:提取表格并输出 LaTeX `tabular`
27
- - 页级文档索引:生成本地可复用的 document / page artifacts
28
- - 语义结构层:在 page index 之上产出可缓存的 heading / section 结构
29
- - 页面渲染与 OCR artifacts:把 page render/image 与 OCR 结果缓存到本地 workspace
26
+ - hosted SaaS
27
+ - treating MCP as the primary product entrypoint
28
+ - turning the docs site into an online PDF processing service
29
+ - domain-specific logic such as datasheet- or EDA-specific extraction behavior
30
30
 
31
- 当前阶段优先:
31
+ ## Install
32
32
 
33
- - 本地 CLI
34
- - 本地 library/client API
35
- - 本地 workspace artifacts
36
- - clean-consumer npm package
33
+ Requirements:
37
34
 
38
- 当前阶段非重点:
35
+ - Node.js `>=20`
36
+ - ESM-capable runtime
39
37
 
40
- - MCP 扩展或把 MCP 作为主入口
41
- - Hosted SaaS / multi-tenant 平台能力
42
- - 把网站做成在线 PDF 服务
43
- - datasheet / EDA 等领域特化逻辑
38
+ Install globally for CLI use:
44
39
 
45
- 进一步的定位说明见:
40
+ ```bash
41
+ npm i -g @echofiles/echo-pdf
42
+ ```
46
43
 
47
- - [`docs/PRODUCT.md`](./docs/PRODUCT.md)
48
- - [`docs/PACKAGING.md`](./docs/PACKAGING.md)
49
- - [`docs/WORKSPACE_CONTRACT.md`](./docs/WORKSPACE_CONTRACT.md)
50
- - [`docs/DEVELOPMENT.md`](./docs/DEVELOPMENT.md)
44
+ Or install as a dependency:
51
45
 
52
- ## Local-first workflow
46
+ ```bash
47
+ npm i @echofiles/echo-pdf
48
+ ```
49
+
50
+ ## Quick Start
53
51
 
54
- 最短路径:
52
+ Index a local PDF and inspect its page-level context:
55
53
 
56
54
  ```bash
57
- npm i -g @echofiles/echo-pdf
58
55
  echo-pdf document ./sample.pdf
59
56
  echo-pdf structure ./sample.pdf
60
- echo-pdf semantic ./sample.pdf
61
57
  echo-pdf page ./sample.pdf --page 1
62
- echo-pdf render ./sample.pdf --page 1
63
- echo-pdf ocr ./sample.pdf --page 1 --model gpt-4.1-mini
58
+ echo-pdf render ./sample.pdf --page 1 --scale 2
64
59
  ```
65
60
 
66
- 源码 checkout 的本地开发路径:
61
+ To run the VL-first semantic path locally, configure a provider key and model once, then run `semantic`:
67
62
 
68
63
  ```bash
69
- npm install
70
- npm run document:dev -- document ./fixtures/smoke.pdf
71
- npm run document:dev -- structure ./fixtures/smoke.pdf
72
- npm run document:dev -- semantic ./fixtures/smoke.pdf
73
- npm run document:dev -- page ./fixtures/smoke.pdf --page 1
64
+ echo-pdf provider set --provider openai --api-key "$OPENAI_API_KEY"
65
+ echo-pdf model set --provider openai --model gpt-4.1-mini
66
+ echo-pdf semantic ./sample.pdf
74
67
  ```
75
68
 
76
- 说明:
69
+ `echo-pdf semantic` now uses the CLI profile's provider/model/api-key settings. If the selected provider or model is missing, it fails early with a clear setup error instead of quietly dropping back to a weaker path.
70
+
71
+ What these commands map to:
77
72
 
78
- - 发布包 / 已构建 checkout:`echo-pdf document ...` 继续走 `dist/`
79
- - 源码 checkout 且还没 build:使用 `npm run document:dev -- ...`
80
- - `document:dev` 只用于本地开发;它会显式优先加载 `src/local/index.ts`,即使仓库里仍然存在旧 `dist/`
81
- - 发布包和正常 `echo-pdf document ...` 仍然只走 `dist/`
73
+ - `document` -> `get_document`
74
+ - `structure` -> `get_document_structure`
75
+ - `semantic` -> `get_semantic_document_structure`
76
+ - `page` -> `get_page_content`
77
+ - `render` -> `get_page_render`
82
78
 
83
- 默认会在当前目录写入可检查的 workspace
79
+ By default, `echo-pdf` writes reusable artifacts into a local workspace:
84
80
 
85
81
  ```text
86
82
  .echo-pdf-workspace/
@@ -95,26 +91,12 @@ npm run document:dev -- page ./fixtures/smoke.pdf --page 1
95
91
  renders/
96
92
  0001.scale-2.json
97
93
  0001.scale-2.png
98
- ocr/
99
- 0001.scale-2.provider-openai.model-gpt-4o.prompt-<hash>.json
100
94
  ```
101
95
 
102
- 这些 artifacts 会在 PDF 未变化时被复用,便于本地下游产品(例如 echo-datasheet)做增量读取。
103
-
104
- 正式的 workspace layout、cache/invalidation、detector/strategy metadata、以及下游可依赖边界,见 [`docs/WORKSPACE_CONTRACT.md`](./docs/WORKSPACE_CONTRACT.md)。
105
-
106
- ## Local library/client API
107
-
108
- 当前阶段优先提供本地可组合 primitives,让下游产品直接围绕 PDF 建立 document metadata / page-level artifacts,而不是先依赖远端 MCP/SaaS。
96
+ These artifacts are meant to be inspected, cached, and reused by downstream local tools.
97
+ ## Library Usage
109
98
 
110
- ### Local-first entrypoints(semver 稳定)
111
-
112
- - `@echofiles/echo-pdf`:core API
113
- - `@echofiles/echo-pdf/core`:与根入口等价的 core API
114
- - `@echofiles/echo-pdf/local`:本地 document primitives
115
- - `@echofiles/echo-pdf/worker`:兼容保留的 Worker 路由入口,不是本阶段重点
116
-
117
- ### Local document primitives
99
+ Use the local document primitives directly from Node/Bun:
118
100
 
119
101
  ```ts
120
102
  import {
@@ -123,523 +105,64 @@ import {
123
105
  get_semantic_document_structure,
124
106
  get_page_content,
125
107
  get_page_render,
126
- get_page_ocr,
127
108
  } from "@echofiles/echo-pdf/local"
128
109
 
129
- const doc = await get_document({ pdfPath: "./sample.pdf" })
130
- const pageIndex = await get_document_structure({ pdfPath: "./sample.pdf" })
110
+ const document = await get_document({ pdfPath: "./sample.pdf" })
111
+ const structure = await get_document_structure({ pdfPath: "./sample.pdf" })
131
112
  const semantic = await get_semantic_document_structure({ pdfPath: "./sample.pdf" })
132
113
  const page1 = await get_page_content({ pdfPath: "./sample.pdf", pageNumber: 1 })
133
- const render1 = await get_page_render({ pdfPath: "./sample.pdf", pageNumber: 1 })
134
- const ocr1 = await get_page_ocr({ pdfPath: "./sample.pdf", pageNumber: 1, model: "gpt-4.1-mini" })
135
- ```
136
-
137
- 这些调用会把 artifacts 写入本地 workspace,并在 PDF 未变化时尽量复用已有页面结果。
138
- `get_document_structure()` 继续返回最小 page index:`document -> pages[]`。
139
- `get_semantic_document_structure()` 单独返回 heading / section 语义层,并写入 `semantic-structure.json`。
140
- `get_page_render()` 会生成可复用的 PNG + metadata。
141
- `get_page_ocr()` 会把 OCR 结果写入独立 artifact;它需要本地 provider key / model,不依赖 MCP 或远端服务入口。
142
-
143
- ### Page Index vs Semantic Structure
144
-
145
- - `get_document_structure()`
146
- - 契约:稳定的 `document -> pages[]`
147
- - artifact:`structure.json`
148
- - 目的:给下游做页级遍历、page artifact 定位、增量读取
149
- - `get_semantic_document_structure()`
150
- - 契约:显式的 heading / section 语义层,优先走本地 provider/model 的 agent 抽取;未配置或失败时退回保守 heuristic
151
- - artifact:`semantic-structure.json`
152
- - 目的:给下游做章节导航、语义分段;它不替代 page index,也不改变 `pages[]` 输出
153
-
154
- 当前 semantic 结构会把 detector 明确写入 artifact:
155
-
156
- - `agent-structured-v1`:使用本地配置的 provider/model 对 page text 进行结构化抽取
157
- - `heading-heuristic-v1`:当本地未配置模型,或 agent 抽取失败时使用的保守回退
158
-
159
- 两种模式都遵循同一输出契约;检测不到时会返回空结构,而不是伪造 section tree。
160
-
161
- ## Tool library compatibility
162
-
163
- 除了 local-first primitives 之外,`@echofiles/echo-pdf` 仍保留现有 `pdf_extract_pages / pdf_ocr_pages / pdf_tables_to_latex / file_ops` 工具实现的复用入口,用于兼容已有集成。
164
-
165
- ### Public entrypoints(semver 稳定)
166
-
167
- - `@echofiles/echo-pdf`:core API
168
- - `@echofiles/echo-pdf/core`:与根入口等价的 core API
169
- - `@echofiles/echo-pdf/local`:本地 document primitives
170
- - `@echofiles/echo-pdf/worker`:Worker 路由入口(兼容保留)
171
-
172
- 仅以上 `exports` 子路径视为公开 API。`src/*`、`dist/*` 等深路径导入不受兼容性承诺保护,可能在次版本中变动。
173
-
174
- 完整的 package entrypoint、runtime、semver、以及 clean-consumer import 保证,见 [`docs/PACKAGING.md`](./docs/PACKAGING.md)。
175
-
176
- ### Runtime expectations
177
-
178
- - Node.js: `>=20`(与 `package.json#engines` 一致)
179
- - 需要 ESM `import` 能力与标准 `fetch`(Node 20+ 原生支持)
180
- - `@echofiles/echo-pdf/local` 面向本地 Node/Bun CLI 或 app runtime
181
- - 建议使用支持 package `exports` 的现代 bundler/runtime(Vite、Webpack 5、Rspack、esbuild、Wrangler 等)
182
- - TypeScript 消费方建议:`module=NodeNext` + `moduleResolution=NodeNext`
183
-
184
- ### Clean project import smoke
185
-
186
- 下面这段命令与仓库中的集成测试保持一致,可在全新目录验证 npm 包“可直接 import”:
187
-
188
- ```bash
189
- tmpdir="$(mktemp -d)"
190
- cd "$tmpdir"
191
- npm init -y
192
- npm i /path/to/echofiles-echo-pdf-<version>.tgz
193
- node --input-type=module -e "await import('@echofiles/echo-pdf'); await import('@echofiles/echo-pdf/core'); await import('@echofiles/echo-pdf/local'); await import('@echofiles/echo-pdf/worker'); console.log('ok')"
194
- ```
195
-
196
- ### Example
197
-
198
- ```ts
199
- import { callTool, listToolSchemas } from "@echofiles/echo-pdf"
200
- import configJson from "./echo-pdf.config.json" with { type: "json" }
201
-
202
- const fileStore = {
203
- async put(input) {
204
- const id = crypto.randomUUID()
205
- const record = { ...input, id, sizeBytes: input.bytes.byteLength, createdAt: new Date().toISOString() }
206
- memory.set(id, record)
207
- return record
208
- },
209
- async get(id) {
210
- return memory.get(id) ?? null
211
- },
212
- async list() {
213
- return [...memory.values()]
214
- },
215
- async delete(id) {
216
- return memory.delete(id)
217
- },
218
- }
219
-
220
- const memory = new Map()
221
- const env = {}
222
-
223
- console.log(listToolSchemas().map((tool) => tool.name))
224
-
225
- const result = await callTool(
226
- "pdf_extract_pages",
227
- { fileId: "<FILE_ID>", pages: [1], returnMode: "inline" },
228
- { config: configJson, env, fileStore }
229
- )
230
- console.log(result)
231
- ```
232
-
233
- 版本策略:
234
-
235
- - `exports` 列出的入口及其导出符号按 semver 管理
236
- - 对公开 API 的破坏性变更只会在 major 版本发布
237
- - 新增导出、参数扩展(向后兼容)会在 minor/patch 发布
238
-
239
- ## 1. Compatibility surfaces(deferred / not primary)
240
-
241
- 以下内容是当前仓库中兼容保留的入口,不是本阶段主线产品形态。
242
- 主线仍然是 npm package + CLI + local workspace artifacts;网站只是文档站,不是在线服务。
243
-
244
- 请先确定你的线上地址(Worker 域名)。文档里用:
245
-
246
- - `https://echo-pdf.echofilesai.workers.dev`
247
-
248
- 你自己的地址如果不同,把下面命令里的域名全部替换掉。
249
-
250
- 主要端点:
251
-
252
- - Web UI: `https://echo-pdf.echofilesai.workers.dev/`
253
- - MCP: `https://echo-pdf.echofilesai.workers.dev/mcp`
254
- - HTTP API 根路径: `https://echo-pdf.echofilesai.workers.dev`
255
-
256
- ## 1.1 API 兼容性说明
257
-
258
- - 从 `v0.3.0` 开始,`POST /tools/call` 返回结构改为:
259
- - `{"ok": true, "data": ..., "artifacts": [...]}`
260
- - 老格式 `{"name":"...","output":...}` 已移除。
261
- - MCP `tools/call` 仍保留 `type:"text"`,并新增 `type:"resource_link"` 供下载二进制结果。
262
-
263
- ## 2. 快速开始(CLI)
264
-
265
- 安装:
266
-
267
- ```bash
268
- npm i -g @echofiles/echo-pdf
114
+ const render1 = await get_page_render({ pdfPath: "./sample.pdf", pageNumber: 1, scale: 2 })
269
115
  ```
270
116
 
271
- 初始化服务地址:
117
+ Notes:
272
118
 
273
- ```bash
274
- echo-pdf init --service-url https://echo-pdf.echofilesai.workers.dev
275
- ```
119
+ - `get_document_structure()` returns the stable page index: `document -> pages[]`
120
+ - `get_semantic_document_structure()` returns a separate semantic structure layer; it does not replace `pages[]`
121
+ - `get_page_render()` materializes a reusable PNG plus render metadata and is the mainline visual input path
276
122
 
277
- 本地一键启动服务(daemon):
123
+ Migration note:
278
124
 
279
- ```bash
280
- echo-pdf dev --port 8788
281
- echo-pdf init --service-url http://127.0.0.1:8788
282
- ```
125
+ - older workspaces may still contain `ocr/*` artifacts from pre-VL-first builds, but they are no longer part of the supported first-class contract
283
126
 
284
- 配置 API Key(仅保存在本机 CLI 配置,不会上报到服务端存储):
127
+ ## Public Package Entrypoints
285
128
 
286
- ```bash
287
- echo-pdf provider set --provider openai --api-key <OPENAI_API_KEY>
288
- echo-pdf provider set --provider openrouter --api-key <OPENROUTER_KEY>
289
- echo-pdf provider set --provider vercel-ai-gateway --api-key <VERCEL_AI_GATEWAY_API_KEY>
290
- ```
129
+ The semver-stable public entrypoints are:
291
130
 
292
- 设置默认 provider + model(项目采用单一默认,不做多层 fallback):
131
+ - `@echofiles/echo-pdf`
132
+ - `@echofiles/echo-pdf/local`
293
133
 
294
- ```bash
295
- echo-pdf provider use --provider vercel_gateway
296
- echo-pdf model set --provider vercel_gateway --model google/gemini-3-flash
297
- echo-pdf model list
298
- ```
134
+ `@echofiles/echo-pdf` and `@echofiles/echo-pdf/local` expose the same supported local-first library surface.
299
135
 
300
- 拉取 provider 模型列表(实时从 provider API 获取,无 hardcode):
136
+ Everything else, including deep imports such as `src/*` or `dist/*`, is private implementation detail.
301
137
 
302
- ```bash
303
- echo-pdf models --provider vercel_gateway
304
- ```
138
+ ## Docs
305
139
 
306
- 修改运行时配置(写入 `.dev.vars` `ECHO_PDF_CONFIG_JSON`):
140
+ Contract and product docs:
307
141
 
308
- ```bash
309
- echo-pdf config set --key service.maxPdfBytes --value 10000000
310
- echo-pdf config set --key service.storage.maxFileBytes --value 10000000
311
- echo-pdf config set --key service.maxPagesPerRequest --value 20
312
- ```
313
-
314
- ## 2.1 六个核心 primitives
315
-
316
- 本地 CLI 主命令面与 `@echofiles/echo-pdf/local` 的六个 primitives 一一对应:
317
-
318
- - `document <file.pdf>` -> `get_document`
319
- - `structure <file.pdf>` -> `get_document_structure`
320
- - `semantic <file.pdf>` -> `get_semantic_document_structure`
321
- - `page <file.pdf> --page <N>` -> `get_page_content`
322
- - `render <file.pdf> --page <N>` -> `get_page_render`
323
- - `ocr <file.pdf> --page <N>` -> `get_page_ocr`
142
+ - [Product positioning](./docs/PRODUCT.md)
143
+ - [Package entrypoints and integration guarantees](./docs/PACKAGING.md)
144
+ - [Workspace artifact contract](./docs/WORKSPACE_CONTRACT.md)
145
+ - [Development guide](./docs/DEVELOPMENT.md)
146
+ - [Shared sample assets](./samples/README.md)
147
+ - [Eval harness](./eval/README.md)
324
148
 
325
- 兼容边界:
149
+ Published docs site:
326
150
 
327
- - 旧的 `document get|index|structure|semantic|page|render|ocr ...` 仍作为兼容别名保留
328
- - README 和 `--help` 现在优先展示这六个主命令,而不是旧的子命令树
151
+ - [pdf.echofile.ai](https://pdf.echofile.ai/)
329
152
 
330
- 建立本地索引并输出 metadata:
331
-
332
- ```bash
333
- echo-pdf document ./sample.pdf
334
- ```
335
-
336
- 读取结构树:
337
-
338
- ```bash
339
- echo-pdf structure ./sample.pdf
340
- ```
341
-
342
- 读取语义结构层:
343
-
344
- ```bash
345
- echo-pdf semantic ./sample.pdf
346
- ```
347
-
348
- 读取指定页面内容:
349
-
350
- ```bash
351
- echo-pdf page ./sample.pdf --page 1
352
- ```
353
-
354
- 生成页面渲染 artifact:
355
-
356
- ```bash
357
- echo-pdf render ./sample.pdf --page 1 --scale 2
358
- ```
359
-
360
- 生成 OCR artifact(需要本地 provider key / model):
361
-
362
- ```bash
363
- echo-pdf ocr ./sample.pdf --page 1 --model gpt-4.1-mini
364
- ```
365
-
366
- 自定义 artifact workspace:
367
-
368
- ```bash
369
- echo-pdf document ./sample.pdf --workspace ./.cache/echo-pdf
370
- ```
371
-
372
- ## 3. MCP 使用(兼容保留,非本阶段重点)
373
-
374
- ### 3.1 检查 MCP 服务可用
375
-
376
- ```bash
377
- echo-pdf mcp initialize
378
- echo-pdf mcp tools
379
- echo-pdf mcp call --tool file_ops --args '{"op":"list"}'
380
- ```
381
-
382
- ### 3.1.1 纯 MCP 场景推荐流程(本地 PDF)
383
-
384
- 远端 MCP server 无法直接读取你本机文件路径。推荐两步:
385
-
386
- 1. 先通过 HTTP 上传本地 PDF,拿到 `fileId`
387
- 2. 再用 MCP 工具传 `fileId` 调用
388
-
389
- 示例:
390
-
391
- ```bash
392
- curl -sS -X POST https://echo-pdf.echofilesai.workers.dev/api/files/upload \
393
- -F 'file=@./input.pdf'
394
-
395
- echo-pdf mcp call --tool pdf_extract_pages --args '{"fileId":"<FILE_ID>","pages":[1]}'
396
- ```
397
-
398
- ### 3.1.2 不上传文件的 URL ingest 流程
399
-
400
- 如果 PDF 已经在公网可访问,直接传 `url`:
401
-
402
- ```bash
403
- echo-pdf mcp call --tool pdf_extract_pages --args '{
404
- "url":"https://example.com/sample.pdf",
405
- "pages":[1]
406
- }'
407
- ```
408
-
409
- ### 3.1.3 stdio MCP(支持本地文件路径)
410
-
411
- stdio 模式会把本地 `path/filePath` 自动上传为 `fileId` 后再调用远端工具。
412
-
413
- ```bash
414
- echo-pdf mcp-stdio
415
- ```
416
-
417
- 生成 Claude Desktop/Cursor 等可用的 stdio 配置片段:
418
-
419
- ```bash
420
- echo-pdf setup add claude-desktop --mode stdio
421
- ```
422
-
423
- ### 3.2 给客户端生成 MCP 配置片段
424
-
425
- ```bash
426
- echo-pdf setup add claude-desktop
427
- echo-pdf setup add cursor
428
- echo-pdf setup add cline
429
- echo-pdf setup add windsurf
430
- echo-pdf setup add json
431
- echo-pdf setup add claude-desktop --mode stdio
432
- ```
433
-
434
- `setup add` 输出的是配置片段,把它合并到对应客户端的 MCP 配置文件。
435
-
436
- ### 3.3 MCP 工具列表
437
-
438
- - `pdf_extract_pages`
439
- - `pdf_ocr_pages`
440
- - `pdf_tables_to_latex`
441
- - `file_ops`
442
-
443
- MCP 输出策略:
444
-
445
- - `pdf_extract_pages` 在 MCP 下默认 `returnMode=url`(不传 `returnMode` 时生效)
446
- - MCP `text` 会对大字段做去二进制/截断,避免把大段 base64 塞进上下文
447
- - 二进制结果请优先使用 `resource_link` 中的下载地址
448
-
449
- ## 4. Web UI 使用
450
-
451
- 打开:
452
-
453
- - `https://echo-pdf.echofilesai.workers.dev/`
454
-
455
- 流程:
456
-
457
- 1. 选择 provider。
458
- 2. 点击“测试模型列表”后,选择一个模型。
459
- 3. 上传 PDF。
460
- 4. 选择工具并填写参数(例如 `pages: [1]`)。
461
- 5. 点击 `Run Tool` 或 `Run Stream`。
462
-
463
- 说明:
464
-
465
- - UI 中输入的 key 属于当前会话,不落库到服务端。
466
- - `returnMode` 支持 `inline`、`file_id`、`url`。
467
- - `tools/call` 返回统一结构:`{ ok, data, artifacts }`,其中 `artifacts[*].url` 可直接下载。
468
- - 表格工具返回值会校验并要求包含合法 `tabular`,否则报错。
469
-
470
- ## 5. HTTP API 使用
471
-
472
- ### 5.1 上传 PDF
473
-
474
- ```bash
475
- curl -sS -X POST https://echo-pdf.echofilesai.workers.dev/api/files/upload \
476
- -F 'file=@./sample.pdf'
477
- ```
478
-
479
- 返回中会拿到 `file.id`。
480
-
481
- CLI 等价命令:
482
-
483
- ```bash
484
- echo-pdf file upload ./sample.pdf
485
- ```
486
-
487
- ### 5.2 提取页面图片
488
-
489
- ```bash
490
- curl -sS -X POST https://echo-pdf.echofilesai.workers.dev/tools/call \
491
- -H 'content-type: application/json' \
492
- -d '{
493
- "name":"pdf_extract_pages",
494
- "arguments":{"fileId":"<FILE_ID>","pages":[1],"returnMode":"inline"},
495
- "provider":"vercel_gateway",
496
- "model":"google/gemini-3-flash"
497
- }'
498
- ```
499
-
500
- CLI(默认不自动上传本地文件,需显式开启):
501
-
502
- ```bash
503
- echo-pdf call --tool pdf_extract_pages --auto-upload --args '{"path":"./sample.pdf","pages":[1],"returnMode":"url"}'
504
- ```
505
-
506
- 说明:
507
-
508
- - `echo-pdf call` 默认禁用本地文件自动上传,避免误上传脚枪。
509
- - 需要自动上传时,显式传 `--auto-upload`,CLI 会回显上传清单(本地路径 -> fileId)。
510
- - 如果是本地 agent/IDE 场景,优先使用 `echo-pdf mcp-stdio`,它会按 MCP stdio 约定处理 `path/filePath` 自动上传。
511
-
512
- 下载产物:
513
-
514
- ```bash
515
- echo-pdf file get --file-id <FILE_ID> --out ./output.bin
516
- ```
517
-
518
- ### 5.3 OCR
519
-
520
- ```bash
521
- curl -sS -X POST https://echo-pdf.echofilesai.workers.dev/tools/call \
522
- -H 'content-type: application/json' \
523
- -d '{
524
- "name":"pdf_ocr_pages",
525
- "arguments":{"fileId":"<FILE_ID>","pages":[1],"provider":"vercel_gateway","model":"google/gemini-3-flash"}
526
- }'
527
- ```
528
-
529
- ### 5.4 表格识别为 LaTeX
530
-
531
- ```bash
532
- curl -sS -X POST https://echo-pdf.echofilesai.workers.dev/tools/call \
533
- -H 'content-type: application/json' \
534
- -d '{
535
- "name":"pdf_tables_to_latex",
536
- "arguments":{"fileId":"<FILE_ID>","pages":[1],"provider":"vercel_gateway","model":"google/gemini-3-flash"}
537
- }'
538
- ```
539
-
540
- ## 6. 配置与环境变量
541
-
542
- 统一配置文件:`echo-pdf.config.json`
543
-
544
- 关键字段:
545
-
546
- - `agent.defaultProvider`
547
- - `agent.defaultModel`
548
- - `service.publicBaseUrl`
549
- - `service.fileGet.cacheTtlSeconds`
550
- - `service.maxPdfBytes`
551
- - `service.storage.maxFileBytes`
552
- - `service.storage.maxTotalBytes`
553
- - `service.storage.ttlHours`
554
-
555
- 限制关系说明:
556
-
557
- - `service.maxPdfBytes`:允许处理的 PDF 最大字节数。
558
- - `service.storage.maxFileBytes`:文件存储单文件上限(上传 PDF、`url/base64` ingest、以及 `file_id` 结果都会落到存储层)。
559
- - 当前项目要求 `service.storage.maxFileBytes >= service.maxPdfBytes`,否则配置无效并在启动时报错。
560
- - 当前默认配置下两者都是 `10000000`(10MB)。
561
- - 当未绑定 R2、使用 DO 存储时,`service.storage.maxFileBytes` 必须 `<= 1200000`,否则启动会报错。
562
- - 生产建议始终绑定 R2,并让 DO 只负责协调/元数据,不承载大文件数据。
563
-
564
- 常用环境变量:
565
-
566
- - `OPENAI_API_KEY`
567
- - `OPENROUTER_KEY` / `OPENROUTER_API_KEY`
568
- - `VERCEL_AI_GATEWAY_API_KEY` / `VERCEL_AI_GATEWAY_KEY`
569
- - `ECHO_PDF_DEFAULT_PROVIDER`
570
- - `ECHO_PDF_DEFAULT_MODEL`
571
- - `ECHO_PDF_PUBLIC_BASE_URL`(可选,强制 artifacts 生成外部可访问绝对 URL)
572
- - `ECHO_PDF_FILE_GET_CACHE_TTL_SECONDS`(可选,`/api/files/get` 缓存秒数,`0` 表示 `no-store`)
573
- - `ECHO_PDF_FILE_GET_AUTH_HEADER` + `ECHO_PDF_FILE_GET_AUTH_ENV`(可选,启用下载端点 header 鉴权)
574
- - `ECHO_PDF_MCP_KEY`(可选,启用 MCP 鉴权)
575
- - `ECHO_PDF_WORKER_NAME`(CLI 默认 URL 推导)
576
-
577
- 鉴权注意:
578
-
579
- - 如果配置了 `authHeader/authEnv` 但未注入对应 secret,服务会返回配置错误(fail-closed),不会默认放行。
580
- - 仅开发调试场景可显式设置 `ECHO_PDF_ALLOW_MISSING_AUTH_SECRET=1` 临时放行“缺 secret”的请求。
581
-
582
- ## 7. 本地开发与测试
583
-
584
- 安装与开发:
585
-
586
- ```bash
587
- npm install
588
- npm run dev
589
- ```
590
-
591
- 测试:
153
+ ## Development
592
154
 
593
155
  ```bash
156
+ npm ci
157
+ npm run build
594
158
  npm run typecheck
595
- npm run test
596
- npm run smoke
597
- ```
598
-
599
- 导出真实调用结果到 `fixtures/output`(会先清空输出目录):
600
-
601
- ```bash
602
- INPUT_PDF=./fixtures/input.pdf ./scripts/export-fixtures.sh
159
+ npm run test:unit
160
+ npm run test:acceptance
161
+ npm run test:integration
603
162
  ```
604
163
 
605
- ## 8. 常见问题
606
-
607
- ### 8.1 设置了模型但没生效
608
-
609
- 请确认三处一致:
610
-
611
- - CLI 当前 profile 的 `model set` 值
612
- - 请求里传入的 `model`
613
- - 实际 provider 的模型列表中存在该 model
614
-
615
- 当前项目策略是“用户设置的 provider/model 即默认”,不会自动切换到其它模型。
616
-
617
- ### 8.2 `pdf_tables_to_latex` 返回失败
618
-
619
- 当前实现要求模型输出中必须包含合法 `\\begin{tabular}...\\end{tabular}`。如果模型返回解释性文本或超时,会直接报错。
620
-
621
- ### 8.3 `returnMode=url` 如何使用
622
-
623
- `url` 模式会把结果落到存储层,并返回一个可直接 `GET` 的下载地址:
624
-
625
- - `GET /api/files/get?fileId=<id>`
626
-
627
- 示例(提取页面并返回 URL):
628
-
629
- ```bash
630
- curl -sS -X POST https://echo-pdf.echofilesai.workers.dev/tools/call \
631
- -H 'content-type: application/json' \
632
- -d '{
633
- "name":"pdf_extract_pages",
634
- "arguments":{"fileId":"<FILE_ID>","pages":[1],"returnMode":"url"}
635
- }'
636
- ```
164
+ For source-checkout CLI development and repo-local workflows, see [docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md).
637
165
 
638
- ### 8.4 错误码语义
166
+ ## License
639
167
 
640
- - 客户端输入错误返回稳定 `4xx + code`,例如:
641
- - `PAGES_REQUIRED`(400)
642
- - `PAGE_OUT_OF_RANGE`(400)
643
- - `MISSING_FILE_INPUT`(400)
644
- - `FILE_NOT_FOUND`(404)
645
- - 服务端故障返回 `5xx`。
168
+ Apache-2.0