@agent-native/core 0.79.2 → 0.79.6

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 (268) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +30 -0
  3. package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.md +392 -0
  4. package/corpus/core/docs/content/locales/zh-TW/actions.md +583 -0
  5. package/corpus/core/docs/content/locales/zh-TW/agent-mentions.md +164 -0
  6. package/corpus/core/docs/content/locales/zh-TW/agent-surfaces.md +397 -0
  7. package/corpus/core/docs/content/locales/zh-TW/agent-teams.md +171 -0
  8. package/corpus/core/docs/content/locales/zh-TW/agent-web-surfaces.md +161 -0
  9. package/corpus/core/docs/content/locales/zh-TW/audit-log.md +111 -0
  10. package/corpus/core/docs/content/locales/zh-TW/authentication.md +332 -0
  11. package/corpus/core/docs/content/locales/zh-TW/automations.md +268 -0
  12. package/corpus/core/docs/content/locales/zh-TW/blueprint-installer.md +83 -0
  13. package/corpus/core/docs/content/locales/zh-TW/cli-adapters.md +129 -0
  14. package/corpus/core/docs/content/locales/zh-TW/client.md +398 -0
  15. package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.md +114 -0
  16. package/corpus/core/docs/content/locales/zh-TW/code-agents-ui.md +436 -0
  17. package/corpus/core/docs/content/locales/zh-TW/components.md +368 -0
  18. package/corpus/core/docs/content/locales/zh-TW/context-awareness.md +373 -0
  19. package/corpus/core/docs/content/locales/zh-TW/creating-templates.md +411 -0
  20. package/corpus/core/docs/content/locales/zh-TW/cross-app-sso.md +188 -0
  21. package/corpus/core/docs/content/locales/zh-TW/database.md +183 -0
  22. package/corpus/core/docs/content/locales/zh-TW/deployment.md +348 -0
  23. package/corpus/core/docs/content/locales/zh-TW/dispatch.md +146 -0
  24. package/corpus/core/docs/content/locales/zh-TW/drop-in-agent.md +260 -0
  25. package/corpus/core/docs/content/locales/zh-TW/durable-resume.md +65 -0
  26. package/corpus/core/docs/content/locales/zh-TW/embedding-sdk.md +597 -0
  27. package/corpus/core/docs/content/locales/zh-TW/evals.md +155 -0
  28. package/corpus/core/docs/content/locales/zh-TW/extensions.md +360 -0
  29. package/corpus/core/docs/content/locales/zh-TW/external-agents.md +619 -0
  30. package/corpus/core/docs/content/locales/zh-TW/faq.md +142 -0
  31. package/corpus/core/docs/content/locales/zh-TW/file-uploads.md +122 -0
  32. package/corpus/core/docs/content/locales/zh-TW/frames.md +153 -0
  33. package/corpus/core/docs/content/locales/zh-TW/getting-started.md +199 -0
  34. package/corpus/core/docs/content/locales/zh-TW/harness-agents.md +349 -0
  35. package/corpus/core/docs/content/locales/zh-TW/human-approval.md +86 -0
  36. package/corpus/core/docs/content/locales/zh-TW/internationalization.md +147 -0
  37. package/corpus/core/docs/content/locales/zh-TW/key-concepts.md +312 -0
  38. package/corpus/core/docs/content/locales/zh-TW/local-file-mode.md +433 -0
  39. package/corpus/core/docs/content/locales/zh-TW/mcp-apps.md +147 -0
  40. package/corpus/core/docs/content/locales/zh-TW/mcp-clients.md +330 -0
  41. package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.md +279 -0
  42. package/corpus/core/docs/content/locales/zh-TW/messaging.md +461 -0
  43. package/corpus/core/docs/content/locales/zh-TW/migration-workbench.md +33 -0
  44. package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +312 -0
  45. package/corpus/core/docs/content/locales/zh-TW/multi-tenancy.md +52 -0
  46. package/corpus/core/docs/content/locales/zh-TW/native-chat-ui.md +321 -0
  47. package/corpus/core/docs/content/locales/zh-TW/notifications.md +231 -0
  48. package/corpus/core/docs/content/locales/zh-TW/observability.md +294 -0
  49. package/corpus/core/docs/content/locales/zh-TW/observational-memory.md +77 -0
  50. package/corpus/core/docs/content/locales/zh-TW/onboarding.md +216 -0
  51. package/corpus/core/docs/content/locales/zh-TW/plan-plugin.md +200 -0
  52. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.md +384 -0
  53. package/corpus/core/docs/content/locales/zh-TW/processors.md +106 -0
  54. package/corpus/core/docs/content/locales/zh-TW/progress.md +199 -0
  55. package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.md +39 -0
  56. package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.md +680 -0
  57. package/corpus/core/docs/content/locales/zh-TW/recurring-jobs.md +142 -0
  58. package/corpus/core/docs/content/locales/zh-TW/routing.md +79 -0
  59. package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.md +227 -0
  60. package/corpus/core/docs/content/locales/zh-TW/security.md +330 -0
  61. package/corpus/core/docs/content/locales/zh-TW/server.md +265 -0
  62. package/corpus/core/docs/content/locales/zh-TW/sharing.md +219 -0
  63. package/corpus/core/docs/content/locales/zh-TW/skills-guide.md +281 -0
  64. package/corpus/core/docs/content/locales/zh-TW/template-analytics.md +259 -0
  65. package/corpus/core/docs/content/locales/zh-TW/template-assets.md +303 -0
  66. package/corpus/core/docs/content/locales/zh-TW/template-brain.md +324 -0
  67. package/corpus/core/docs/content/locales/zh-TW/template-calendar.md +194 -0
  68. package/corpus/core/docs/content/locales/zh-TW/template-chat.md +129 -0
  69. package/corpus/core/docs/content/locales/zh-TW/template-clips.md +368 -0
  70. package/corpus/core/docs/content/locales/zh-TW/template-content.md +402 -0
  71. package/corpus/core/docs/content/locales/zh-TW/template-design.md +173 -0
  72. package/corpus/core/docs/content/locales/zh-TW/template-dispatch.md +220 -0
  73. package/corpus/core/docs/content/locales/zh-TW/template-forms.md +178 -0
  74. package/corpus/core/docs/content/locales/zh-TW/template-mail.md +239 -0
  75. package/corpus/core/docs/content/locales/zh-TW/template-plan.md +814 -0
  76. package/corpus/core/docs/content/locales/zh-TW/template-slides.md +293 -0
  77. package/corpus/core/docs/content/locales/zh-TW/template-videos.md +222 -0
  78. package/corpus/core/docs/content/locales/zh-TW/tracking.md +236 -0
  79. package/corpus/core/docs/content/locales/zh-TW/using-your-agent.md +71 -0
  80. package/corpus/core/docs/content/locales/zh-TW/voice-input.md +81 -0
  81. package/corpus/core/docs/content/locales/zh-TW/what-is-agent-native.md +202 -0
  82. package/corpus/core/docs/content/locales/zh-TW/workspace-connections.md +321 -0
  83. package/corpus/core/docs/content/locales/zh-TW/workspace-management.md +175 -0
  84. package/corpus/core/docs/content/locales/zh-TW/workspace.md +323 -0
  85. package/corpus/core/docs/content/locales/zh-TW/writing-agent-instructions.md +173 -0
  86. package/corpus/core/package.json +2 -2
  87. package/corpus/core/scripts/check-dist-imports.mjs +35 -0
  88. package/corpus/core/src/client/ErrorBoundary.tsx +10 -0
  89. package/corpus/core/src/client/FeedbackButton.tsx +12 -0
  90. package/corpus/core/src/client/blocks/library/block-copy.ts +32 -0
  91. package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +33 -0
  92. package/corpus/core/src/client/i18n.tsx +6 -1
  93. package/corpus/core/src/localization/actions/set-localization-preference.ts +2 -1
  94. package/corpus/core/src/localization/default-messages.ts +492 -0
  95. package/corpus/core/src/localization/shared.ts +45 -0
  96. package/corpus/core/src/server/agent-chat-plugin.ts +38 -0
  97. package/corpus/core/src/server/onboarding-html.ts +99 -0
  98. package/corpus/core/src/templates/default/app/i18n/index.ts +2 -0
  99. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +466 -0
  100. package/corpus/core/src/templates/default/app/root.tsx +8 -0
  101. package/corpus/templates/analytics/app/i18n/index.ts +2 -0
  102. package/corpus/templates/analytics/app/i18n/zh-TW.ts +818 -0
  103. package/corpus/templates/analytics/app/i18n-data.ts +9 -0
  104. package/corpus/templates/assets/app/i18n/index.ts +2 -0
  105. package/corpus/templates/assets/app/i18n/zh-TW.ts +860 -0
  106. package/corpus/templates/assets/app/i18n-data.ts +3 -0
  107. package/corpus/templates/brain/app/i18n/index.ts +2 -0
  108. package/corpus/templates/brain/app/i18n/zh-TW.ts +709 -0
  109. package/corpus/templates/brain/app/i18n-data.ts +3 -0
  110. package/corpus/templates/calendar/app/i18n/zh-TW.ts +836 -0
  111. package/corpus/templates/calendar/app/i18n-data.ts +4 -0
  112. package/corpus/templates/chat/app/i18n/index.ts +2 -0
  113. package/corpus/templates/chat/app/i18n/zh-TW.ts +67 -0
  114. package/corpus/templates/chat/app/i18n-data.ts +3 -0
  115. package/corpus/templates/clips/app/i18n/index.ts +2 -0
  116. package/corpus/templates/clips/app/i18n/zh-TW.ts +1280 -0
  117. package/corpus/templates/content/app/i18n/index.ts +2 -0
  118. package/corpus/templates/content/app/i18n/zh-TW.ts +906 -0
  119. package/corpus/templates/content/app/i18n-data.ts +4 -0
  120. package/corpus/templates/design/app/i18n/index.ts +2 -0
  121. package/corpus/templates/design/app/i18n/zh-TW.ts +517 -0
  122. package/corpus/templates/design/app/i18n-data.ts +6 -0
  123. package/corpus/templates/dispatch/app/i18n/index.ts +2 -0
  124. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +195 -0
  125. package/corpus/templates/dispatch/app/i18n-data.ts +3 -0
  126. package/corpus/templates/forms/app/i18n/index.ts +2 -0
  127. package/corpus/templates/forms/app/i18n/zh-TW.ts +349 -0
  128. package/corpus/templates/macros/app/i18n/index.ts +2 -0
  129. package/corpus/templates/macros/app/i18n/zh-TW.ts +224 -0
  130. package/corpus/templates/mail/app/i18n/index.ts +2 -0
  131. package/corpus/templates/mail/app/i18n/zh-TW.ts +562 -0
  132. package/corpus/templates/mail/app/root.tsx +6 -0
  133. package/corpus/templates/plan/app/i18n/index.ts +2 -0
  134. package/corpus/templates/plan/app/i18n/zh-TW.ts +712 -0
  135. package/corpus/templates/slides/app/i18n/index.ts +2 -0
  136. package/corpus/templates/slides/app/i18n/zh-TW.ts +531 -0
  137. package/corpus/templates/videos/app/i18n/index.ts +2 -0
  138. package/corpus/templates/videos/app/i18n/zh-TW.ts +435 -0
  139. package/dist/client/ErrorBoundary.d.ts.map +1 -1
  140. package/dist/client/ErrorBoundary.js +10 -0
  141. package/dist/client/ErrorBoundary.js.map +1 -1
  142. package/dist/client/FeedbackButton.d.ts.map +1 -1
  143. package/dist/client/FeedbackButton.js +12 -0
  144. package/dist/client/FeedbackButton.js.map +1 -1
  145. package/dist/client/blocks/library/block-copy.d.ts.map +1 -1
  146. package/dist/client/blocks/library/block-copy.js +32 -0
  147. package/dist/client/blocks/library/block-copy.js.map +1 -1
  148. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  149. package/dist/client/extensions/ExtensionsSidebarSection.js +32 -0
  150. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  151. package/dist/client/i18n.d.ts.map +1 -1
  152. package/dist/client/i18n.js +6 -1
  153. package/dist/client/i18n.js.map +1 -1
  154. package/dist/collab/routes.d.ts +2 -2
  155. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  156. package/dist/localization/actions/set-localization-preference.d.ts.map +1 -1
  157. package/dist/localization/actions/set-localization-preference.js +2 -2
  158. package/dist/localization/actions/set-localization-preference.js.map +1 -1
  159. package/dist/localization/default-messages.d.ts +443 -0
  160. package/dist/localization/default-messages.d.ts.map +1 -0
  161. package/dist/localization/default-messages.js +448 -0
  162. package/dist/localization/default-messages.js.map +1 -0
  163. package/dist/localization/shared.d.ts +1 -1
  164. package/dist/localization/shared.d.ts.map +1 -1
  165. package/dist/localization/shared.js +43 -0
  166. package/dist/localization/shared.js.map +1 -1
  167. package/dist/notifications/routes.d.ts +2 -2
  168. package/dist/observability/routes.d.ts +7 -7
  169. package/dist/progress/routes.d.ts +1 -1
  170. package/dist/resources/handlers.d.ts +3 -3
  171. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  172. package/dist/server/agent-chat-plugin.js +39 -0
  173. package/dist/server/agent-chat-plugin.js.map +1 -1
  174. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  175. package/dist/server/onboarding-html.d.ts.map +1 -1
  176. package/dist/server/onboarding-html.js +96 -0
  177. package/dist/server/onboarding-html.js.map +1 -1
  178. package/dist/server/transcribe-voice.d.ts +1 -1
  179. package/dist/templates/default/app/i18n/index.ts +2 -0
  180. package/dist/templates/default/app/i18n/zh-TW.ts +466 -0
  181. package/dist/templates/default/app/root.tsx +8 -0
  182. package/docs/content/locales/zh-TW/a2a-protocol.md +392 -0
  183. package/docs/content/locales/zh-TW/actions.md +583 -0
  184. package/docs/content/locales/zh-TW/agent-mentions.md +164 -0
  185. package/docs/content/locales/zh-TW/agent-surfaces.md +397 -0
  186. package/docs/content/locales/zh-TW/agent-teams.md +171 -0
  187. package/docs/content/locales/zh-TW/agent-web-surfaces.md +161 -0
  188. package/docs/content/locales/zh-TW/audit-log.md +111 -0
  189. package/docs/content/locales/zh-TW/authentication.md +332 -0
  190. package/docs/content/locales/zh-TW/automations.md +268 -0
  191. package/docs/content/locales/zh-TW/blueprint-installer.md +83 -0
  192. package/docs/content/locales/zh-TW/cli-adapters.md +129 -0
  193. package/docs/content/locales/zh-TW/client.md +398 -0
  194. package/docs/content/locales/zh-TW/cloneable-saas.md +114 -0
  195. package/docs/content/locales/zh-TW/code-agents-ui.md +436 -0
  196. package/docs/content/locales/zh-TW/components.md +368 -0
  197. package/docs/content/locales/zh-TW/context-awareness.md +373 -0
  198. package/docs/content/locales/zh-TW/creating-templates.md +411 -0
  199. package/docs/content/locales/zh-TW/cross-app-sso.md +188 -0
  200. package/docs/content/locales/zh-TW/database.md +183 -0
  201. package/docs/content/locales/zh-TW/deployment.md +348 -0
  202. package/docs/content/locales/zh-TW/dispatch.md +146 -0
  203. package/docs/content/locales/zh-TW/drop-in-agent.md +260 -0
  204. package/docs/content/locales/zh-TW/durable-resume.md +65 -0
  205. package/docs/content/locales/zh-TW/embedding-sdk.md +597 -0
  206. package/docs/content/locales/zh-TW/evals.md +155 -0
  207. package/docs/content/locales/zh-TW/extensions.md +360 -0
  208. package/docs/content/locales/zh-TW/external-agents.md +619 -0
  209. package/docs/content/locales/zh-TW/faq.md +142 -0
  210. package/docs/content/locales/zh-TW/file-uploads.md +122 -0
  211. package/docs/content/locales/zh-TW/frames.md +153 -0
  212. package/docs/content/locales/zh-TW/getting-started.md +199 -0
  213. package/docs/content/locales/zh-TW/harness-agents.md +349 -0
  214. package/docs/content/locales/zh-TW/human-approval.md +86 -0
  215. package/docs/content/locales/zh-TW/internationalization.md +147 -0
  216. package/docs/content/locales/zh-TW/key-concepts.md +312 -0
  217. package/docs/content/locales/zh-TW/local-file-mode.md +433 -0
  218. package/docs/content/locales/zh-TW/mcp-apps.md +147 -0
  219. package/docs/content/locales/zh-TW/mcp-clients.md +330 -0
  220. package/docs/content/locales/zh-TW/mcp-protocol.md +279 -0
  221. package/docs/content/locales/zh-TW/messaging.md +461 -0
  222. package/docs/content/locales/zh-TW/migration-workbench.md +33 -0
  223. package/docs/content/locales/zh-TW/multi-app-workspace.md +312 -0
  224. package/docs/content/locales/zh-TW/multi-tenancy.md +52 -0
  225. package/docs/content/locales/zh-TW/native-chat-ui.md +321 -0
  226. package/docs/content/locales/zh-TW/notifications.md +231 -0
  227. package/docs/content/locales/zh-TW/observability.md +294 -0
  228. package/docs/content/locales/zh-TW/observational-memory.md +77 -0
  229. package/docs/content/locales/zh-TW/onboarding.md +216 -0
  230. package/docs/content/locales/zh-TW/plan-plugin.md +200 -0
  231. package/docs/content/locales/zh-TW/pr-visual-recap.md +384 -0
  232. package/docs/content/locales/zh-TW/processors.md +106 -0
  233. package/docs/content/locales/zh-TW/progress.md +199 -0
  234. package/docs/content/locales/zh-TW/pure-agent-apps.md +39 -0
  235. package/docs/content/locales/zh-TW/real-time-collaboration.md +680 -0
  236. package/docs/content/locales/zh-TW/recurring-jobs.md +142 -0
  237. package/docs/content/locales/zh-TW/routing.md +79 -0
  238. package/docs/content/locales/zh-TW/sandbox-adapters.md +227 -0
  239. package/docs/content/locales/zh-TW/security.md +330 -0
  240. package/docs/content/locales/zh-TW/server.md +265 -0
  241. package/docs/content/locales/zh-TW/sharing.md +219 -0
  242. package/docs/content/locales/zh-TW/skills-guide.md +281 -0
  243. package/docs/content/locales/zh-TW/template-analytics.md +259 -0
  244. package/docs/content/locales/zh-TW/template-assets.md +303 -0
  245. package/docs/content/locales/zh-TW/template-brain.md +324 -0
  246. package/docs/content/locales/zh-TW/template-calendar.md +194 -0
  247. package/docs/content/locales/zh-TW/template-chat.md +129 -0
  248. package/docs/content/locales/zh-TW/template-clips.md +368 -0
  249. package/docs/content/locales/zh-TW/template-content.md +402 -0
  250. package/docs/content/locales/zh-TW/template-design.md +173 -0
  251. package/docs/content/locales/zh-TW/template-dispatch.md +220 -0
  252. package/docs/content/locales/zh-TW/template-forms.md +178 -0
  253. package/docs/content/locales/zh-TW/template-mail.md +239 -0
  254. package/docs/content/locales/zh-TW/template-plan.md +814 -0
  255. package/docs/content/locales/zh-TW/template-slides.md +293 -0
  256. package/docs/content/locales/zh-TW/template-videos.md +222 -0
  257. package/docs/content/locales/zh-TW/tracking.md +236 -0
  258. package/docs/content/locales/zh-TW/using-your-agent.md +71 -0
  259. package/docs/content/locales/zh-TW/voice-input.md +81 -0
  260. package/docs/content/locales/zh-TW/what-is-agent-native.md +202 -0
  261. package/docs/content/locales/zh-TW/workspace-connections.md +321 -0
  262. package/docs/content/locales/zh-TW/workspace-management.md +175 -0
  263. package/docs/content/locales/zh-TW/workspace.md +323 -0
  264. package/docs/content/locales/zh-TW/writing-agent-instructions.md +173 -0
  265. package/package.json +2 -2
  266. package/src/templates/default/app/i18n/index.ts +2 -0
  267. package/src/templates/default/app/i18n/zh-TW.ts +466 -0
  268. package/src/templates/default/app/root.tsx +8 -0
@@ -0,0 +1,680 @@
1
+ ---
2
+ title: "實時協作"
3
+ description: "多使用者協作編輯,其中 AI 代理是一流的同行:CRDT 合並、實時呈現、SSE 快速路徑和細粒度伺服器端合並 - 在任何 SQL 資料庫和任何主機上。"
4
+ ---
5
+
6
+ # 實時協作
7
+
8
+ 想象一下開啟檔案並看到同伴的光標滾動到某個段落,
9
+ 然後文本會自行重寫——就像外科手術一樣,不會丟失你的位置。那
10
+ 同伴可能是隊友。可能是代理吧來自框架的
11
+ 從角度來看它們是相同的:都產生合並的 Yjs 操作
12
+ 無衝突地進入共用檔案。這是
13
+ 代理與本機協作模型。
14
+
15
+ ## 願景 {#vision}
16
+
17
+ 與代理一起編輯感覺就像在 Google Docs 或 Figma 中工作
18
+ 一位既快速又不知疲倦的同事:
19
+
20
+ 如果您只需要在代理或其他使用者寫入 SQL 時刷新 UI,則不需要任何這些 — 使用 [`useDbSync`](/docs/client)。此頁面用於對單個富文本檔案進行字符級共同編輯(共用光標、無衝突合並)。兩者都使用相同的 `/_agent-native/poll` 通道。
21
+
22
+ 它建立在三項經過實战檢驗的技術之上:**Yjs**(CRDT,用於無衝突合並)、**TipTap**(富文本編輯器)和**基於輪詢的同步**(適用於所有部署環境,包括無伺服器和邊缘)。
23
+
24
+ - **CRDT 合並** - 人類和代理的並發編輯無需合並
25
+ 衝突。您輸入一個段落;代理重寫另一個;兩者
26
+ 幹淨利落地著陸。
27
+ - **存在** - `PresenceBar` 顯示目前誰在檔案中,
28
+ 當客服人員正在積極編輯時,包括客服人員存在指示器。
29
+ - **代理作為對等編輯器** — 代理通過相同的 Yjs 進行編輯流程
30
+ 作為人工編輯的基礎設施。它們顯示為實時狀態,不會幹擾光標
31
+ 位置、選取或撤消堆堆疊。
32
+ - **隨處可用** — Drizzle 支持的任何 SQL 資料庫(SQLite、Postgres)。
33
+ Nitro 支持的任何託管目標,包括無伺服器和邊缘。
34
+
35
+ ## 架構 {#architecture}
36
+
37
+ 協作系統有五個互鎖層。
38
+
39
+ ```an-diagram title="五層互鎖" summary="從內存中的 CRDT 到在對等點之間傳送更新的傳輸 — 每一層都有一項工作。"
40
+ {
41
+ "html": "<div class=\"diagram-stack\"><div class=\"diagram-card layer\"><span class=\"diagram-pill accent\">1 &middot; Yjs Y.Doc</span><small class=\"diagram-muted\">CRDT &mdash; 無衝突合並,無協調器</small></div><div class=\"diagram-card layer\"><span class=\"diagram-pill\">2 &middot; SQL 規範內容</span><small class=\"diagram-muted\">_collab_docs &mdash; durable source of truth, versioned</small></div><div class=\"diagram-card layer\"><span class=\"diagram-pill\">3 &middot; 由 updatedAt 門控的對帳</span><small class=\"diagram-muted\">代理編輯通過 SQL 更新時間傳播</small></div><div class=\"diagram-card layer\"><span class=\"diagram-pill\">4 &middot; 主用戶端選舉</span><small class=\"diagram-muted\">恰好一個標籤頁面應用快照</small></div><div class=\"diagram-card layer\"><span class=\"diagram-pill ok\">5 &middot; SSE 快速路徑 + 輪詢</span><small class=\"diagram-muted\">約幾十毫秒,任何地方都可降級為 2 秒輪詢</small></div></div>",
42
+ "css": ".diagram-stack{display:flex;flex-direction:column;gap:8px}.diagram-stack .layer{display:flex;flex-direction:column;gap:4px;padding:12px 14px}"
43
+ }
44
+ ```
45
+
46
+ ### 1。 Yjs Y.Doc(CRDT層)
47
+
48
+ 每個協作檔案都是一個包含共用型別的 `Y.Doc` — 通常是
49
+ `Y.XmlFragment` 用於富文本(TipTap 讀取的 ProseMirror 節點樹)或
50
+ `Y.Map` / `Y.Array` 用於結構化 JSON 資料。 Yjs合並並發更新
51
+ 沒有中央協調員;任何兩個交換狀態的用戶端
52
+ 無論順序如何,結果都是相同的。
53
+
54
+ ### 2。 SQL 規範內容(持久的事實來源)
55
+
56
+ Yjs 狀態以 Base64 編碼的二進制形式儲存在 `_collab_docs` 表中。
57
+ 該表由框架管理且與提供者無關(SQLite 和 Postgres 使用
58
+ 相同的模式)。每行都有一個樂觀並發版本列
59
+ 防止並發寫入競爭。墓碑壓縮會機會性地執行
60
+ 當存儲的 blob 超過新編碼狀態的 4 倍時 — 無後台作業
61
+ 必需。
62
+
63
+ ### 3。 `updatedAt` 門控協調(代理編輯傳播)
64
+
65
+ 代理 actions 不會推送到進程中的 Yjs。相反,該操作會編輯
66
+ 規範的 SQL 內容列和凹凸 `updatedAt`。變更同步系統
67
+ 檢測到碰撞,開啟的編輯器重新獲取紀錄,並且主要用戶端
68
+ 通過 `setContent` 將新內容應用到共用的 Y.Doc 中。一個`updatedAt`
69
+ gate 確保僅采用真正較新的內容 - 滯後的民意調查回應
70
+ 無法恢復編輯。
71
+
72
+ ### 4。主客戶選舉(重複資料刪除)
73
+
74
+ 開啟多個分頁時,只有一個分頁應用權威的 SQL 快照
75
+ 進入共用的 Y.Doc。領先的是 Yjs `clientID` 最低的分頁
76
+ 目前可見的對等體中。代理的意識條目使用
77
+ `AGENT_CLIENT_ID` (max int) 所以它永遠不可能成為領先。用戶端編輯
78
+ 獨自一人永遠是領先者。選舉是確定性的,沒有協調
79
+ 往返(從 `@agent-native/core/client` 到 `isReconcileLeadClient`)。
80
+
81
+ ### 5。 SSE 快速路徑+輪詢回退(傳輸)
82
+
83
+ 協作更新事件通過兩條路徑傳輸:
84
+
85
+ - **SSE 快速路徑** — 用戶端訂閱 `/_agent-native/poll-events`
86
+ (`useDbSync` 使用的相同 `EventSource`)。協作更新事件到來
87
+ 推送式,通常為數十毫秒。雖然 SSE 很健康
88
+ 輪詢循環放松到較慢的節奏(預設情況下約為 12 秒)。
89
+ - **輪詢回退** — `/_agent-native/poll?since=N` 每 2 秒輪詢一次
90
+ 當 SSE 不可用時。這使得協作可以在任何部署上進行
91
+ 目標 - 包括持久連線的無伺服器功能
92
+ 不可能,不同的調用可以處理不同的請求。
93
+
94
+ 本機 Yjs 更新已去抖並與 `Y.mergeUpdates` 合並(約 80 毫秒)
95
+ 在發送到伺服器之前,減少擊鍵級別的網路流量。
96
+ 批次立即在 `visibilitychange` 或 `pagehide` 上刷新。一個
97
+ 狀態向量差異(`GET /:docId/state?stateVector=…`)僅在
98
+ 重新連線、環形緩衝區溢出或每 15 個輪詢週期 - 不是每個
99
+ 循環。
100
+
101
+ 網路錯誤使用帶抖動的指數退避,上限約為 15 秒。
102
+
103
+ ```an-diagram title="兩條編輯路徑,一條合並" summary="人類擊鍵流程 Y.Doc → 伺服器 → SSE。代理編輯經過 SQL:操作在更新時發生碰撞,主要客戶進行協調,然後更改重新進入 Yjs。"
104
+ {
105
+ "html": "<div class=\"diagram-collab\"><div class=\"lane\"><span class=\"diagram-pill\">人工編輯</span><div class=\"diagram-node\">Y.Doc update<br><small class=\"diagram-muted\">debounce 約 80ms</small></div><span class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">&rarr;</span><div class=\"diagram-box\" data-rough>POST /update<br><small class=\"diagram-muted\">apply + persist</small></div><span class=\"diagram-arrow diagram-accent\" aria-hidden=\"true\">&rarr;</span><div class=\"diagram-box diagram-accent\">SSE push<br><small class=\"diagram-muted\">to all peers</small></div></div><div class=\"lane\"><span class=\"diagram-pill warn\">代理編輯</span><div class=\"diagram-node\">Action 寫入 SQL<br><small class=\"diagram-muted\">更新 updatedAt</small></div><span class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">&rarr;</span><div class=\"diagram-box\" data-rough>主用戶端<br><small class=\"diagram-muted\">setContent 寫入 Y.Doc</small></div><span class=\"diagram-arrow diagram-accent\" aria-hidden=\"true\">&rarr;</span><div class=\"diagram-box diagram-accent\">POST /update<br><small class=\"diagram-muted\">re-enters Yjs &middot; SSE push</small></div></div></div>",
106
+ "css": ".diagram-collab{display:flex;flex-direction:column;gap:14px}.diagram-collab .lane{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.diagram-collab .diagram-arrow{font-size:22px;line-height:1}"
107
+ }
108
+ ```
109
+
110
+ ## 快速入門 {#quickstart}
111
+
112
+ ### 1。安裝包
113
+
114
+ ```bash
115
+ pnpm add @tiptap/extension-collaboration @tiptap/extension-collaboration-caret @tiptap/y-tiptap @tiptap/core
116
+ ```
117
+
118
+ ### 2。新增Vite最佳化Deps
119
+
120
+ 防止 Vite 在開發過程中以不兼容的方式重新捆綁 TipTap:
121
+
122
+ ```ts
123
+ // vite.config.ts
124
+ import { reactRouter } from "@react-router/dev/vite";
125
+ import { agentNative } from "@agent-native/core/vite";
126
+ import { defineConfig } from "vite";
127
+
128
+ export default defineConfig({
129
+ plugins: [reactRouter(), agentNative()],
130
+ optimizeDeps: {
131
+ include: [
132
+ "yjs",
133
+ "y-protocols/awareness",
134
+ "@tiptap/core",
135
+ "@tiptap/extension-collaboration",
136
+ "@tiptap/extension-collaboration-caret",
137
+ "@tiptap/y-tiptap",
138
+ ],
139
+ },
140
+ });
141
+ ```
142
+
143
+ ### 3。新增協作伺服器外掛
144
+
145
+ 始終將 `resourceType` 設定為註冊的可共用資源的名稱
146
+ 通過 `registerShareableResource`。如果沒有它,協作推送事件就會被傳遞
147
+ 所有經過驗證的使用者(沒有檔案級範圍)和伺服器
148
+ 紀錄一次性警告。
149
+
150
+ ```ts
151
+ // server/plugins/collab.ts
152
+ import { createCollabPlugin } from "@agent-native/core/server";
153
+
154
+ export default createCollabPlugin({
155
+ table: "documents",
156
+ contentColumn: "content",
157
+ idColumn: "id",
158
+ resourceType: "document", // required for access-scoped event delivery
159
+ });
160
+ ```
161
+
162
+ ### 4.使用用戶端鉤子
163
+
164
+ ```ts
165
+ import {
166
+ useCollaborativeDoc,
167
+ emailToColor,
168
+ emailToName,
169
+ } from "@agent-native/core/client";
170
+
171
+ const TAB_ID = generateTabId(); // or Math.random().toString(36)
172
+
173
+ const { ydoc, awareness, isLoading, activeUsers, agentActive, agentPresent } =
174
+ useCollaborativeDoc({
175
+ docId: documentId,
176
+ requestSource: TAB_ID,
177
+ user: {
178
+ name: emailToName(session.email),
179
+ email: session.email,
180
+ color: emailToColor(session.email),
181
+ },
182
+ });
183
+ ```
184
+
185
+ ### 5.新增TipTap擴充功能
186
+
187
+ ```ts
188
+ import Collaboration from "@tiptap/extension-collaboration";
189
+ import CollaborationCaret from "@tiptap/extension-collaboration-caret";
190
+
191
+ const editor = useEditor({
192
+ extensions: [
193
+ StarterKit.configure({ history: false }), // Yjs owns undo
194
+ Collaboration.configure({ document: ydoc }),
195
+ CollaborationCaret.configure({
196
+ provider: { awareness },
197
+ user: { name, color },
198
+ }),
199
+ ],
200
+ // Do NOT pass content here — Yjs owns the content
201
+ });
202
+ ```
203
+
204
+ ### 6。首次載入時的種子(如果內容存在)
205
+
206
+ 協作擴充功能不會從 `content` 屬性自動播種。如果
207
+ Y.Doc 為空,檔案已有內容,為其播種:
208
+
209
+ ```ts
210
+ useEffect(() => {
211
+ if (!ydoc || !editor || !isLoaded) return;
212
+ const fragment = ydoc.getXmlFragment("default");
213
+ if (fragment.length === 0 && initialContent) {
214
+ editor.commands.setContent(initialContent);
215
+ }
216
+ }, [ydoc, editor, isLoaded]);
217
+ ```
218
+
219
+ 使用者身分來源自工作階段電子郵件。該框架提供了 `emailToColor()` 和 `emailToName()` 幫助程序,用於根據電子郵件地址生成一致的光標顏色和顯示名稱。
220
+
221
+ ## 評論 {#comments}
222
+
223
+ 範本可以新增評論系統,對檔案進行線程討論。內容範本的評論系統包括完整的實現:
224
+
225
+ - `document_comments` SQL 表(話題、回複、已解決狀態)
226
+ - 內容範本的REST路由,用於在`/api/comments/:id`處更新/刪除;通過 `add-comment` / `list-comments` actions 建立並列出執行。自訂範本針對核心 `POST /_agent-native/collab/:docId/search-replace` 路由實現自己的等效端點。
227
+ - 帶有線索視圖和回複的評論側邊欄 UI
228
+ - 解析/取消解析線程
229
+ - **發送到 AI** 按鈕 - 通過 `sendToAgentChat()` 將評論線程上下文發送到代理聊天
230
+ - 代理actions:`list-comments`,`add-comment`
231
+ - Notion評論同步:`sync-notion-comments`雙向拉/推操作
232
+
233
+ ## 協作路線 {#collab-routes}
234
+
235
+ 所有協作路由均由協作外掛自動掛載在 `/_agent-native/collab/` 下:
236
+
237
+ | 路線 | 目的 |
238
+ | ----------------------------- | ------------------------------------------ |
239
+ | `GET /:docId/state` | 獲取完整的 Y.Doc 狀態 (base64) |
240
+ | `POST /:docId/update` | 應用用戶端 Yjs 更新 |
241
+ | `POST /:docId/text` | 應用全文替換(基於差異) |
242
+ | `POST /:docId/search-replace` | 在 Y.XmlFragment 中進行外科手術式查找/替換 |
243
+ | `POST /:docId/awareness` | 同步光標/存在狀態 |
244
+ | `GET /:docId/users` | 列出檔案上的活躍使用者 |
245
+
246
+ ## 代理編輯操作 {#edit-document}
247
+
248
+ 內容範本的 `edit-document` 操作是代理在協作模式下更改檔案的主要方式:
249
+
250
+ ```bash
251
+ # 單次編輯
252
+ pnpm action edit-document --id doc123 --find "old text" --replace "new text"
253
+
254
+ # 批量編輯
255
+ pnpm action edit-document --id doc123 --edits '[{"find":"old","replace":"new"}]'
256
+
257
+ # 刪除文字
258
+ pnpm action edit-document --id doc123 --find "delete me" --replace ""
259
+ ```
260
+
261
+ ---
262
+
263
+ ## 存在套件 {#presence-kit}
264
+
265
+ 存在套件在現有感知層之上提供 Liveblocks/Figma 級實時光標和選取基元。
266
+
267
+ 從焦點瀏覽器子路徑匯入用戶端狀態和編輯器 UI:
268
+
269
+ ```ts
270
+ import {
271
+ PresenceBar,
272
+ LiveCursorOverlay,
273
+ RemoteSelectionRings,
274
+ useCollaborativeDoc,
275
+ usePresence,
276
+ } from "@agent-native/core/client/collab";
277
+ ```
278
+
279
+ 伺服器端代理存在幫助程序保留在較低級別的協作包中:
280
+
281
+ ```ts
282
+ import {
283
+ agentEnterDocument,
284
+ agentLeaveDocument,
285
+ agentUpdateSelection,
286
+ } from "@agent-native/core/collab";
287
+ ```
288
+
289
+ ### 公開API {#presence-public-api}
290
+
291
+ | API | 目的 |
292
+ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
293
+ | `useCollaborativeDoc(options)` | 建立穩定的 `Y.Doc` 和感知執行個體,處理狀態向量同步、SSE 快速路徑、輪詢回退、活動使用者和代理存在標志。 |
294
+ | `usePresence(awareness, localClientId)` | 派生遠端參與者並發布任意本機感知欄位,例如光標、選取、視口或工具模式。 |
295
+ | `<PresenceBar>` | 渲染活躍的協作者和人工智能代理,並帶有可選的頭像點擊跟隨模式連線。 |
296
+ | `<LiveCursorOverlay>` | 根據標準化的 0-1 坐標在定位容器上渲染遠端光標標籤。 |
297
+ | `<RemoteSelectionRings>` | 在您的應用解析的選定 DOM 元素週圍渲染彩色環和標籤。 |
298
+ | `useFollowUser(options)` | 當關注的參與者發布視口更改時調用回調。 |
299
+ | `toNormalized()` / `fromNormalized()` | 將指針坐標與標準化容器坐標相互轉換。 |
300
+ | `dedupeCollabUsersByEmail()` | 建置自訂頭像堆堆疊,無需一個使用者在每個開啟的分頁中顯示一次。 |
301
+ | `useCollaborativeMap()` / `useCollaborativeArray()` | 用於 Y.Map/Y.Array 結構化協作的用戶端掛鉤。視為較低級別,直到範本證明準確的產品模式。 |
302
+
303
+ `UseCollaborativeDocOptions`:
304
+
305
+ | 選項 | 描述 |
306
+ | --------------------- | ------------------------------------------------- |
307
+ | `docId` | 檔案 ID,或 `null` 以停用掛鉤。 |
308
+ | `pollInterval` | SSE 不可用時的輪詢間隔。預設值:`2000`。 |
309
+ | `pollIntervalWithSse` | SSE 執行狀況良好時輪詢間隔較慢。預設值:`12000`。 |
310
+ | `pauseWhenHidden` | 隱藏時暫停遠端更新/狀態輪詢。預設值:`true`。 |
311
+ | `baseUrl` | 協作端點前綴。預設值:`/_agent-native/collab`。 |
312
+ | `requestSource` | 穩定的分頁/來源 ID 用於忽略自產生的刷新噪音。 |
313
+ | `user` | 光標中顯示 `{ name, email, color }` 並存在 UI。 |
314
+
315
+ `UseCollaborativeDocResult`:
316
+
317
+ | 欄位 | 描述 |
318
+ | -------------- | --------------------------------------------------- |
319
+ | `ydoc` | 目前`docId`的穩定`Y.Doc`。 |
320
+ | `awareness` | 光標、選取和跟隨模式使用的 Yjs Awareness 執行個體。 |
321
+ | `isLoading` | 初始伺服器狀態仍在載入中。 |
322
+ | `isSynced` | 掛鉤已趕上伺服器狀態。 |
323
+ | `activeUsers` | 來自意識的人類合作者。 |
324
+ | `agentActive` | 代理正在積極編輯。 |
325
+ | `agentPresent` | 代理有此檔案的認知條目。 |
326
+
327
+ ### 快速認知 {#fast-awareness}
328
+
329
+ 感知狀態更改現在以約 150 毫秒的速度傳播,而不是 2 秒的輪詢週期:
330
+
331
+ - **用戶端 → 伺服器**:對 `setPresence()` 或 `awareness.setLocalStateField()` 的任何調用都會在 150 毫秒內觸發對 POST 到 `/_agent-native/collab/:docId/awareness` 的節流,將快速更改合並為一個請求。
332
+ - **伺服器 → 用戶端**:`postAwareness` 處理程序在存儲後發出 `AWARENESS_CHANGE_EVENT`。 `/_agent-native/poll-events` SSE 流將這些事件推送式轉發到連線的對等點。僅輪詢部署繼續工作 - 光標降級到輪詢節奏而不會出現錯誤。
333
+
334
+ ### `usePresence(awareness, localClientId)` {#use-presence}
335
+
336
+ 返回遠端參與者的反應列表和本機線上狀態有效負載的設定器:
337
+
338
+ ```ts
339
+ import { usePresence } from "@agent-native/core/client";
340
+
341
+ const { others, setPresence } = usePresence(awareness, ydoc?.clientID);
342
+
343
+ // Publish cursor position (normalized 0–1)
344
+ setPresence({ cursor: { x: 0.4, y: 0.7 }, selection: "#hero" });
345
+
346
+ // others: OtherPresence[]
347
+ // {
348
+ // clientId: number
349
+ // user: { name, email, color }
350
+ // presence: { cursor?, selection?, viewport?, ... }
351
+ // isAgent: boolean ← true for AGENT_CLIENT_ID
352
+ // }
353
+ ```
354
+
355
+ 代理 (AGENT_CLIENT_ID) 顯示為 `isAgent: true` 的一級參與者。當 `agentUpdateSelection()` 被稱為伺服器端時,它的選取元資料像任何其他參與者一樣流經 `usePresence`。
356
+
357
+ ### `LiveCursorOverlay` {#live-cursor-overlay}
358
+
359
+ 將遠端光標呈現為容器元素上的絕對定位標籤:
360
+
361
+ ```tsx
362
+ import { LiveCursorOverlay } from "@agent-native/core/client";
363
+
364
+ // cursor positions stored as { x, y } normalized 0–1 under presence.cursor
365
+ <div ref={containerRef} style={{ position: "relative" }}>
366
+ {content}
367
+ <LiveCursorOverlay
368
+ others={others} // from usePresence
369
+ containerRef={containerRef}
370
+ cursorKey="cursor" // key in presence payload (default: "cursor")
371
+ />
372
+ </div>;
373
+ ```
374
+
375
+ 代理的光標清晰地呈現為閃爍圖標。光標在 10 秒不活動後淡出,並以 120 毫秒平滑 CSS 過渡。
376
+
377
+ ### `RemoteSelectionRings` {#remote-selection-rings}
378
+
379
+ 在遠端選取的元素上渲染彩色輪廓環+名稱標籤:
380
+
381
+ ```tsx
382
+ import { RemoteSelectionRings } from "@agent-native/core/client";
383
+
384
+ <div ref={containerRef} style={{ position: "relative" }}>
385
+ {content}
386
+ <RemoteSelectionRings
387
+ others={others}
388
+ selectionKey="selection" // key in presence payload (default: "selection")
389
+ resolveRect={(descriptor) =>
390
+ document.querySelector(descriptor)?.getBoundingClientRect() ?? null
391
+ }
392
+ containerRef={containerRef}
393
+ />
394
+ </div>;
395
+ ```
396
+
397
+ ### `useFollowUser` {#follow-user}
398
+
399
+ 每當跟隨的參與者的視口發生變化時調用回調:
400
+
401
+ ```ts
402
+ import { useFollowUser } from "@agent-native/core/client";
403
+
404
+ const { isFollowing, stopFollowing } = useFollowUser({
405
+ others,
406
+ followingId, // null to stop following
407
+ viewportKey: "viewport",
408
+ onViewport: (vp) => {
409
+ if (vp.fileId) setActiveFileId(vp.fileId);
410
+ if (vp.zoom) setZoom(vp.zoom);
411
+ },
412
+ });
413
+ ```
414
+
415
+ 參與者使用 `setPresence({ viewport: { fileId, zoom } })` 發布他們的視口。
416
+
417
+ ### `PresenceBar`跟隨模式道具 {#presence-bar-follow}
418
+
419
+ `PresenceBar` 元件現在接受可選的跟隨模式道具:
420
+
421
+ ```tsx
422
+ <PresenceBar
423
+ activeUsers={activeUsers}
424
+ agentActive={agentActive}
425
+ onAvatarClick={(user) => {
426
+ // user is null for the agent avatar
427
+ const email = user?.email ?? "agent@system";
428
+ setFollowing((prev) => (prev === email ? null : email));
429
+ }}
430
+ followingEmail={followingEmail} // highlighted avatar + "Following X" chip
431
+ />
432
+ ```
433
+
434
+ ### 標準化坐標助手 {#norm-coords}
435
+
436
+ ```ts
437
+ import { toNormalized, fromNormalized } from "@agent-native/core/client";
438
+
439
+ // In a pointer event handler:
440
+ const norm = toNormalized(
441
+ e.clientX,
442
+ e.clientY,
443
+ container.getBoundingClientRect(),
444
+ );
445
+ setPresence({ cursor: norm });
446
+
447
+ // In a cursor renderer:
448
+ const px = fromNormalized(norm, container.getBoundingClientRect());
449
+ ```
450
+
451
+ ### 代理光標管道 {#agent-cursor}
452
+
453
+ 伺服器端actions調用`agentUpdateSelection()`來發布代理在哪裡工作。設計範本的 `edit-design` 和 `generate-design` actions 自動調用此函數。其他範本也可以執行相同的操作:
454
+
455
+ ```ts
456
+ import {
457
+ agentEnterDocument,
458
+ agentLeaveDocument,
459
+ agentUpdateSelection,
460
+ } from "@agent-native/core/collab";
461
+
462
+ agentEnterDocument(docId);
463
+ agentUpdateSelection(docId, {
464
+ selection: "#target-element",
465
+ editingFile: "index.html",
466
+ });
467
+ try {
468
+ // ... perform edits ...
469
+ } finally {
470
+ agentLeaveDocument(docId);
471
+ }
472
+ ```
473
+
474
+ 選取元資料作為 `other.presence.selection` 在連線的用戶端上通過 `usePresence` 流動。
475
+
476
+ ---
477
+
478
+ ## 路由表 {#routes}
479
+
480
+ 所有路由均由協作自動掛載在`/_agent-native/collab/`下
481
+ 外掛:
482
+
483
+ | 路線 | 目的 |
484
+ | ----------------------------- | --------------------------------------------------------- |
485
+ | `GET /:docId/state` | 完整的 Y.Doc 狀態 (base64)。接受 `?stateVector=` 進行差異 |
486
+ | `POST /:docId/update` | 應用用戶端 Yjs 更新 (base64)。預設最大 2 MB |
487
+ | `POST /:docId/text` | 應用全文替換(基於差異) |
488
+ | `POST /:docId/search-replace` | 在 Y.XmlFragment 中進行外科手術式查找/替換 |
489
+ | `POST /:docId/json` | 將完整的 JSON 差異應用於 Y.Map/Y.Array |
490
+ | `GET /:docId/json` | 讀取目前JSON狀態 |
491
+ | `POST /:docId/patch` | 應用手術 JSON 補丁操作(更新插入/刪除/重新排序) |
492
+ | `POST /:docId/awareness` | 同步光標/存在狀態 |
493
+ | `GET /:docId/users` | 列出檔案上的活躍使用者 |
494
+
495
+ ## 傳輸和性能 {#transport}
496
+
497
+ | 財產 | 值 |
498
+ | -------------------- | -------------------------------------------- |
499
+ | 更新去抖 | ~80 ms(通過 `Y.mergeUpdates` 合並快速擊鍵) |
500
+ | 輪詢間隔(無 SSE) | 2秒(可通過`pollInterval`設定) |
501
+ | 輪詢間隔(SSE 健康) | ~12秒(可通過`pollIntervalWithSse`設定) |
502
+ | 狀態向量獲取頻率 | 重新連線、環形緩衝區間隙或每 15 個輪詢週期時 |
503
+ | 出錯時退避 | 帶抖動的指數,上限約為 15 秒 |
504
+ | 最大有效負載(寫入) | 預設 2 MB,可通過 `maxPayloadBytes` 設定 |
505
+ | 壓縮閾值 | 存儲的 blob > 4× 新編碼觸發墓碑緊湊 |
506
+ | 每次寫入資料庫讀取 | 1(僅在`persistMergedState`內部讀取CAS版本) |
507
+
508
+ ## 安全 {#security}
509
+
510
+ ### 始終設定 `resourceType`
511
+
512
+ ```ts
513
+ createCollabPlugin({
514
+ resourceType: "document", // the name passed to registerShareableResource
515
+ });
516
+ ```
517
+
518
+ 如果沒有 `resourceType`,外掛會紀錄警告並廣播協作推送
519
+ 部署中所有經過驗證的使用者的事件,無檔案級別
520
+ 範圍。非所有者退回到狀態向量追趕(安全但更高
521
+ 延遲),無論是否設定 `resourceType`。
522
+
523
+ ### 存取檢查
524
+
525
+ 所有協作路由都需要驗證。當 `resourceType` 設定時,讀取
526
+ 至少需要檢視者存取權限,並且寫入需要編輯者存取權限,使用
527
+ 與共用系統相同的 `resolveAccess` / `assertAccess` 幫助程序。 404
528
+ (不是 403)在存取失敗時返回,以避免泄漏檔案存在。
529
+
530
+ ### 有效負載限制
531
+
532
+ 寫入路由(`update`、`text`、`json`、`patch`、`search-replace`)拒絕
533
+ 有效負載超出 HTTP 413 設定的限制。預設值為 2 MB。
534
+ 覆蓋每個外掛:
535
+
536
+ ```ts
537
+ createCollabPlugin({
538
+ resourceType: "document",
539
+ maxPayloadBytes: 512 * 1024, // 512 KB
540
+ });
541
+ ```
542
+
543
+ ### 意識範圍
544
+
545
+ 意識路線(`POST /awareness`、`GET /users`)由相同的門控
546
+ 讀取時進行存取檢查 - 缺乏檢視者存取權限的使用者無法了解其他人
547
+ 正在編輯檔案。
548
+
549
+ ## 模式 {#patterns}
550
+
551
+ ### 結構化資料的粒度伺服器端合並
552
+
553
+ 對於結構化檔案(幻燈片、表單建置器、設計檔案),Yjs
554
+ 當兩個代理或使用者重寫相同的主體協作模型時,可能會發生衝突
555
+ 頂級紀錄同時進行。更安全的模式是**粒度伺服器端
556
+ merge**:定義一個接受一組目標操作的操作,並且
557
+ 以原子方式應用它們,因此對不同專案的並發編輯都可以保留。
558
+
559
+ **幻燈片 (`patch-deck`)** — 而不是每次更換整個牌組 JSON
560
+ 更改,該操作接受每張幻燈片的操作:
561
+
562
+ ```ts
563
+ // Conceptual patch-deck action shape
564
+ type PatchDeckOp =
565
+ | { type: "patch"; slideId: string; fields: Partial<SlideFields> }
566
+ | { type: "add"; position: number; slide: SlideData }
567
+ | { type: "delete"; slideId: string }
568
+ | { type: "reorder"; slideId: string; newIndex: number };
569
+ ```
570
+
571
+ 兩個使用者編輯不同的幻燈片均成功;
572
+ 甲板層。
573
+
574
+ **表單 (`patch-form-fields`)** — 使用更新插入/刪除/重新排序進行欄位級合並
575
+ 操作,因此對不同表單欄位的並發編輯都可以生存。
576
+
577
+ 在以下情況下使用此模式:
578
+
579
+ - 檔案是結構化的(容器內的專案)。
580
+ - 並發編輯針對不同的專案。
581
+ - 身體協作(Yjs `Y.XmlFragment`)過度殺傷或不適用。
582
+
583
+ 在以下情況下使用主體協作(Y.XmlFragment + TipTap):
584
+
585
+ - 該檔案是自由格式的富文本,可以編輯任何區域。
586
+ - 游標級 CRDT 合並很重要。
587
+
588
+ ### 協作撤消範圍(Y.UndoManager)
589
+
590
+ 設計範本使用 `Y.UndoManager` 將撤消/重做範圍限制為本機
591
+ 使用者自己的編輯。遠端對等編輯和代理編輯永遠不會被撤消
592
+ 使用者的 Cmd+Z。
593
+
594
+ ```ts
595
+ import * as Y from "yjs";
596
+
597
+ const LOCAL_EDIT_ORIGIN = "local";
598
+
599
+ const undoManager = new Y.UndoManager(ydoc.getText("content"), {
600
+ trackedOrigins: new Set([LOCAL_EDIT_ORIGIN]),
601
+ captureTimeout: 800, // coalesce rapid slider drags into one undo step
602
+ });
603
+
604
+ // Wrap local edits with the tracked origin
605
+ ydoc.transact(() => {
606
+ // apply local style change
607
+ }, LOCAL_EDIT_ORIGIN);
608
+
609
+ // Undo/redo — only reverses LOCAL_EDIT_ORIGIN transactions
610
+ undoManager.undo(); // Cmd+Z
611
+ undoManager.redo(); // Shift+Cmd+Z
612
+ ```
613
+
614
+ 關鍵屬性:
615
+
616
+ - `trackedOrigins` 必須是 `Set`。僅具有匹配來源的 transactions
617
+ 在撤消堆堆疊中捕獲。
618
+ - 遠端更新(來源 `"remote"`)和代理更新(來源 `"agent"`)
619
+ 從未被捕獲。
620
+ - 當活動檔案發生變化時,重新建立並處置管理器;陳舊
621
+ 經理擁有可以無限增長的參考資料。
622
+
623
+ ## 已知限制 {#limitations}
624
+
625
+ ```an-callout
626
+ {
627
+ "tone": "risk",
628
+ "body": "**同一區域同時重寫是最後寫入獲勝。**如果代理重寫了一個段落,而人類在“完全相同的區域”中有未儲存的編輯,則主要用戶端快照可能會破壞正在進行的人類編輯。不同區域中的編輯始終通過 CRDT 幹淨地合並。對於結構化檔案,請使用粒度伺服器端合並來完全避免這種情況。"
629
+ }
630
+ ```
631
+
632
+ - **同區域同時重寫為 LWW** — 如果代理重寫了
633
+ 段落和人類在完全相同的區域中有未儲存的編輯,
634
+ 主要客戶快照可以覆蓋人類正在進行的更改。編輯
635
+ 不同區域通過 CRDT 正確合並。細粒度伺服器端合並
636
+ (見上文)避免了結構化檔案的這種情況。
637
+ - **無伺服器上的進程內寫入鎖** — `_writeLocks` 對應為
638
+ 進程本機。並發請求登陸不同的Serverless
639
+ 調用在 SQL CAS 層(樂觀並發)序列化
640
+ 比內存鎖。這是安全的,但意味著高吞吐量場景
641
+ 無伺服器可能會看到更多 CAS 重試。
642
+ - **感知是針對每個進程的** — 感知內存存儲是
643
+ 進程本機。無伺服器/多進程部署看到部分感知
644
+ 每次調用的狀態。客戶仍然會收到每個的完整認知快照
645
+ 輪詢週期,因此狀態指示器會在一個輪詢間隔內更新。
646
+
647
+ ## 存在 {#presence}
648
+
649
+ `useCollaborativeDoc` 鉤子返回:
650
+
651
+ - `activeUsers` — 所有對等點的 `CollabUser` 陣列(姓名、電子郵件、顏色)
652
+ 目前在檔案中(來自意識)。
653
+ - `agentActive` - 代理進行編輯後短暫的 `true`(用於
654
+ 瞬態視覺指示器)。
655
+ - `agentPresent` - `true`,而代理具有主動感知條目
656
+ (持久存在心跳)。
657
+
658
+ Use `emailToColor(email)` and `emailToName(email)` from
659
+ `@agent-native/core/client` 生成一致的光標顏色和顯示
660
+ 電子郵件地址中的姓名。
661
+
662
+ 使用 `activeUsers` 渲染的 `PresenceBar` 顯示活人和特工
663
+ 合作者。每張幻燈片的存在(哪些使用者正在檢視給定的幻燈片)
664
+ 同一意識狀態之上的層。
665
+
666
+ ## 相關檔案 {#related}
667
+
668
+ - [Real-Time Sync](/docs/client#usedbsync) — `useDbSync` + `useChangeVersion`
669
+ 提供 `updatedAt` 碰撞驅動編輯器協調的系統。
670
+ - [Security](/docs/security) — `registerShareableResource`, `resolveAccess`,
671
+ 和`assertAccess`為`resourceType`引用的存取模型。
672
+ - [Sharing](/docs/sharing) — 如何共用檔案以及如何授予存取權限。
673
+ - [Template: Content](/docs/template-content) — 參考實現
674
+ 協作富文本編輯。
675
+ - [Template: Slides](/docs/template-slides) — 精細的 `patch-deck` 操作
676
+ 結構化並發編輯。
677
+ - [Template: Forms](/docs/template-forms) — 欄位級 `patch-form-fields`
678
+ 伺服器端合並。
679
+ - [Template: Design](/docs/template-design) — `Y.UndoManager` 撤消/重做範圍
680
+ 本機使用者編輯。