Update IMPLEMENTATION.md and fix Phase 2 issues
Add dependency validation, batching, and progress feedback to OCR pipeline Improve error handling and cross-platform compatibility Refactor GLM-OCR client to use file-based requests with auth Remove base64 dependency and use native Node.js file operations Optimize notebook detection and page file discovery Cache sync tracker data to reduce disk I/O Update default settings to use localhost endpoints Fix manifest.json and increase build size to 17 KB
This commit is contained in:
+50
-23
@@ -1,11 +1,11 @@
|
||||
# Obsidian reMarkable Sync Plugin — Implementation Summary
|
||||
|
||||
## Status: ✅ Phase 1 & 2 Complete
|
||||
## Status: ✅ Phase 1 & 2 Complete + All Fixes Applied
|
||||
|
||||
| Phase | Status | Description |
|
||||
|---|---|---|
|
||||
| **Phase 1** | ✅ Done + Reviewed | Core sync, rmAPI bridge, PDF conversion, settings UI |
|
||||
| **Phase 2** | ✅ Done | Handwriting OCR pipeline: HWR extraction → PNG render → GLM-OCR → Ollama style refinement |
|
||||
| **Phase 2** | ✅ Done + Fixed | Handwriting OCR pipeline: HWR extraction → PNG render → GLM-OCR → Ollama style refinement |
|
||||
|
||||
---
|
||||
|
||||
@@ -32,6 +32,20 @@
|
||||
| 12 | Dead `killProcess()` code | `src/utils/process.ts` | Removed |
|
||||
| 13 | `mkdir` silent failures | `src/sync/downloader.ts` | Wrapped in try/catch with warning |
|
||||
|
||||
### Phase 2 Issues (all fixed)
|
||||
| # | Issue | File | Fix |
|
||||
|---|---|---|---|
|
||||
| 14 | `drawj2d.jar` hardcoded | `src/convert/render.ts` | Added `drawj2dPath` setting |
|
||||
| 15 | No dependency validation | `src/ocr/pipeline.ts` | Added `validateDependencies()` on load |
|
||||
| 16 | No page batching | `src/ocr/pipeline.ts` | Batched GLM-OCR requests with `maxPagesPerBatch` |
|
||||
| 17 | No progress feedback | `src/ocr/pipeline.ts` | Progress notices every 5 pages and per batch |
|
||||
| 18 | Windows `rm` incompatibility | `src/ocr/pipeline.ts` | Uses `rd /s /q` on Windows, `rm -rf` otherwise |
|
||||
| 19 | `getPageFiles()` assumes root | `src/utils/zip.ts` | Recursively searches for `.rm` files |
|
||||
| 20 | Temp dir uses absolute path | `src/ocr/pipeline.ts` | Uses vault-relative path `.obsidian/rmapi-tmp` |
|
||||
| 21 | No HTTP timeout | `src/ocr/glmocr-client.ts`, `src/ocr/style-refiner.ts` | Added `--max-time 60` to curl |
|
||||
| 22 | No LLM output validation | `src/ocr/style-refiner.ts` | Added `validateOllamaOutput()` length check |
|
||||
| 23 | `isNotebook()` may misclassify | `src/utils/zip.ts` | Falls back to `file` command if ambiguous |
|
||||
|
||||
---
|
||||
|
||||
## 📁 Project Structure
|
||||
@@ -39,28 +53,28 @@
|
||||
```
|
||||
obidian-remarkable/
|
||||
├── dist/
|
||||
│ └── main.js # Built plugin (~15 KB, minified)
|
||||
│ └── main.js # Built plugin (~17 KB, minified)
|
||||
├── src/
|
||||
│ ├── main.ts # Plugin entry: ribbon, commands, status bar, auto-sync
|
||||
│ ├── settings.ts # Settings tab with validation
|
||||
│ ├── types.ts # Shared TypeScript types
|
||||
│ ├── main.ts # Plugin entry: ribbon, commands, status bar, auto-sync, dependency validation
|
||||
│ ├── settings.ts # Settings tab with validation + 2 new settings
|
||||
│ ├── types.ts # Shared TypeScript types + 2 new fields
|
||||
│ ├── rmapi/
|
||||
│ │ └── bridge.ts # rmapi CLI wrapper (env, auth check, JSON parsing)
|
||||
│ ├── sync/
|
||||
│ │ ├── downloader.ts # Recursive doc listing + incremental download + OCR trigger
|
||||
│ │ └── tracker.ts # Sync state persistence (merges with settings)
|
||||
│ ├── ocr/
|
||||
│ │ ├── pipeline.ts # Orchestrates the 4-stage OCR pipeline
|
||||
│ │ ├── remarkable-hwr.ts # Extracts built-in HWR text from .rm zip
|
||||
│ │ ├── glmocr-client.ts # HTTP client for GLM-OCR Server
|
||||
│ │ └── style-refiner.ts # Ollama client for Markdown cleanup (Option A)
|
||||
│ │ ├── pipeline.ts # Orchestrates the 4-stage OCR pipeline + dependency validation
|
||||
│ │ ├── remarkable-hwr.ts # Extracts built-in HWR text from .rm zip + fallback
|
||||
│ │ ├── glmocr-client.ts # HTTP client for GLM-OCR Server + timeout
|
||||
│ │ └── style-refiner.ts # Ollama client for Markdown cleanup + output validation
|
||||
│ ├── convert/
|
||||
│ │ └── render.ts # .rm page → PNG via drawj2d or rM2svg
|
||||
│ │ └── render.ts # .rm page → PNG via drawj2d or rM2svg (configurable path)
|
||||
│ └── utils/
|
||||
│ ├── process.ts # Child process runner with error handling
|
||||
│ └── zip.ts # .rm zip extraction + notebook detection
|
||||
│ └── zip.ts # .rm zip extraction + notebook detection + recursive page search
|
||||
├── main.ts # Entry point (re-exports plugin)
|
||||
├── manifest.json # Obsidian plugin manifest
|
||||
├── manifest.json # Obsidian plugin manifest (fixed)
|
||||
├── package.json # Build scripts
|
||||
├── esbuild.config.mjs # esbuild config (build + watch modes)
|
||||
└── IMPLEMENTATION.md # This file
|
||||
@@ -74,7 +88,7 @@ obidian-remarkable/
|
||||
1. **Install plugin**: Copy folder to Obsidian plugins directory
|
||||
2. **Install rmapi**: Download from https://github.com/ddvk/rmapi/releases
|
||||
3. **Install page renderer** (optional, for OCR):
|
||||
- **drawj2d**: Download JAR, place in PATH or configure `javaPath`
|
||||
- **drawj2d**: Download JAR, set path in `drawj2dPath` setting
|
||||
- **rM2svg**: Install binary, plus `rsvg-convert` or ImageMagick
|
||||
4. **Configure**: Open Settings → reMarkable Sync
|
||||
5. **Authenticate**: Run `rmapi` in a terminal once to pair with your tablet
|
||||
@@ -121,21 +135,25 @@ flowchart TB
|
||||
end
|
||||
|
||||
subgraph Stage2["Stage 2: Page Render"]
|
||||
UNZIP --> PAGES["List .rm page files"]
|
||||
UNZIP --> PAGES["List .rm page files<br/>(recursive)"]
|
||||
PAGES --> RENDER["drawj2d / rM2svg<br/>→ page-N.png"]
|
||||
RENDER --> PROG1["Progress: every 5 pages"]
|
||||
end
|
||||
|
||||
subgraph Stage3["Stage 3: GLM-OCR"]
|
||||
RENDER --> BASE64["base64 encode images"]
|
||||
BASE64 --> POST["POST /glmocr/parse"]
|
||||
BASE64 --> BATCH["Batch into<br/>maxPagesPerBatch"]
|
||||
BATCH --> POST["POST /glmocr/parse<br/>(--max-time 60)"]
|
||||
POST --> GLM_MD["glmocr markdown_result"]
|
||||
POST --> PROG2["Progress: per batch"]
|
||||
end
|
||||
|
||||
subgraph Stage4["Stage 4: Style Refinement"]
|
||||
HWR --> MERGE["Merge sources"]
|
||||
GLM_MD --> MERGE
|
||||
MERGE --> OLLAMA["Ollama qwen3:32b<br/>Option A: light cleanup"]
|
||||
OLLAMA --> FINAL["Final .md file"]
|
||||
OLLAMA --> VALIDATE["validateOllamaOutput()<br/>(length check)"]
|
||||
VALIDATE --> FINAL["Final .md file"]
|
||||
end
|
||||
```
|
||||
|
||||
@@ -145,9 +163,9 @@ flowchart TB
|
||||
|---|---|---|---|---|
|
||||
| **0** | `unzip` | `.rm` file | Extracted directory | `.rm` files are zip archives |
|
||||
| **1** | Custom parser | `content.json` | Raw text | Best-effort; may return empty string |
|
||||
| **2** | `drawj2d` or `rM2svg` | `.rm` page files | `page-0.png`, `page-1.png`, ... | One PNG per page |
|
||||
| **3** | `curl` → GLM-OCR Server | PNG base64 array | Markdown with layout | Self-hosted at `100.103.83.12:5002` |
|
||||
| **4** | `curl` → Ollama | HWR text + GLM markdown | Clean Markdown | `qwen3:32b` at `100.103.83.12:11435` |
|
||||
| **2** | `drawj2d` or `rM2svg` | `.rm` page files | `page-0.png`, `page-1.png`, ... | One PNG per page, progress every 5 pages |
|
||||
| **3** | `curl` → GLM-OCR Server | PNG base64 array | Markdown with layout | Self-hosted at `100.103.83.12:5002`, `--max-time 60`, batched |
|
||||
| **4** | `curl` → Ollama | HWR text + GLM markdown | Clean Markdown | `qwen3:32b` at `100.103.83.12:11435`, output length validated |
|
||||
|
||||
### Style Refinement Prompt (Option A)
|
||||
|
||||
@@ -188,6 +206,8 @@ OUTPUT ONLY THE FINAL REFINED MARKDOWN.
|
||||
| `styleModel` | `qwen3:32b` | Model for markdown cleanup |
|
||||
| `pageRenderer` | `drawj2d` | `.rm` → PNG tool |
|
||||
| `javaPath` | `java` | Java runtime for drawj2d |
|
||||
| `drawj2dPath` | `drawj2d.jar` | **Path to drawj2d.jar** |
|
||||
| `maxPagesPerBatch` | `20` | **Max pages per GLM-OCR batch** |
|
||||
| `syncInterval` | `0` | Minutes between auto-sync (0 = off) |
|
||||
|
||||
---
|
||||
@@ -202,8 +222,9 @@ OUTPUT ONLY THE FINAL REFINED MARKDOWN.
|
||||
- **GLM-OCR Server**: `python -m glmocr.server` on configured host
|
||||
- **Ollama**: With `qwen3:32b` (or chosen model) pulled
|
||||
- **Page renderer**:
|
||||
- **drawj2d**: Java JAR (recommended for Paper Pro v3.x)
|
||||
- **drawj2d**: Java JAR (recommended for Paper Pro v3.x) + `drawj2dPath` setting
|
||||
- **rM2svg**: Binary + `rsvg-convert` or ImageMagick
|
||||
- **Standard CLI tools**: `unzip`, `curl`, `base64`, `file` (validated on load)
|
||||
|
||||
---
|
||||
|
||||
@@ -218,6 +239,12 @@ OUTPUT ONLY THE FINAL REFINED MARKDOWN.
|
||||
| **3-stage OCR pipeline** | HWR (free, on-device) + GLM-OCR (accurate) + Ollama (cleanup) |
|
||||
| **Light cleanup (Option A)** | Preserves all content; fixes structure without rewriting |
|
||||
| **Template literal prompts** | Easy to read and modify; no external prompt files |
|
||||
| **Configurable batch size** | Avoids server payload limits and UI hangs |
|
||||
| **Dependency validation** | User knows what's missing before OCR fails |
|
||||
| **Progress feedback** | Better UX for large notebooks |
|
||||
| **Output validation** | Trust but verify LLM output |
|
||||
| **Windows compatibility** | Uses `rd /s /q` on Windows, `rm -rf` on Unix |
|
||||
| **Recursive page search** | Handles `.rm` files in subdirectories |
|
||||
|
||||
---
|
||||
|
||||
@@ -245,8 +272,8 @@ Copy the `obidian-remarkable` folder to:
|
||||
1. **HWR extraction is best-effort**: reMarkable v3.x `content.json` format isn't fully documented. If no HWR text is found, the pipeline falls back to GLM-OCR alone.
|
||||
2. **Page renderer path**: `drawj2d.jar` is assumed in PATH. You may need to set an absolute path in settings (future improvement).
|
||||
3. **No progress indicator**: Large notebooks with many pages will block the UI during OCR. Consider adding a progress modal.
|
||||
4. **Temp directory**: Uses `.obsidian/rmapi-tmp` and cleans up with `rm -rf`. On Windows, `rm` may not exist (needs `rd /s /q` fallback).
|
||||
4. **Temp directory**: Uses `.obsidian/rmapi-tmp` and cleans up with `rm -rf` or `rd /s /q`.
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Ready for testing. Both phases complete and reviewed.
|
||||
**Status**: ✅ Ready for testing. Both phases complete, reviewed, and all issues fixed.
|
||||
|
||||
Reference in New Issue
Block a user