deeptutor-knowledge 1.7.0__py3-none-any.whl

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 (168) hide show
  1. deeptutor/api/routers/knowledge.py +5225 -0
  2. deeptutor/api/routers/marginnote4.py +278 -0
  3. deeptutor/capabilities/ima/__init__.py +6 -0
  4. deeptutor/capabilities/ima/binding.py +118 -0
  5. deeptutor/capabilities/ima/capability.py +92 -0
  6. deeptutor/capabilities/ima/prompts/en/system.md +33 -0
  7. deeptutor/capabilities/ima/prompts/zh/system.md +24 -0
  8. deeptutor/capabilities/ima/tools.py +476 -0
  9. deeptutor/capabilities/marginnote4/__init__.py +13 -0
  10. deeptutor/capabilities/marginnote4/binding.py +66 -0
  11. deeptutor/capabilities/marginnote4/capability.py +80 -0
  12. deeptutor/capabilities/marginnote4/models.py +173 -0
  13. deeptutor/capabilities/marginnote4/prompts/en/system.md +54 -0
  14. deeptutor/capabilities/marginnote4/prompts/zh/system.md +44 -0
  15. deeptutor/capabilities/marginnote4/store.py +562 -0
  16. deeptutor/capabilities/marginnote4/tools.py +329 -0
  17. deeptutor/capabilities/obsidian/__init__.py +6 -0
  18. deeptutor/capabilities/obsidian/binding.py +75 -0
  19. deeptutor/capabilities/obsidian/capability.py +82 -0
  20. deeptutor/capabilities/obsidian/prompts/en/system.md +32 -0
  21. deeptutor/capabilities/obsidian/prompts/zh/system.md +28 -0
  22. deeptutor/capabilities/obsidian/tools.py +399 -0
  23. deeptutor/capabilities/obsidian/vault.py +341 -0
  24. deeptutor/knowledge/__init__.py +28 -0
  25. deeptutor/knowledge/add_documents.py +734 -0
  26. deeptutor/knowledge/indexing_run.py +432 -0
  27. deeptutor/knowledge/initializer.py +448 -0
  28. deeptutor/knowledge/manager.py +2570 -0
  29. deeptutor/knowledge/module_service.py +29 -0
  30. deeptutor/knowledge/naming.py +40 -0
  31. deeptutor/knowledge/progress_events.py +45 -0
  32. deeptutor/knowledge/progress_tracker.py +355 -0
  33. deeptutor/knowledge/staging.py +69 -0
  34. deeptutor/services/config/knowledge_base_config.py +239 -0
  35. deeptutor/services/embedding/__init__.py +46 -0
  36. deeptutor/services/embedding/adapters/__init__.py +40 -0
  37. deeptutor/services/embedding/adapters/base.py +196 -0
  38. deeptutor/services/embedding/adapters/cohere.py +176 -0
  39. deeptutor/services/embedding/adapters/dashscope_native.py +242 -0
  40. deeptutor/services/embedding/adapters/gemini.py +462 -0
  41. deeptutor/services/embedding/adapters/jina.py +161 -0
  42. deeptutor/services/embedding/adapters/ollama.py +145 -0
  43. deeptutor/services/embedding/adapters/openai_compatible.py +406 -0
  44. deeptutor/services/embedding/adapters/openai_sdk.py +150 -0
  45. deeptutor/services/embedding/client.py +323 -0
  46. deeptutor/services/embedding/config.py +114 -0
  47. deeptutor/services/embedding/request_options.py +46 -0
  48. deeptutor/services/embedding/validation.py +128 -0
  49. deeptutor/services/github_source/__init__.py +5 -0
  50. deeptutor/services/github_source/client.py +164 -0
  51. deeptutor/services/github_source/sync.py +384 -0
  52. deeptutor/services/github_source/sync_service.py +72 -0
  53. deeptutor/services/rag/__init__.py +21 -0
  54. deeptutor/services/rag/embedding_binding.py +331 -0
  55. deeptutor/services/rag/embedding_signature.py +63 -0
  56. deeptutor/services/rag/eval/__init__.py +92 -0
  57. deeptutor/services/rag/eval/dataset.py +244 -0
  58. deeptutor/services/rag/eval/diff.py +312 -0
  59. deeptutor/services/rag/eval/matching.py +218 -0
  60. deeptutor/services/rag/eval/metrics.py +213 -0
  61. deeptutor/services/rag/eval/report.py +111 -0
  62. deeptutor/services/rag/eval/runner.py +309 -0
  63. deeptutor/services/rag/factory.py +369 -0
  64. deeptutor/services/rag/file_routing.py +5 -0
  65. deeptutor/services/rag/index_probe.py +327 -0
  66. deeptutor/services/rag/index_versioning.py +387 -0
  67. deeptutor/services/rag/kb_paths.py +50 -0
  68. deeptutor/services/rag/linked_kb.py +237 -0
  69. deeptutor/services/rag/pipelines/__init__.py +7 -0
  70. deeptutor/services/rag/pipelines/base.py +41 -0
  71. deeptutor/services/rag/pipelines/graphrag/__init__.py +18 -0
  72. deeptutor/services/rag/pipelines/graphrag/compatibility.py +42 -0
  73. deeptutor/services/rag/pipelines/graphrag/completion_adapter.py +251 -0
  74. deeptutor/services/rag/pipelines/graphrag/config.py +357 -0
  75. deeptutor/services/rag/pipelines/graphrag/engine.py +479 -0
  76. deeptutor/services/rag/pipelines/graphrag/errors.py +328 -0
  77. deeptutor/services/rag/pipelines/graphrag/ingestion.py +135 -0
  78. deeptutor/services/rag/pipelines/graphrag/pandas_compat.py +68 -0
  79. deeptutor/services/rag/pipelines/graphrag/pipeline.py +284 -0
  80. deeptutor/services/rag/pipelines/graphrag/provider.py +134 -0
  81. deeptutor/services/rag/pipelines/graphrag/storage.py +127 -0
  82. deeptutor/services/rag/pipelines/ima/__init__.py +28 -0
  83. deeptutor/services/rag/pipelines/ima/client.py +364 -0
  84. deeptutor/services/rag/pipelines/ima/config.py +140 -0
  85. deeptutor/services/rag/pipelines/ima/envelope.py +109 -0
  86. deeptutor/services/rag/pipelines/ima/inventory.py +209 -0
  87. deeptutor/services/rag/pipelines/ima/media.py +190 -0
  88. deeptutor/services/rag/pipelines/ima/models.py +348 -0
  89. deeptutor/services/rag/pipelines/ima/notes.py +240 -0
  90. deeptutor/services/rag/pipelines/ima/pipeline.py +238 -0
  91. deeptutor/services/rag/pipelines/ima/probe.py +105 -0
  92. deeptutor/services/rag/pipelines/ima/sources.py +105 -0
  93. deeptutor/services/rag/pipelines/ima/transport.py +130 -0
  94. deeptutor/services/rag/pipelines/kiwix/__init__.py +1 -0
  95. deeptutor/services/rag/pipelines/kiwix/client.py +369 -0
  96. deeptutor/services/rag/pipelines/kiwix/pipeline.py +75 -0
  97. deeptutor/services/rag/pipelines/lightrag/README.md +78 -0
  98. deeptutor/services/rag/pipelines/lightrag/__init__.py +15 -0
  99. deeptutor/services/rag/pipelines/lightrag/block_policy.py +266 -0
  100. deeptutor/services/rag/pipelines/lightrag/cache_reuse.py +137 -0
  101. deeptutor/services/rag/pipelines/lightrag/config.py +453 -0
  102. deeptutor/services/rag/pipelines/lightrag/engine.py +536 -0
  103. deeptutor/services/rag/pipelines/lightrag/indexing_policy.py +696 -0
  104. deeptutor/services/rag/pipelines/lightrag/ingress.py +364 -0
  105. deeptutor/services/rag/pipelines/lightrag/parser.py +99 -0
  106. deeptutor/services/rag/pipelines/lightrag/pipeline.py +692 -0
  107. deeptutor/services/rag/pipelines/lightrag/roles.py +132 -0
  108. deeptutor/services/rag/pipelines/lightrag/sidecar.py +320 -0
  109. deeptutor/services/rag/pipelines/lightrag/storage.py +338 -0
  110. deeptutor/services/rag/pipelines/lightrag/worker.py +259 -0
  111. deeptutor/services/rag/pipelines/lightrag/write_lock.py +55 -0
  112. deeptutor/services/rag/pipelines/lightrag_server/__init__.py +15 -0
  113. deeptutor/services/rag/pipelines/lightrag_server/client.py +149 -0
  114. deeptutor/services/rag/pipelines/lightrag_server/config.py +68 -0
  115. deeptutor/services/rag/pipelines/lightrag_server/pipeline.py +120 -0
  116. deeptutor/services/rag/pipelines/lightrag_server/probe.py +110 -0
  117. deeptutor/services/rag/pipelines/llamaindex/__init__.py +3 -0
  118. deeptutor/services/rag/pipelines/llamaindex/config.py +199 -0
  119. deeptutor/services/rag/pipelines/llamaindex/document_loader.py +648 -0
  120. deeptutor/services/rag/pipelines/llamaindex/embedding_adapter.py +264 -0
  121. deeptutor/services/rag/pipelines/llamaindex/errors.py +76 -0
  122. deeptutor/services/rag/pipelines/llamaindex/exercise_lookup.py +373 -0
  123. deeptutor/services/rag/pipelines/llamaindex/ingestion.py +129 -0
  124. deeptutor/services/rag/pipelines/llamaindex/pipeline.py +556 -0
  125. deeptutor/services/rag/pipelines/llamaindex/rerank.py +130 -0
  126. deeptutor/services/rag/pipelines/llamaindex/retrievers.py +360 -0
  127. deeptutor/services/rag/pipelines/llamaindex/storage.py +655 -0
  128. deeptutor/services/rag/pipelines/llamaindex/vector_store.py +288 -0
  129. deeptutor/services/rag/pipelines/modes.py +48 -0
  130. deeptutor/services/rag/pipelines/pageindex/__init__.py +47 -0
  131. deeptutor/services/rag/pipelines/pageindex/client.py +146 -0
  132. deeptutor/services/rag/pipelines/pageindex/config.py +49 -0
  133. deeptutor/services/rag/pipelines/pageindex/pipeline.py +313 -0
  134. deeptutor/services/rag/pipelines/pageindex/reasoning.py +262 -0
  135. deeptutor/services/rag/pipelines/pageindex/storage.py +133 -0
  136. deeptutor/services/rag/pipelines/pageindex/tools.py +221 -0
  137. deeptutor/services/rag/pipelines/weknora/__init__.py +13 -0
  138. deeptutor/services/rag/pipelines/weknora/client.py +106 -0
  139. deeptutor/services/rag/pipelines/weknora/config.py +56 -0
  140. deeptutor/services/rag/pipelines/weknora/pipeline.py +74 -0
  141. deeptutor/services/rag/pipelines/weknora/probe.py +80 -0
  142. deeptutor/services/rag/preflight.py +274 -0
  143. deeptutor/services/rag/provider_binding.py +70 -0
  144. deeptutor/services/rag/query_rewrite.py +186 -0
  145. deeptutor/services/rag/service.py +379 -0
  146. deeptutor/services/rag/smart_retriever.py +81 -0
  147. deeptutor/services/rag/source_pages.py +292 -0
  148. deeptutor/services/rag/source_visuals.py +434 -0
  149. deeptutor/services/rag/visual_assets.py +430 -0
  150. deeptutor/services/rag/visual_coverage.py +165 -0
  151. deeptutor/services/web_source/__init__.py +1 -0
  152. deeptutor/services/web_source/bilingual.py +255 -0
  153. deeptutor/services/web_source/crawler.py +681 -0
  154. deeptutor/services/web_source/html_extractor.py +643 -0
  155. deeptutor/services/web_source/markdown.py +28 -0
  156. deeptutor/services/web_source/navigation.py +72 -0
  157. deeptutor/services/web_source/repository.py +640 -0
  158. deeptutor/services/web_source/robots.py +182 -0
  159. deeptutor/services/web_source/scheduler.py +336 -0
  160. deeptutor/services/web_source/snapshot_assets.py +171 -0
  161. deeptutor/services/web_source/sync.py +253 -0
  162. deeptutor/services/workspace/kb_move.py +446 -0
  163. deeptutor/tools/rag_tool.py +110 -0
  164. deeptutor_cli/kb.py +756 -0
  165. deeptutor_knowledge-1.7.0.dist-info/METADATA +15 -0
  166. deeptutor_knowledge-1.7.0.dist-info/RECORD +168 -0
  167. deeptutor_knowledge-1.7.0.dist-info/WHEEL +5 -0
  168. deeptutor_knowledge-1.7.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,173 @@
1
+ """Core data models for the MarginNote 4 bridge.
2
+
3
+ These types describe MN4 objects as they land in DeepTutor after sync.
4
+ The MN4 Add-on serialises its native objects (notes, excerpts, cards, mindmap
5
+ nodes, documents) into :class:`MarginNoteObject` rows that the sync store
6
+ indexes and the capability tools query.
7
+
8
+ Design notes
9
+ ------------
10
+ * Every object carries a stable ``object_id`` derived from MN4's internal ID,
11
+ so re-syncs update in place instead of creating duplicates.
12
+ * Text fields (``title``, ``excerpt``, ``content``) are plain strings — no
13
+ HTML or MN4 markup. The Add-on is responsible for flattening rich text.
14
+ * ``raw`` preserves the original MN4 JSON for fields DeepTutor does not model
15
+ yet, so the schema can grow without re-syncing.
16
+ * ``device_id`` ties each object to the paired device that synced it, so a
17
+ user with multiple devices can tell which copy is authoritative.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from dataclasses import asdict, dataclass, field
23
+ from typing import Any
24
+
25
+ # --------------------------------------------------------------------------- #
26
+ # Object types — what kind of MN4 entity a row represents.
27
+ # --------------------------------------------------------------------------- #
28
+
29
+ NOTE = "note" # A highlight, underline, or text selection annotation.
30
+ EXCERPT = "excerpt" # An excerpt block (longer quoted passage).
31
+ CARD = "card" # A flashcard with front/back.
32
+ MINDMAP_NODE = "mindmap_node" # A node in the study mindmap.
33
+ DOCUMENT = "document" # A source document (PDF, EPUB, web).
34
+ COMMENT = "comment" # A free-form comment attached to a note or node.
35
+
36
+ ALL_TYPES: frozenset[str] = frozenset({NOTE, EXCERPT, CARD, MINDMAP_NODE, DOCUMENT, COMMENT})
37
+
38
+
39
+ @dataclass(slots=True)
40
+ class MarginNoteObject:
41
+ """One synced MarginNote 4 entity.
42
+
43
+ Attributes:
44
+ object_id: Stable ID from MN4 (its internal ``noteId`` / ``nodeId``).
45
+ object_type: One of :data:`ALL_TYPES`.
46
+ title: Display title (note title, card title, node text, doc title).
47
+ content: Primary text body. For a card this is the front; for an
48
+ annotation it is the excerpt text; for a mindmap node it is the
49
+ node's text content.
50
+ excerpt: Quoted source text (the highlighted passage), when the object
51
+ is anchored to a document. ``None`` for cards without a source.
52
+ document_id: ID of the source document, when the object belongs to one.
53
+ document_title: Human-readable title of the source document.
54
+ page: Page number in the source document, when known.
55
+ tags: User-assigned tags.
56
+ links: IDs of linked MN4 objects (parent/child in mindmap,
57
+ linked cards, etc.).
58
+ color: MN4 highlight colour label, when applicable.
59
+ created_at: ISO-8601 timestamp from MN4.
60
+ updated_at: ISO-8601 timestamp from MN4 (last modification).
61
+ synced_at: ISO-8601 timestamp when DeepTutor received this version.
62
+ device_id: The paired device that synced this object.
63
+ raw: Original MN4 JSON payload, preserved verbatim for forward compat.
64
+ """
65
+
66
+ object_id: str
67
+ object_type: str
68
+ title: str = ""
69
+ content: str = ""
70
+ excerpt: str | None = None
71
+ document_id: str | None = None
72
+ document_title: str | None = None
73
+ page: int | None = None
74
+ tags: list[str] = field(default_factory=list)
75
+ links: list[str] = field(default_factory=list)
76
+ color: str | None = None
77
+ created_at: str = ""
78
+ updated_at: str = ""
79
+ synced_at: str = ""
80
+ device_id: str = ""
81
+ raw: dict[str, Any] = field(default_factory=dict)
82
+
83
+ def to_dict(self) -> dict[str, Any]:
84
+ """Serialise to a plain dict for JSON responses and storage."""
85
+ return asdict(self)
86
+
87
+
88
+ @dataclass(slots=True)
89
+ class SyncBatch:
90
+ """A batch of objects pushed by a device during incremental sync.
91
+
92
+ Attributes:
93
+ device_id: The paired device pushing this batch.
94
+ cursor: Monotonic sync position this batch advances from.
95
+ objects: New or updated objects since the previous cursor.
96
+ deleted_ids: IDs tombstoned since the previous cursor.
97
+ """
98
+
99
+ device_id: str
100
+ cursor: str = ""
101
+ objects: list[MarginNoteObject] = field(default_factory=list)
102
+ deleted_ids: list[str] = field(default_factory=list)
103
+
104
+
105
+ @dataclass(slots=True)
106
+ class SyncResult:
107
+ """Outcome of ingesting a :class:`SyncBatch` into the store."""
108
+
109
+ stored: int = 0
110
+ updated: int = 0
111
+ deleted: int = 0
112
+ new_cursor: str = ""
113
+
114
+
115
+ @dataclass(slots=True)
116
+ class PairedDevice:
117
+ """A MarginNote 4 device registered with this DeepTutor instance.
118
+
119
+ Attributes:
120
+ device_id: Stable identifier generated at pairing time.
121
+ device_name: Human-readable label (e.g. "MacBook Pro", "iPad").
122
+ device_kind: ``macos`` or ``ipados``.
123
+ paired_at: ISO-8601 timestamp.
124
+ last_seen: ISO-8601 timestamp of last sync or heartbeat.
125
+ active: Whether the device is currently enabled.
126
+ """
127
+
128
+ device_id: str
129
+ device_name: str = ""
130
+ device_kind: str = "macos"
131
+ paired_at: str = ""
132
+ last_seen: str = ""
133
+ active: bool = True
134
+
135
+
136
+ @dataclass(slots=True)
137
+ class LearningEvent:
138
+ """A study event observed on the MN4 side (Phase 3).
139
+
140
+ Captures a review or study interaction so DeepTutor can track mastery
141
+ without touching MN4's private FSRS scheduling data.
142
+
143
+ Attributes:
144
+ event_id: Unique event identifier.
145
+ object_id: The MN4 object studied (usually a card).
146
+ event_type: ``review``, ``study``, ``flag``, ``confidence``.
147
+ outcome: ``again``, ``hard``, ``good``, ``easy`` (or free text).
148
+ timestamp: ISO-8601.
149
+ device_id: Device that observed the event.
150
+ """
151
+
152
+ event_id: str
153
+ object_id: str
154
+ event_type: str = "review"
155
+ outcome: str = ""
156
+ timestamp: str = ""
157
+ device_id: str = ""
158
+
159
+
160
+ __all__ = [
161
+ "ALL_TYPES",
162
+ "CARD",
163
+ "COMMENT",
164
+ "DOCUMENT",
165
+ "EXCERPT",
166
+ "LearningEvent",
167
+ "MINDMAP_NODE",
168
+ "NOTE",
169
+ "MarginNoteObject",
170
+ "PairedDevice",
171
+ "SyncBatch",
172
+ "SyncResult",
173
+ ]
@@ -0,0 +1,54 @@
1
+ # MarginNote 4 Library
2
+
3
+ You are connected to the user's MarginNote 4 library **{library_name}** -- study
4
+ data synced from MarginNote 4, a reading and study app for PDFs, EPUBs, and web
5
+ articles. The library contains five kinds of objects:
6
+
7
+ - **notes**: highlights and annotations the user made while reading
8
+ - **excerpts**: longer quoted passages from source documents
9
+ - **cards**: flashcards with a front (question) and back (answer)
10
+ - **mindmap_nodes**: nodes in the study mindmap that organize knowledge
11
+ - **documents**: source PDFs, books, and articles the user studies from
12
+
13
+ Every object may link to related objects (a note links to its card, a mindmap
14
+ node links to its children). Follow these links to surface connections a flat
15
+ search would miss.
16
+
17
+ This turn you work *only* with the MarginNote tools; there is no web, code, or
18
+ other knowledge base. The synced library is the source of truth.
19
+
20
+ ## Retrieving (answering from the library)
21
+
22
+ Don't guess -- explore. A typical path:
23
+
24
+ 1. `marginnote_search` for the topic, or `marginnote_tags` /
25
+ `marginnote_documents` to map the library when you lack a search term.
26
+ 2. `marginnote_read` the promising objects for full content.
27
+ 3. Follow the graph: `marginnote_links` surfaces related notes and cards a
28
+ keyword search misses.
29
+ 4. Answer grounded in what you read, citing document titles and page numbers.
30
+ If the library doesn't cover it, say so rather than inventing.
31
+
32
+ ## Tips for good answers
33
+
34
+ - When you find a relevant note, check `marginnote_links` to discover the card
35
+ it generated and the mindmap node it belongs to -- this gives the full study
36
+ context.
37
+ - If the user asks "what do I know about X", search for X, then read the top
38
+ results and summarize the connections between them.
39
+ - If the user wants to review, use `marginnote_cards` to pull flashcards and
40
+ walk through them interactively.
41
+ - Page numbers and document titles are your citation anchors -- always include
42
+ them so the user can find the source in MarginNote 4.
43
+
44
+ ## Study material
45
+
46
+ - `marginnote_cards` lists flashcards. When the user wants to review or study,
47
+ pull the relevant cards and walk through them one by one.
48
+ - `marginnote_list` with `object_type=mindmap_node` shows the mindmap structure
49
+ -- useful for understanding how the user organizes their knowledge.
50
+
51
+ ## Writing (Phase 2 -- not yet available)
52
+
53
+ Writing back to MarginNote 4 is not available yet. If the user asks to create or
54
+ modify notes in MN4, suggest they do it directly in the app for now.
@@ -0,0 +1,44 @@
1
+ # MarginNote 4 学习库
2
+
3
+ 你已连接到用户的 MarginNote 4 学习库 **{library_name}** -- 这是从 MarginNote 4
4
+ (一款用于 PDF、EPUB 和网页文章的阅读与学习应用)同步的学习数据。学习库包含五种对象:
5
+
6
+ - **note(笔记)**:用户阅读时做的高亮和批注
7
+ - **excerpt(摘录)**:从源文档中摘录的较长段落
8
+ - **card(卡片)**:带有正面(问题)和背面(答案)的抽认卡
9
+ - **mindmap_node(思维导图节点)**:学习思维导图中组织知识的节点
10
+ - **document(文档)**:用户学习的源 PDF、书籍和文章
11
+
12
+ 每个对象都可能链接到相关对象(一条笔记链接到它生成的卡片,一个思维导图节点链接到其子节点)。
13
+ 追踪这些链接,发现扁平搜索会遗漏的知识关联。
14
+
15
+ 本轮你*只*使用 MarginNote 工具;没有网络搜索、代码或其他知识库。同步的学习库是唯一的数据来源。
16
+
17
+ ## 检索(从学习库中回答)
18
+
19
+ 不要猜测 -- 先探索。典型路径:
20
+
21
+ 1. 用 `marginnote_search` 搜索主题,或在没有搜索词时用 `marginnote_tags` /
22
+ `marginnote_documents` 浏览学习库结构。
23
+ 2. 用 `marginnote_read` 读取感兴趣的对象的完整内容。
24
+ 3. 追踪知识图谱:`marginnote_links` 能发现关键词搜索遗漏的相关笔记和卡片。
25
+ 4. 基于你读到的内容回答,引用文档标题和页码。如果学习库中没有覆盖,如实说明。
26
+
27
+ ## 回答技巧
28
+
29
+ - 找到一条相关笔记后,用 `marginnote_links` 查看它关联的卡片和所属的思维导图节点 -- 这能
30
+ 给出完整的学习上下文。
31
+ - 当用户问"我对 X 了解什么"时,搜索 X,然后读取前几条结果,总结它们之间的联系。
32
+ - 当用户想复习时,用 `marginnote_cards` 调取抽认卡,逐张讲解。
33
+ - 页码和文档标题是你的引用锚点 -- 始终包含它们,让用户能在 MarginNote 4 中找到原文。
34
+
35
+ ## 学习材料
36
+
37
+ - `marginnote_cards` 列出抽认卡。当用户想要复习或学习时,调取相关卡片并逐一讲解。
38
+ - `marginnote_list`(`object_type=mindmap_node`)展示思维导图结构 -- 有助于了解用户如何
39
+ 组织知识。
40
+
41
+ ## 写回(第二阶段 -- 尚未实现)
42
+
43
+ 向 MarginNote 4 写回功能尚未实现。如果用户要求在 MN4 中创建或修改笔记,建议暂时直接在
44
+ 应用中操作。