64 Commits

Author SHA1 Message Date
wangdl
c1bac717fd docs: add UniFFI UDL spec + codegen guide (DOC-FULL-030)
- UDL syntax: namespace, functions, dictionary, enum, error
- Type mapping table: UDL→Rust→Swift
- New type checklist: Rust→UDL→codegen→verify
- Common pitfalls: type exports, naming, version compatibility
- Current interface stats: 28 functions, 10 records, 7 enums

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 14:41:44 +08:00
wangdl
a7b941bd42 docs: add file format support matrix (DOC-FULL-028)
- 9 MaterialType × 8 capabilities matrix
- MIME detection strategy (magic bytes → extension)
- Per-format details: Markdown/Text/PDF/EPUB/Image/Office
- PreviewMode mapping, search capabilities, limits

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 14:38:00 +08:00
wangdl
8968858211 docs: add iOS FFI integration guide (DOC-FULL-027)
- Architecture: Swift→uniffi C-ABI→Rust FFI→core
- Type mapping: Rust struct/enum ↔ Swift Record/Enum
- Core API reference: document parsing, search, anchors, V2 sessions
- Error handling, thread safety, performance recommendations

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 14:34:59 +08:00
wangdl
ce30798f51 test: fill DOC coverage gaps - epub path fallback + PDF error handling
- epub: full-path chapter_id, .html suffix, bare ID→OEBPS fallback (3)
- pdf: garbage file, empty file, truncated PDF metadata (3)
- pdf: garbage file text extraction returns empty (1)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:47:46 +08:00
wangdl
d7605774f6 test: add validate_search_result boundary tests (DOC-FULL-025)
- 10 new boundary tests: empty snippet, match at end, start>end,
  exact bounds, query longer than snippet, unicode snippet,
  zero-length match, match_end==snippet_len, query mismatch
- Total 14 validate_search_result tests + 28 other search tests

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:37:14 +08:00
wangdl
7d82a5676c test: add extract_epub_chapter_texts + strip_html unit tests (DOC-FULL-024)
- 7 strip_html tests: remove tags, collapse whitespace, nested tags,
  self-closing tags, attributes, empty input, plain text
- 4 extract_epub_chapter_texts tests: chapters with HTML, empty chapter
  filtered, all empty, plain text preserved
- epub_with_chapter_text helper builds EPUB with custom chapter content

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:35:03 +08:00
wangdl
7570717ec8 test: add extract_pdf_text unit tests (DOC-FULL-023)
- pdf_with_text_stream helper: build minimal PDFs with BT/ET text
- single/multiple text blocks, no BT/ET→empty, empty PDF→empty
- MAX_SCAN_BYTES limit respected, empty text filtered
- page_count from pages dict, default to 1

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:32:34 +08:00
wangdl
1c93308e8b test: add full MaterialType coverage for DocumentInfo (DOC-FULL-022)
- Add 9 new tests: Text, Pdf, Image, Epub, Excel, PowerPoint,
  all_stats_start_none, file_size, material_type_matches
- Total 12 tests covering all 9 MaterialType variants
- Capabilities (is_searchable, supports_position, supports_anchor)
  + preview_mode verified per type

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:29:45 +08:00
wangdl
c957bf2882 feat: Document Runtime 核心增强 - anchors、文档解析、搜索
- anchors: 锚点处理增强
- document: 文档核心逻辑
- epub/markdown/pdf: 多格式解析增强
- search: 全文搜索增强
- FFI: 接口绑定更新 + UDL 定义

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:22:44 +08:00
wangdl
c51e116c7e fix: cleanup_stale_sessions_v2 also removes orphaned trackers
Review finding #4: trackers without a corresponding session (e.g., after
lock poisoning during remove) are now cleaned up during stale sweep.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:34:06 +08:00
wangdl
8ab767ee4a fix: close_reading_session_v2 takes timestamp, sets closed_at_ms
Review finding #3: close now accepts timestamp_ms and sets closed_at_ms
automatically, removing the need for a separate set_session_closed_at_ms call.
set_session_closed_at_ms retained for override use cases.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:33:42 +08:00
wangdl
1a0095cd58 fix: mark_events_failed_v2 idempotent for already-Failed events
Review finding #2: duplicate mark_failed calls double-counted retry_count.
Now skips events already in Failed state. Added test_mark_failed_idempotent.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:31:45 +08:00
wangdl
ce0315d9ae fix: architecture doc - ReadingMaterialRef → ReadingMaterialRefV2
Review finding #1: section 3.3 still referenced old V1 type name.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:31:20 +08:00
wangdl
4c9ac7cb9f docs: V1→V2 compatibility layer (DOC-FULL-034)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:20:28 +08:00
wangdl
254907194c docs: iOS ReadingEvent V2 integration example (DOC-FULL-008)
Swift pseudocode showing full V2 event pipeline:
openSession → heartbeat → position → markedAsRead → closeSession
→ export → local queue → ack → error handling → crash recovery

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:19:42 +08:00
wangdl
b02efe18c7 feat: FFI DTO V2 completion - add EventBufferStateV2 (DOC-FULL-007)
- 新增 EventBufferStateV2 结构体 (total/pending/exported/failed)
- 新增 get_event_buffer_state_v2() 方法
- FFI 导出 EventBufferStateV2 类型 + 方法
- FFI V2 exports 审计: 6 DTO + 9 方法全部到位
- V1 保留 deprecated,V2 接口显式带 V2 后缀

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:13:56 +08:00
wangdl
6250dacd71 docs: update V2 architecture to reflect DOC-FULL-001~006 changes
- ReadingMaterialRef → ReadingMaterialRefV2 (full fields, camelCase)
- ReadingSessionV2: add closed_at_ms, Interrupted/Failed statuses
- EventBuffer: add reload_stale_events_v2, buffer_size_v2
- V1/V2 diff table: add session status/recovery rows
- Verification chain: add startup recovery + V2 MaterialRef

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:10:58 +08:00
wangdl
e64f96d43c feat: ReadingEvent V2 delta semantics verification (DOC-FULL-003)
- 新增 test_delta_semantics_per_event_type: 验证所有 5 种事件类型的
  activeSecondsDelta 均为增量语义(非累计值)
- ReadingEventV2 + ReadingEventTypeV2 已有完整实现(610行/22测试)
- No readingTargetType/userId/knowledgeBaseId(编译时保证)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:05:17 +08:00
wangdl
7d678b4bb3 feat: ReadingSession V2 complete (DOC-FULL-002)
- 新增 ReadingSessionStatus::Interrupted / Failed
- ReadingSessionV2 增加 closedAtMs 字段
- 新增 mark_session_interrupted_v2 / mark_session_failed_v2
- 新增 get_active_session_v2 (按 materialId 查 active session)
- 新增 set_session_closed_at_ms (独立设置关闭时间)
- FFI 暴露 6 个新接口
- SessionError 补充 AlreadyInterrupted / AlreadyFailed
- 167 tests passed / 0 failed

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:03:19 +08:00
wangdl
d1c6edd57a feat: ReadingMaterialRef V2 (DOC-FULL-001)
- 新增 ReadingMaterialRefV2: materialId/filePath/fileName/fileType
  (camelCase) + mimeType/fileSize/contentHash/createdAtMs (可选)
- V1 ReadingMaterialRef 标记 deprecated,保留向后兼容
- session_v2 迁移到 V2 类型
- FFI 层暴露 V2 类型,start_reading_session_v2 接收 V2
- 明确禁止字段: readingTargetType/userId/knowledgeBaseId
- 160 tests passed / 0 failed

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 20:59:43 +08:00
wangdl
c67dbe3e3d fix: add reload_stale_events_v2 FFI export + update UDL with V2 types + XCFramework rebuild
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 19:58:07 +08:00
wangdl
f463c63e03 fix: DOC-FULL V1 export deprecated 2026-06-07 20:33:53 +08:00
wangdl
6cdf88df35 feat: DOC-FULL #63 #64 #70 DocumentInfo + Position restore
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 20:31:59 +08:00
wangdl
c2c40ef1b3 fix: DOC-FULL #57 #60 iOS doc + xtask verify-ios
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 20:26:48 +08:00
wangdl
e08056eccd feat: DOC-FULL Batch 1 FFI + Compat
#56 FFI DTO V2 exports (done in A1)
#83 V1 deprecated annotations
#84 V2→API protocol mapping doc

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 20:26:05 +08:00
wangdl
2978fd4de9 fix: DOC-FULL A1-A8 审查修复
A1: FFI 导出 V2 函数 (start/pause/resume/close/push/export/ack/mark)
A2: ActiveTimeTracker 集成到 session_v2
A3: push_event 调用 position.normalized()
A4: remove_session 检查 Closed 状态
A5: Buffer 溢出驱逐 if-let 链修正
A8: reload_stale_events_v2() 启动恢复

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 20:16:39 +08:00
wangdl
994017e21f feat: DOC-FULL-006 EventBuffer ack/failed/state
BufferedReadingEventV2{event, state: Pending|Exported|Failed, retry_count}
export_pending_events_v2(limit, ts) - marks as Exported
ack_events_v2(eventIds) - removes by eventId
mark_events_failed_v2(eventIds) - for retry
Overflow: Failed→Exported→oldest eviction

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:54:34 +08:00
wangdl
b9251174ee fix: DOC-FULL-005 ReadingPosition camelCase + clamp
Manual Serialize for camelCase JSON output
Clamp progress 0~1 (NaN→0, <0→0, >1→1)
normalized() + progress_value() methods
Backward-compatible Deserialize with #[serde(rename)]

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:49:49 +08:00
wangdl
80774ca927 feat: DOC-FULL-004 ActiveTimeTracker
iOS控制tick节奏,Rust计算delta。start/pause/resume/tick/close。
毫秒余数累计。时间倒退不产生负数。8单元测试。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:41:09 +08:00
wangdl
dcf148ebc6 feat: DOC-FULL-003 ReadingEventV2
5 types: MaterialOpened/Closed/PositionChanged/Heartbeat/MarkedAsRead
active_seconds_delta (增量)
集成 ReadingSessionV2 (clientSessionId/sequence/materialId)
10 单元测试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:37:19 +08:00
wangdl
1d71e2b02a feat: DOC-FULL-002 ReadingSessionV2
- clientSessionId UUID 生成
- start/pause/resume/close lifecycle
- sequence 递增
- record_session_event_v2 更新时长和位置
- 7 个单元测试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:34:12 +08:00
wangdl
ff7f681cd4 feat: DOC-FULL-001 ReadingMaterialRef
Rust 只保存 materialId,不区分 KnowledgeSource/TemporaryFile。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:26:48 +08:00
wangdl
4c5a725305 feat: DOC-FULL-000 完整架构文档 v2
7 设计决策、V2 核心模型、V1→V2 迁移、API 协议映射、项目结构、验收链路

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 19:23:56 +08:00
wangdl
48101e7bad fix: RagChatModule 导入 AiModule,修复 AiGatewayService 未注入
AiGatewayService 使用了 @Optional() 导致不报错但始终为 null,
sendMessage 永远走 fallbackReply。现在导入 AiModule 正确注入。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 13:38:57 +08:00
wangdl
f4336ba05f fix: #44 events.rs Mutex poison 时恢复而非静默丢事件
push_reading_event 改用 match 替代 if let,poison 时通过 into_inner 恢复缓冲区。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 13:00:37 +08:00
wangdl
3acf7d464f fix: #41 detect_material_type 只读前 8KB 做魔数检测
std::fs::read 整个文件 → File::open + read 前 8192 字节,节省大文件内存。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:59:19 +08:00
wangdl
475532cdd9 fix: #48 markdown.rs 处理 FrontMatter 和 FootnoteDefinition 节点
FrontMatter → CodeBlock(language=yaml)
FootnoteDefinition → Paragraph

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:56:45 +08:00
wangdl
0ad7734d2d fix: #39 from_bytes_separate 检查 RustCallStatus 返回值
分配失败时将 out 参数置零并 return,避免返回未初始化栈垃圾。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:55:37 +08:00
wangdl
89ff71aeb8 fix: #38 EVENT_BUFFER 增加 MAX_BUFFER_SIZE=1000 上限
push_reading_event 时超出上限自动丢弃最旧事件,防止未导出事件堆积导致 OOM。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:55:00 +08:00
wangdl
794b0f91b3 feat: #37 Batch2+3 — 全部函数迁移到 out-pointer FFI
新增 8 个 _separate 函数:
- push_reading_event_separate
- update_reading_position_separate
- export_pending_events_separate
- create_note_anchor_separate
- search_markdown_blocks_separate
- search_text_content_separate

新增 lift_from_raw! 宏用于从原始 buffer 参数反序列化复杂类型。
原 #[uniffi::export] 函数保留(macOS/Android 路径可用)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:51:50 +08:00
wangdl
2aeb72f1e3 feat: #37 Batch1 — detect_material_type/read_image_meta/read_text_stats/parse_text out-pointer FFI
新增 4 个 _separate 函数绕过 RustBuffer struct-passing:
- ffi_zx_document_ffi_detect_material_type_separate
- ffi_zx_document_ffi_read_image_meta_separate
- ffi_zx_document_ffi_read_text_stats_separate
- ffi_zx_document_ffi_parse_text_separate

提取 write_result_to_out! 宏和 read_str_input helper 减少样板代码。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:45:56 +08:00
wangdl
08f5f0559b fix: #47 移除所有调试 eprintln! 日志
清理 FFI 调试期间在 lib.rs 和 markdown.rs 中添加的 16 行 eprintln!
调试日志,spam iOS 控制台。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 12:40:48 +08:00
wangdl
942ac06230 feat: M3 completion — event buffer, FFI search/anchor, PDF strategy, quality fixes
Rust Core:
- events: global Mutex-buffered event queue (push/export/clear/update_position)
- image_meta: use ImageReader::format() for real decoded format instead of extension
- search: change match_start/match_end usize→u64 for FFI compatibility
- epub/pdf: module-level placeholder comments

FFI (UDL exposed, 12 total functions):
- Added: search_markdown_blocks, search_text_content, create_note_anchor
- Added: push_reading_event, update_reading_position, export_pending_events,
  clear_exported_events

Docs:
- README: synced DocumentBlock model (Table.headers + HorizontalRule),
  simplified dependency recommendations, removed nonexistent doc references
- docs/pdf-strategy.md: PDFKit vs PDFium vs MuPDF evaluation, 5 decisions,
  platform strategy matrix, roadmap

Build:
- .cargo/config.toml: cargo xtask alias
- xtask: CLI implementation (test/build-ios/fixtures commands)
- fixtures: markdown/sample.md (9 block types), text/sample.txt
- XCFramework rebuilt, Swift bindings regenerated (1977 lines)

58 tests pass, zero warnings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 21:23:26 +08:00
wangdl
87814802b1 feat: expose parse_text via FFI - returns paragraph blocks from TXT 2026-06-02 19:55:03 +08:00
wangdl
7b827ca01a feat: expose parse_markdown via FFI - returns [DocumentBlock] with all 8 block types 2026-06-02 19:53:42 +08:00
wangdl
4c8a50daec feat: expose 3 FFI functions via UDL - detect_material_type, read_image_meta, read_text_stats 2026-06-02 19:45:54 +08:00
wangdl
e1e1f27b07 feat: iOS integration docs + demo app skeleton 2026-06-02 19:33:45 +08:00
wangdl
dba2276b6e feat: iOS XCFramework build - device + simulator static libs 2026-06-01 20:09:29 +08:00
wangdl
ddcc5b392c feat: generated Swift bindings from UDL (48KB) 2026-05-30 22:13:22 +08:00
wangdl
9481cc20e9 feat: UniFFI setup - UDL interface, build.rs scaffolding, cargo check passes 2026-05-30 22:11:27 +08:00