mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 00:28:33 +00:00
## Summary This PR adds write capabilities to AFFiNE's MCP (Model Context Protocol) integration, enabling external tools (Claude, GPT, etc.) to create and modify documents programmatically. **New MCP Tools:** - `create_document` - Create new documents from markdown content - `update_document` - Update document content using structural diffing for minimal changes (preserves document history and enables real-time collaboration) **Implementation:** - `markdown_to_ydoc.rs` - Converts markdown to AFFiNE-compatible y-octo binary format - `markdown_utils.rs` - Shared markdown parsing utilities (used by both ydoc-to-md and md-to-ydoc) - `update_ydoc.rs` - Structural diffing implementation for updating existing documents - `DocWriter` service - TypeScript service for document operations - Exposes `markdownToDocBinary` and `updateDocBinary` via napi bindings **Supported Markdown Elements:** - Headings (H1-H6) - Paragraphs - Bullet lists and numbered lists - Code blocks (with language detection) - Blockquotes - Horizontal dividers - Todo items (checkboxes) **y-octo Changes:** This PR reverts the y-octo sync (ca2462f,a5b60cf) which introduced a concurrency bug causing hangs when creating documents with many nested block structures. It also ports the improved `get_node_index` binary search fix from upstream that prevents divide-by-zero panics when decoding documents. ## Test Results ✅ ### Unit Tests (47/47 passing) | Test Suite | Tests | Status | |------------|-------|--------| | markdown_to_ydoc | 16/16 | ✅ Pass | | markdown_utils | 11/11 | ✅ Pass | | update_ydoc | 13/13 | ✅ Pass | | delta_markdown | 2/2 | ✅ Pass | | affine (doc parser) | 5/5 | ✅ Pass | ### End-to-End MCP Testing ✅ Tested against local AFFiNE server with real MCP client requests: | Tool | Result | Notes | |------|--------|-------| | `tools/list` | ✅ Pass | Returns all 5 tools with correct schemas | | `create_document` | ✅ Pass | Successfully created test documents | | `update_document` | ✅ Pass | Successfully updated documents with structural diffing | | `read_document` | ✅ Pass | Existing tool, works correctly | | `keyword_search` | ✅ Pass | Existing tool, works correctly | **E2E Test Details:** - Started local AFFiNE server with PostgreSQL, Redis, and Manticore - Created test user and workspace via seed/GraphQL - Verified MCP endpoint at `/api/workspaces/:workspaceId/mcp` - Tested JSON-RPC calls with proper SSE streaming - Confirmed documents are stored and indexed correctly (verified via server logs) ## Test Plan - [x] All Rust unit tests pass (47 tests) - [x] Native bindings build successfully (release mode) - [x] Document creation via MCP works end-to-end - [x] Document update via MCP works end-to-end - [x] CodeRabbit feedback addressed - [ ] Integration testing with Claude/GPT MCP clients Closes #14161 --- **Requested by:** @realies **Key guidance from:** @darkskygit (use y-octo instead of yjs for memory efficiency) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Create documents from Markdown: generate new documents directly from Markdown content with automatic title extraction * Update documents with Markdown: modify existing documents using Markdown as the source with automatic diff calculation for efficient updates * Copilot integration: new tools for document creation and updates through Copilot's interface <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
146 lines
4.1 KiB
TOML
146 lines
4.1 KiB
TOML
[workspace]
|
|
members = [
|
|
"./packages/backend/native",
|
|
"./packages/common/native",
|
|
"./packages/common/y-octo/core",
|
|
"./packages/common/y-octo/utils",
|
|
"./packages/frontend/mobile-native",
|
|
"./packages/frontend/native",
|
|
"./packages/frontend/native/nbstore",
|
|
"./packages/frontend/native/schema",
|
|
"./packages/frontend/native/sqlite_v1",
|
|
]
|
|
resolver = "3"
|
|
|
|
[workspace.package]
|
|
edition = "2024"
|
|
|
|
[workspace.dependencies]
|
|
affine_common = { path = "./packages/common/native" }
|
|
affine_nbstore = { path = "./packages/frontend/native/nbstore" }
|
|
ahash = "0.8"
|
|
anyhow = "1"
|
|
arbitrary = { version = "1.3", features = ["derive"] }
|
|
assert-json-diff = "2.0"
|
|
async-lock = { version = "3.4.0", features = ["loom"] }
|
|
base64-simd = "0.8"
|
|
bitvec = "1.0"
|
|
block2 = "0.6"
|
|
byteorder = "1.5"
|
|
chrono = "0.4"
|
|
clap = { version = "4.4", features = ["derive"] }
|
|
core-foundation = "0.10"
|
|
coreaudio-rs = "0.12"
|
|
cpal = "0.15"
|
|
criterion = { version = "0.5", features = ["html_reports"] }
|
|
criterion2 = { version = "3", default-features = false }
|
|
crossbeam-channel = "0.5"
|
|
dispatch2 = "0.3"
|
|
docx-parser = { git = "https://github.com/toeverything/docx-parser" }
|
|
dotenvy = "0.15"
|
|
file-format = { version = "0.28", features = ["reader"] }
|
|
homedir = "0.3"
|
|
infer = { version = "0.19.0" }
|
|
lasso = { version = "0.7", features = ["multi-threaded"] }
|
|
lib0 = { version = "0.16", features = ["lib0-serde"] }
|
|
libc = "0.2"
|
|
log = "0.4"
|
|
loom = { version = "0.7", features = ["checkpoint"] }
|
|
memory-indexer = "0.3.0"
|
|
mimalloc = "0.1"
|
|
mp4parse = "0.17"
|
|
nanoid = "0.4"
|
|
napi = { version = "3.7.0", features = [
|
|
"async",
|
|
"chrono_date",
|
|
"error_anyhow",
|
|
"napi9",
|
|
"serde",
|
|
] }
|
|
napi-build = { version = "2" }
|
|
napi-derive = { version = "3.4" }
|
|
nom = "8"
|
|
notify = { version = "8", features = ["serde"] }
|
|
objc2 = "0.6"
|
|
objc2-foundation = "0.3"
|
|
once_cell = "1"
|
|
ordered-float = "5"
|
|
parking_lot = "0.12"
|
|
path-ext = "0.1.2"
|
|
pdf-extract = { git = "https://github.com/toeverything/pdf-extract", branch = "darksky/improve-font-decoding" }
|
|
phf = { version = "0.11", features = ["macros"] }
|
|
proptest = "1.3"
|
|
proptest-derive = "0.5"
|
|
pulldown-cmark = "0.13"
|
|
rand = "0.9"
|
|
rand_chacha = "0.9"
|
|
rand_distr = "0.5"
|
|
rayon = "1.10"
|
|
readability = { version = "0.3.0", default-features = false }
|
|
regex = "1.10"
|
|
rubato = "0.16"
|
|
screencapturekit = "0.3"
|
|
serde = "1"
|
|
serde_json = "1"
|
|
sha3 = "0.10"
|
|
smol_str = "0.3"
|
|
sqlx = { version = "0.8", default-features = false, features = [
|
|
"chrono",
|
|
"macros",
|
|
"migrate",
|
|
"runtime-tokio",
|
|
"sqlite",
|
|
"tls-rustls",
|
|
] }
|
|
strum_macros = "0.27.0"
|
|
symphonia = { version = "0.5", features = ["all", "opt-simd"] }
|
|
text-splitter = "0.27"
|
|
thiserror = "2"
|
|
tiktoken-rs = "0.7"
|
|
tokio = "1.45"
|
|
tree-sitter = { version = "0.25" }
|
|
tree-sitter-c = { version = "0.24" }
|
|
tree-sitter-c-sharp = { version = "0.23" }
|
|
tree-sitter-cpp = { version = "0.23" }
|
|
tree-sitter-go = { version = "0.23" }
|
|
tree-sitter-java = { version = "0.23" }
|
|
tree-sitter-javascript = { version = "0.23" }
|
|
tree-sitter-kotlin-ng = { version = "1.1" }
|
|
tree-sitter-python = { version = "0.23" }
|
|
tree-sitter-rust = { version = "0.24" }
|
|
tree-sitter-scala = { version = "0.24" }
|
|
tree-sitter-typescript = { version = "0.23" }
|
|
uniffi = "0.29"
|
|
url = { version = "2.5" }
|
|
uuid = "1.8"
|
|
v_htmlescape = "0.15"
|
|
windows = { version = "0.61", features = [
|
|
"Win32_Devices_FunctionDiscovery",
|
|
"Win32_Foundation",
|
|
"Win32_Media_Audio",
|
|
"Win32_System_Com",
|
|
"Win32_System_Com_StructuredStorage",
|
|
"Win32_System_Diagnostics_ToolHelp",
|
|
"Win32_System_ProcessStatus",
|
|
"Win32_System_Threading",
|
|
"Win32_System_Variant",
|
|
"Win32_UI_Shell_PropertiesSystem",
|
|
] }
|
|
windows-core = { version = "0.61" }
|
|
y-octo = { path = "./packages/common/y-octo/core" }
|
|
y-sync = { version = "0.4" }
|
|
yrs = "0.23.0"
|
|
|
|
[profile.dev.package.sqlx-macros]
|
|
opt-level = 3
|
|
|
|
[profile.release]
|
|
codegen-units = 1
|
|
lto = true
|
|
opt-level = 3
|
|
strip = "symbols"
|
|
|
|
# android uniffi bindgen requires symbols
|
|
[profile.release.package.affine_mobile_native]
|
|
strip = "none"
|