studiograph 1.3.47 → 1.3.48-beta.1

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 (1067) hide show
  1. package/README.md +26 -16
  2. package/dist/agent/agent-pool.d.ts +117 -0
  3. package/dist/agent/agent-pool.js +287 -0
  4. package/dist/agent/agent-pool.js.map +1 -0
  5. package/dist/agent/followups.d.ts +34 -0
  6. package/dist/agent/followups.js +52 -0
  7. package/dist/agent/followups.js.map +1 -0
  8. package/dist/agent/orchestrator.d.ts +113 -22
  9. package/dist/agent/orchestrator.js +573 -181
  10. package/dist/agent/orchestrator.js.map +1 -1
  11. package/dist/agent/prompts/entity-types-section.d.ts +36 -0
  12. package/dist/agent/prompts/entity-types-section.js +90 -0
  13. package/dist/agent/prompts/entity-types-section.js.map +1 -0
  14. package/dist/agent/prompts/system.md +148 -69
  15. package/dist/agent/skill-loader.d.ts +30 -17
  16. package/dist/agent/skill-loader.js +63 -30
  17. package/dist/agent/skill-loader.js.map +1 -1
  18. package/dist/agent/skills/entity-schema.md +77 -433
  19. package/dist/agent/skills/interview/entity-templates.md +193 -0
  20. package/dist/agent/skills/interview/question-domains.md +391 -0
  21. package/dist/agent/skills/interview/skill.md +204 -0
  22. package/dist/agent/skills/schema-rules.md +54 -0
  23. package/dist/agent/tools/capture-tools.d.ts +31 -0
  24. package/dist/agent/tools/capture-tools.js +40 -0
  25. package/dist/agent/tools/capture-tools.js.map +1 -0
  26. package/dist/agent/tools/folder-tools.d.ts +47 -0
  27. package/dist/agent/tools/folder-tools.js +249 -0
  28. package/dist/agent/tools/folder-tools.js.map +1 -0
  29. package/dist/agent/tools/fs-tools.d.ts +7 -6
  30. package/dist/agent/tools/fs-tools.js +5 -4
  31. package/dist/agent/tools/fs-tools.js.map +1 -1
  32. package/dist/agent/tools/graph-tools.d.ts +21 -58
  33. package/dist/agent/tools/graph-tools.js +635 -332
  34. package/dist/agent/tools/graph-tools.js.map +1 -1
  35. package/dist/agent/tools/history-tools.d.ts +95 -0
  36. package/dist/agent/tools/history-tools.js +461 -0
  37. package/dist/agent/tools/history-tools.js.map +1 -0
  38. package/dist/agent/tools/load-skill.d.ts +6 -5
  39. package/dist/agent/tools/load-skill.js +3 -3
  40. package/dist/agent/tools/load-skill.js.map +1 -1
  41. package/dist/agent/tools/ops-tools.d.ts +5 -4
  42. package/dist/agent/tools/ops-tools.js +130 -236
  43. package/dist/agent/tools/ops-tools.js.map +1 -1
  44. package/dist/agent/tools/permission-tools.d.ts +87 -17
  45. package/dist/agent/tools/permission-tools.js +233 -38
  46. package/dist/agent/tools/permission-tools.js.map +1 -1
  47. package/dist/agent/tools/tool-loader.js +5 -4
  48. package/dist/agent/tools/tool-loader.js.map +1 -1
  49. package/dist/agent/tools/web-tools.d.ts +18 -0
  50. package/dist/agent/tools/web-tools.js +283 -0
  51. package/dist/agent/tools/web-tools.js.map +1 -0
  52. package/dist/cli/commands/about.d.ts +1 -0
  53. package/dist/cli/commands/about.js +55 -3
  54. package/dist/cli/commands/about.js.map +1 -1
  55. package/dist/cli/commands/admin/audit-workspace.d.ts +23 -0
  56. package/dist/cli/commands/admin/audit-workspace.js +133 -0
  57. package/dist/cli/commands/admin/audit-workspace.js.map +1 -0
  58. package/dist/cli/commands/admin/audit.d.ts +21 -0
  59. package/dist/cli/commands/admin/audit.js +174 -0
  60. package/dist/cli/commands/admin/audit.js.map +1 -0
  61. package/dist/cli/commands/admin/backup.d.ts +54 -0
  62. package/dist/cli/commands/admin/backup.js +207 -0
  63. package/dist/cli/commands/admin/backup.js.map +1 -0
  64. package/dist/cli/commands/admin/folder.d.ts +11 -0
  65. package/dist/cli/commands/admin/folder.js +186 -0
  66. package/dist/cli/commands/admin/folder.js.map +1 -0
  67. package/dist/cli/commands/admin/index.d.ts +16 -0
  68. package/dist/cli/commands/admin/index.js +46 -0
  69. package/dist/cli/commands/admin/index.js.map +1 -0
  70. package/dist/cli/commands/admin/migrate-assets.d.ts +53 -0
  71. package/dist/cli/commands/admin/migrate-assets.js +184 -0
  72. package/dist/cli/commands/admin/migrate-assets.js.map +1 -0
  73. package/dist/cli/commands/admin/migrate.d.ts +56 -0
  74. package/dist/cli/commands/admin/migrate.js +263 -0
  75. package/dist/cli/commands/admin/migrate.js.map +1 -0
  76. package/dist/cli/commands/admin/restore.d.ts +24 -0
  77. package/dist/cli/commands/admin/restore.js +228 -0
  78. package/dist/cli/commands/admin/restore.js.map +1 -0
  79. package/dist/cli/commands/admin/secrets.d.ts +23 -0
  80. package/dist/cli/commands/admin/secrets.js +256 -0
  81. package/dist/cli/commands/admin/secrets.js.map +1 -0
  82. package/dist/cli/commands/admin/settings.d.ts +28 -0
  83. package/dist/cli/commands/admin/settings.js +284 -0
  84. package/dist/cli/commands/admin/settings.js.map +1 -0
  85. package/dist/cli/commands/admin/token.d.ts +42 -0
  86. package/dist/cli/commands/admin/token.js +126 -0
  87. package/dist/cli/commands/admin/token.js.map +1 -0
  88. package/dist/cli/commands/admin/transfer-ownership.d.ts +15 -0
  89. package/dist/cli/commands/admin/transfer-ownership.js +106 -0
  90. package/dist/cli/commands/admin/transfer-ownership.js.map +1 -0
  91. package/dist/cli/commands/admin/user.d.ts +11 -0
  92. package/dist/cli/commands/admin/user.js +187 -0
  93. package/dist/cli/commands/admin/user.js.map +1 -0
  94. package/dist/cli/commands/clone.d.ts +25 -3
  95. package/dist/cli/commands/clone.js +142 -36
  96. package/dist/cli/commands/clone.js.map +1 -1
  97. package/dist/cli/commands/commit.d.ts +1 -1
  98. package/dist/cli/commands/commit.js +24 -11
  99. package/dist/cli/commands/commit.js.map +1 -1
  100. package/dist/cli/commands/config.d.ts +23 -107
  101. package/dist/cli/commands/config.js +52 -260
  102. package/dist/cli/commands/config.js.map +1 -1
  103. package/dist/cli/commands/connector.d.ts +10 -13
  104. package/dist/cli/commands/connector.js +16 -58
  105. package/dist/cli/commands/connector.js.map +1 -1
  106. package/dist/cli/commands/deploy.js +215 -68
  107. package/dist/cli/commands/deploy.js.map +1 -1
  108. package/dist/cli/commands/index.js +2 -2
  109. package/dist/cli/commands/index.js.map +1 -1
  110. package/dist/cli/commands/init.js +10 -30
  111. package/dist/cli/commands/init.js.map +1 -1
  112. package/dist/cli/commands/mcp.js +12 -4
  113. package/dist/cli/commands/mcp.js.map +1 -1
  114. package/dist/cli/commands/orphans.js +14 -30
  115. package/dist/cli/commands/orphans.js.map +1 -1
  116. package/dist/cli/commands/r2.d.ts +3 -0
  117. package/dist/cli/commands/r2.js +223 -204
  118. package/dist/cli/commands/r2.js.map +1 -1
  119. package/dist/cli/commands/redeploy.js +65 -12
  120. package/dist/cli/commands/redeploy.js.map +1 -1
  121. package/dist/cli/commands/reset.d.ts +22 -6
  122. package/dist/cli/commands/reset.js +142 -63
  123. package/dist/cli/commands/reset.js.map +1 -1
  124. package/dist/cli/commands/serve.js +209 -24
  125. package/dist/cli/commands/serve.js.map +1 -1
  126. package/dist/cli/commands/sync.d.ts +1 -1
  127. package/dist/cli/commands/sync.js +372 -202
  128. package/dist/cli/commands/sync.js.map +1 -1
  129. package/dist/cli/crypto-bundle.d.ts +39 -0
  130. package/dist/cli/crypto-bundle.js +94 -0
  131. package/dist/cli/crypto-bundle.js.map +1 -0
  132. package/dist/cli/index.js +24 -35
  133. package/dist/cli/index.js.map +1 -1
  134. package/dist/cli/railway-pin.d.ts +68 -0
  135. package/dist/cli/railway-pin.js +96 -0
  136. package/dist/cli/railway-pin.js.map +1 -0
  137. package/dist/cli/railway-provisioning.d.ts +53 -0
  138. package/dist/cli/railway-provisioning.js +85 -0
  139. package/dist/cli/railway-provisioning.js.map +1 -0
  140. package/dist/cli/setup-wizard.d.ts +33 -52
  141. package/dist/cli/setup-wizard.js +43 -68
  142. package/dist/cli/setup-wizard.js.map +1 -1
  143. package/dist/core/accent-palette.d.ts +22 -0
  144. package/dist/core/accent-palette.js +47 -0
  145. package/dist/core/accent-palette.js.map +1 -0
  146. package/dist/core/cell-anchor.d.ts +29 -0
  147. package/dist/core/cell-anchor.js +53 -0
  148. package/dist/core/cell-anchor.js.map +1 -0
  149. package/dist/core/comment-anchor.d.ts +41 -0
  150. package/dist/core/comment-anchor.js +147 -0
  151. package/dist/core/comment-anchor.js.map +1 -0
  152. package/dist/core/commit-messages.d.ts +57 -0
  153. package/dist/core/commit-messages.js +85 -0
  154. package/dist/core/commit-messages.js.map +1 -0
  155. package/dist/core/embeds.d.ts +56 -0
  156. package/dist/core/embeds.js +103 -0
  157. package/dist/core/embeds.js.map +1 -0
  158. package/dist/core/entity-body-templates.d.ts +21 -0
  159. package/dist/core/entity-body-templates.js +53 -0
  160. package/dist/core/entity-body-templates.js.map +1 -0
  161. package/dist/core/entity-types-catalog.d.ts +65 -0
  162. package/dist/core/entity-types-catalog.js +140 -0
  163. package/dist/core/entity-types-catalog.js.map +1 -0
  164. package/dist/core/folder-paths.d.ts +41 -0
  165. package/dist/core/folder-paths.js +95 -0
  166. package/dist/core/folder-paths.js.map +1 -0
  167. package/dist/core/folder-sidecar.d.ts +36 -0
  168. package/dist/core/folder-sidecar.js +91 -0
  169. package/dist/core/folder-sidecar.js.map +1 -0
  170. package/dist/core/graph.d.ts +675 -14
  171. package/dist/core/graph.js +2118 -314
  172. package/dist/core/graph.js.map +1 -1
  173. package/dist/core/history-diff.d.ts +35 -0
  174. package/dist/core/history-diff.js +114 -0
  175. package/dist/core/history-diff.js.map +1 -0
  176. package/dist/core/schema-registry.d.ts +59 -0
  177. package/dist/core/schema-registry.js +198 -0
  178. package/dist/core/schema-registry.js.map +1 -1
  179. package/dist/core/schemas/connector.d.ts +67 -0
  180. package/dist/core/schemas/connector.js +100 -0
  181. package/dist/core/schemas/connector.js.map +1 -0
  182. package/dist/core/schemas/workspace.d.ts +122 -0
  183. package/dist/core/schemas/workspace.js +211 -0
  184. package/dist/core/schemas/workspace.js.map +1 -0
  185. package/dist/core/secrets/SecretStore.d.ts +77 -0
  186. package/dist/core/secrets/SecretStore.js +13 -0
  187. package/dist/core/secrets/SecretStore.js.map +1 -0
  188. package/dist/core/secrets/SettingsResolver.d.ts +54 -0
  189. package/dist/core/secrets/SettingsResolver.js +80 -0
  190. package/dist/core/secrets/SettingsResolver.js.map +1 -0
  191. package/dist/core/secrets/SettingsStore.d.ts +30 -0
  192. package/dist/core/secrets/SettingsStore.js +9 -0
  193. package/dist/core/secrets/SettingsStore.js.map +1 -0
  194. package/dist/core/secrets/SqliteEncryptedStore.d.ts +90 -0
  195. package/dist/core/secrets/SqliteEncryptedStore.js +598 -0
  196. package/dist/core/secrets/SqliteEncryptedStore.js.map +1 -0
  197. package/dist/core/secrets/audit.d.ts +36 -0
  198. package/dist/core/secrets/audit.js +60 -0
  199. package/dist/core/secrets/audit.js.map +1 -0
  200. package/dist/core/secrets/auth-db-migration.d.ts +129 -0
  201. package/dist/core/secrets/auth-db-migration.js +653 -0
  202. package/dist/core/secrets/auth-db-migration.js.map +1 -0
  203. package/dist/core/secrets/bundle.d.ts +141 -0
  204. package/dist/core/secrets/bundle.js +435 -0
  205. package/dist/core/secrets/bundle.js.map +1 -0
  206. package/dist/core/secrets/dual-write.d.ts +81 -0
  207. package/dist/core/secrets/dual-write.js +247 -0
  208. package/dist/core/secrets/dual-write.js.map +1 -0
  209. package/dist/core/secrets/encryption.d.ts +44 -0
  210. package/dist/core/secrets/encryption.js +97 -0
  211. package/dist/core/secrets/encryption.js.map +1 -0
  212. package/dist/core/secrets/index.d.ts +49 -0
  213. package/dist/core/secrets/index.js +74 -0
  214. package/dist/core/secrets/index.js.map +1 -0
  215. package/dist/core/secrets/master-key.d.ts +38 -0
  216. package/dist/core/secrets/master-key.js +122 -0
  217. package/dist/core/secrets/master-key.js.map +1 -0
  218. package/dist/core/secrets/probes/anthropic.d.ts +98 -0
  219. package/dist/core/secrets/probes/anthropic.js +300 -0
  220. package/dist/core/secrets/probes/anthropic.js.map +1 -0
  221. package/dist/core/secrets/probes/brave.d.ts +9 -0
  222. package/dist/core/secrets/probes/brave.js +15 -0
  223. package/dist/core/secrets/probes/brave.js.map +1 -0
  224. package/dist/core/secrets/probes/r2.d.ts +15 -0
  225. package/dist/core/secrets/probes/r2.js +14 -0
  226. package/dist/core/secrets/probes/r2.js.map +1 -0
  227. package/dist/core/secrets/probes/voyage.d.ts +13 -0
  228. package/dist/core/secrets/probes/voyage.js +52 -0
  229. package/dist/core/secrets/probes/voyage.js.map +1 -0
  230. package/dist/core/secrets/r2-structural-migration.d.ts +39 -0
  231. package/dist/core/secrets/r2-structural-migration.js +109 -0
  232. package/dist/core/secrets/r2-structural-migration.js.map +1 -0
  233. package/dist/core/secrets/read-flip.d.ts +59 -0
  234. package/dist/core/secrets/read-flip.js +87 -0
  235. package/dist/core/secrets/read-flip.js.map +1 -0
  236. package/dist/core/secrets/registry.d.ts +188 -0
  237. package/dist/core/secrets/registry.js +598 -0
  238. package/dist/core/secrets/registry.js.map +1 -0
  239. package/dist/core/types.d.ts +77 -455
  240. package/dist/core/types.js +17 -3
  241. package/dist/core/types.js.map +1 -1
  242. package/dist/core/user-config.d.ts +75 -7
  243. package/dist/core/user-config.js +155 -7
  244. package/dist/core/user-config.js.map +1 -1
  245. package/dist/core/validation.d.ts +717 -1791
  246. package/dist/core/validation.js +357 -228
  247. package/dist/core/validation.js.map +1 -1
  248. package/dist/core/workspace-manager.d.ts +79 -12
  249. package/dist/core/workspace-manager.js +213 -73
  250. package/dist/core/workspace-manager.js.map +1 -1
  251. package/dist/core/workspace.d.ts +19 -5
  252. package/dist/core/workspace.js +69 -35
  253. package/dist/core/workspace.js.map +1 -1
  254. package/dist/mcp/comment-virtual-entity.d.ts +36 -0
  255. package/dist/mcp/comment-virtual-entity.js +71 -0
  256. package/dist/mcp/comment-virtual-entity.js.map +1 -0
  257. package/dist/mcp/connector-manager.d.ts +94 -13
  258. package/dist/mcp/connector-manager.js +283 -62
  259. package/dist/mcp/connector-manager.js.map +1 -1
  260. package/dist/mcp/oauth-provider.d.ts +27 -33
  261. package/dist/mcp/oauth-provider.js +65 -134
  262. package/dist/mcp/oauth-provider.js.map +1 -1
  263. package/dist/mcp/oauth-registry.d.ts +62 -0
  264. package/dist/mcp/oauth-registry.js +85 -0
  265. package/dist/mcp/oauth-registry.js.map +1 -0
  266. package/dist/mcp/server.d.ts +11 -3
  267. package/dist/mcp/server.js +30 -5
  268. package/dist/mcp/server.js.map +1 -1
  269. package/dist/mcp/state-signer.d.ts +41 -0
  270. package/dist/mcp/state-signer.js +120 -0
  271. package/dist/mcp/state-signer.js.map +1 -0
  272. package/dist/mcp/tools.d.ts +35 -2
  273. package/dist/mcp/tools.js +1051 -117
  274. package/dist/mcp/tools.js.map +1 -1
  275. package/dist/server/__tests__/helpers/graph-api.d.ts +18 -0
  276. package/dist/server/__tests__/helpers/graph-api.js +16 -0
  277. package/dist/server/__tests__/helpers/graph-api.js.map +1 -0
  278. package/dist/server/body-write-coordinator.d.ts +151 -0
  279. package/dist/server/body-write-coordinator.js +161 -0
  280. package/dist/server/body-write-coordinator.js.map +1 -0
  281. package/dist/server/cloud-billing-flow.d.ts +32 -0
  282. package/dist/server/cloud-billing-flow.js +75 -0
  283. package/dist/server/cloud-billing-flow.js.map +1 -0
  284. package/dist/server/commit-audit.d.ts +26 -0
  285. package/dist/server/commit-audit.js +30 -0
  286. package/dist/server/commit-audit.js.map +1 -0
  287. package/dist/server/index.d.ts +14 -3
  288. package/dist/server/index.js +451 -193
  289. package/dist/server/index.js.map +1 -1
  290. package/dist/server/middleware/sanitize.d.ts +46 -0
  291. package/dist/server/middleware/sanitize.js +171 -0
  292. package/dist/server/middleware/sanitize.js.map +1 -0
  293. package/dist/server/routes/asset-api.d.ts +10 -0
  294. package/dist/server/routes/asset-api.js +294 -0
  295. package/dist/server/routes/asset-api.js.map +1 -0
  296. package/dist/server/routes/audit-api.d.ts +24 -0
  297. package/dist/server/routes/audit-api.js +117 -0
  298. package/dist/server/routes/audit-api.js.map +1 -0
  299. package/dist/server/routes/auth-api.d.ts +3 -2
  300. package/dist/server/routes/auth-api.js +519 -38
  301. package/dist/server/routes/auth-api.js.map +1 -1
  302. package/dist/server/routes/capture-api.d.ts +18 -0
  303. package/dist/server/routes/capture-api.js +257 -0
  304. package/dist/server/routes/capture-api.js.map +1 -0
  305. package/dist/server/routes/chat.d.ts +4 -1
  306. package/dist/server/routes/chat.js +298 -88
  307. package/dist/server/routes/chat.js.map +1 -1
  308. package/dist/server/routes/comments-api.d.ts +15 -0
  309. package/dist/server/routes/comments-api.js +444 -0
  310. package/dist/server/routes/comments-api.js.map +1 -0
  311. package/dist/server/routes/config-api.d.ts +21 -0
  312. package/dist/server/routes/config-api.js +256 -0
  313. package/dist/server/routes/config-api.js.map +1 -0
  314. package/dist/server/routes/connectors-api.d.ts +17 -0
  315. package/dist/server/routes/connectors-api.js +410 -0
  316. package/dist/server/routes/connectors-api.js.map +1 -0
  317. package/dist/server/routes/event-ingest-api.d.ts +15 -0
  318. package/dist/server/routes/event-ingest-api.js +125 -0
  319. package/dist/server/routes/event-ingest-api.js.map +1 -0
  320. package/dist/server/routes/git-http.d.ts +3 -3
  321. package/dist/server/routes/git-http.js +86 -38
  322. package/dist/server/routes/git-http.js.map +1 -1
  323. package/dist/server/routes/graph-api-access.d.ts +35 -0
  324. package/dist/server/routes/graph-api-access.js +105 -0
  325. package/dist/server/routes/graph-api-access.js.map +1 -0
  326. package/dist/server/routes/graph-api.d.ts +3 -2
  327. package/dist/server/routes/graph-api.js +1321 -263
  328. package/dist/server/routes/graph-api.js.map +1 -1
  329. package/dist/server/routes/health.d.ts +18 -0
  330. package/dist/server/routes/health.js +74 -0
  331. package/dist/server/routes/health.js.map +1 -0
  332. package/dist/server/routes/insights-api.d.ts +1 -2
  333. package/dist/server/routes/insights-api.js +149 -41
  334. package/dist/server/routes/insights-api.js.map +1 -1
  335. package/dist/server/routes/mcp.d.ts +7 -3
  336. package/dist/server/routes/mcp.js +22 -6
  337. package/dist/server/routes/mcp.js.map +1 -1
  338. package/dist/server/routes/permissions-api.d.ts +9 -2
  339. package/dist/server/routes/permissions-api.js +87 -30
  340. package/dist/server/routes/permissions-api.js.map +1 -1
  341. package/dist/server/routes/r2-api.d.ts +25 -0
  342. package/dist/server/routes/r2-api.js +276 -0
  343. package/dist/server/routes/r2-api.js.map +1 -0
  344. package/dist/server/routes/secrets-api.d.ts +36 -0
  345. package/dist/server/routes/secrets-api.js +308 -0
  346. package/dist/server/routes/secrets-api.js.map +1 -0
  347. package/dist/server/routes/settings-api.d.ts +29 -0
  348. package/dist/server/routes/settings-api.js +180 -0
  349. package/dist/server/routes/settings-api.js.map +1 -0
  350. package/dist/server/routes/url-api.d.ts +7 -0
  351. package/dist/server/routes/url-api.js +74 -0
  352. package/dist/server/routes/url-api.js.map +1 -0
  353. package/dist/server/routes/views-api.js +81 -7
  354. package/dist/server/routes/views-api.js.map +1 -1
  355. package/dist/server/routes/workspace-api.d.ts +2 -1
  356. package/dist/server/routes/workspace-api.js +124 -35
  357. package/dist/server/routes/workspace-api.js.map +1 -1
  358. package/dist/server/routes/ws.d.ts +2 -1
  359. package/dist/server/routes/ws.js +64 -16
  360. package/dist/server/routes/ws.js.map +1 -1
  361. package/dist/server/session-manager.d.ts +48 -5
  362. package/dist/server/session-manager.js +182 -15
  363. package/dist/server/session-manager.js.map +1 -1
  364. package/dist/server/ws-hub.d.ts +138 -14
  365. package/dist/server/ws-hub.js +0 -0
  366. package/dist/server/ws-hub.js.map +1 -1
  367. package/dist/server/yjs-manager.d.ts +285 -7
  368. package/dist/server/yjs-manager.js +907 -36
  369. package/dist/server/yjs-manager.js.map +1 -1
  370. package/dist/server/yjs-persistence.d.ts +165 -0
  371. package/dist/server/yjs-persistence.js +557 -0
  372. package/dist/server/yjs-persistence.js.map +1 -0
  373. package/dist/server/yjs-text-diff.d.ts +32 -0
  374. package/dist/server/yjs-text-diff.js +61 -0
  375. package/dist/server/yjs-text-diff.js.map +1 -0
  376. package/dist/services/access-control.d.ts +73 -0
  377. package/dist/services/access-control.js +146 -0
  378. package/dist/services/access-control.js.map +1 -0
  379. package/dist/services/asset-listing.d.ts +39 -0
  380. package/dist/services/asset-listing.js +125 -0
  381. package/dist/services/asset-listing.js.map +1 -0
  382. package/dist/services/asset-upload-service.d.ts +53 -0
  383. package/dist/services/asset-upload-service.js +201 -0
  384. package/dist/services/asset-upload-service.js.map +1 -0
  385. package/dist/services/assets/asset-index-service.d.ts +82 -0
  386. package/dist/services/assets/asset-index-service.js +167 -0
  387. package/dist/services/assets/asset-index-service.js.map +1 -0
  388. package/dist/services/assets/base.d.ts +44 -0
  389. package/dist/services/assets/base.js +55 -0
  390. package/dist/services/assets/base.js.map +1 -1
  391. package/dist/services/assets/index.d.ts +69 -1
  392. package/dist/services/assets/index.js +125 -0
  393. package/dist/services/assets/index.js.map +1 -1
  394. package/dist/services/assets/local.d.ts +12 -1
  395. package/dist/services/assets/local.js +100 -1
  396. package/dist/services/assets/local.js.map +1 -1
  397. package/dist/services/assets/r2-sync.d.ts +88 -0
  398. package/dist/services/assets/r2-sync.js +412 -0
  399. package/dist/services/assets/r2-sync.js.map +1 -0
  400. package/dist/services/assets/r2.d.ts +34 -1
  401. package/dist/services/assets/r2.js +93 -1
  402. package/dist/services/assets/r2.js.map +1 -1
  403. package/dist/services/auth-service.d.ts +314 -36
  404. package/dist/services/auth-service.js +1126 -139
  405. package/dist/services/auth-service.js.map +1 -1
  406. package/dist/services/bookmark-import-service.d.ts +49 -0
  407. package/dist/services/bookmark-import-service.js +250 -0
  408. package/dist/services/bookmark-import-service.js.map +1 -0
  409. package/dist/services/cloud-inference-billing.d.ts +64 -0
  410. package/dist/services/cloud-inference-billing.js +313 -0
  411. package/dist/services/cloud-inference-billing.js.map +1 -0
  412. package/dist/services/comment-service.d.ts +97 -0
  413. package/dist/services/comment-service.js +341 -0
  414. package/dist/services/comment-service.js.map +1 -0
  415. package/dist/services/csv-service.d.ts +22 -17
  416. package/dist/services/csv-service.js +55 -92
  417. package/dist/services/csv-service.js.map +1 -1
  418. package/dist/services/entity-mutations.d.ts +161 -0
  419. package/dist/services/entity-mutations.js +296 -0
  420. package/dist/services/entity-mutations.js.map +1 -0
  421. package/dist/services/event-processor.d.ts +104 -0
  422. package/dist/services/event-processor.js +441 -0
  423. package/dist/services/event-processor.js.map +1 -0
  424. package/dist/services/folder-creation.d.ts +33 -0
  425. package/dist/services/folder-creation.js +103 -0
  426. package/dist/services/folder-creation.js.map +1 -0
  427. package/dist/services/git.d.ts +54 -0
  428. package/dist/services/git.js +188 -54
  429. package/dist/services/git.js.map +1 -1
  430. package/dist/services/graph-maintenance.d.ts +42 -0
  431. package/dist/services/graph-maintenance.js +143 -0
  432. package/dist/services/graph-maintenance.js.map +1 -0
  433. package/dist/services/import-service.d.ts +45 -2
  434. package/dist/services/import-service.js +304 -100
  435. package/dist/services/import-service.js.map +1 -1
  436. package/dist/services/lint-service.js +9 -16
  437. package/dist/services/lint-service.js.map +1 -1
  438. package/dist/services/markdown.d.ts +12 -1
  439. package/dist/services/markdown.js +71 -6
  440. package/dist/services/markdown.js.map +1 -1
  441. package/dist/services/memory-service.d.ts +22 -14
  442. package/dist/services/memory-service.js +53 -35
  443. package/dist/services/memory-service.js.map +1 -1
  444. package/dist/services/mention-detector.d.ts +23 -0
  445. package/dist/services/mention-detector.js +47 -0
  446. package/dist/services/mention-detector.js.map +1 -0
  447. package/dist/services/notification-broadcast.d.ts +32 -0
  448. package/dist/services/notification-broadcast.js +38 -0
  449. package/dist/services/notification-broadcast.js.map +1 -0
  450. package/dist/services/notification-service.d.ts +41 -0
  451. package/dist/services/notification-service.js +100 -0
  452. package/dist/services/notification-service.js.map +1 -0
  453. package/dist/services/personal-folder.d.ts +40 -0
  454. package/dist/services/personal-folder.js +101 -0
  455. package/dist/services/personal-folder.js.map +1 -0
  456. package/dist/services/user-person-bridge.d.ts +118 -0
  457. package/dist/services/user-person-bridge.js +306 -0
  458. package/dist/services/user-person-bridge.js.map +1 -0
  459. package/dist/services/vector-service.d.ts +146 -6
  460. package/dist/services/vector-service.js +276 -13
  461. package/dist/services/vector-service.js.map +1 -1
  462. package/dist/services/workspace-access.d.ts +106 -0
  463. package/dist/services/workspace-access.js +149 -0
  464. package/dist/services/workspace-access.js.map +1 -0
  465. package/dist/utils/git.d.ts +17 -2
  466. package/dist/utils/git.js +23 -7
  467. package/dist/utils/git.js.map +1 -1
  468. package/dist/utils/log.d.ts +42 -0
  469. package/dist/utils/log.js +137 -0
  470. package/dist/utils/log.js.map +1 -0
  471. package/dist/utils/preflight.js +2 -2
  472. package/dist/utils/preflight.js.map +1 -1
  473. package/dist/utils/version-checker.d.ts +12 -19
  474. package/dist/utils/version-checker.js +14 -104
  475. package/dist/utils/version-checker.js.map +1 -1
  476. package/dist/web/_app/immutable/assets/0.DOumm94J.css +2 -0
  477. package/dist/web/_app/immutable/assets/13.DlIf1mKh.css +1 -0
  478. package/dist/web/_app/immutable/assets/14.7d-Q37wc.css +1 -0
  479. package/dist/web/_app/immutable/assets/15.CmLrbzZp.css +1 -0
  480. package/dist/web/_app/immutable/assets/2.BftNiAA4.css +1 -0
  481. package/dist/web/_app/immutable/assets/3.CV0abekd.css +1 -0
  482. package/dist/web/_app/immutable/assets/4.BgXzUTTk.css +1 -0
  483. package/dist/web/_app/immutable/assets/9.gsF-Ne6_.css +1 -0
  484. package/dist/web/_app/immutable/assets/AgentOverlay.CpvH9rhf.css +1 -0
  485. package/dist/web/_app/immutable/assets/AssetManagerModal.BKJfPAPk.css +1 -0
  486. package/dist/web/_app/immutable/assets/CalendarView.bNewSxkH.css +1 -0
  487. package/dist/web/_app/immutable/assets/ChevronDown.Bz0FjM7b.css +1 -0
  488. package/dist/web/_app/immutable/assets/FolderMembersPanel.DX1oBeF_.css +1 -0
  489. package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
  490. package/dist/web/_app/immutable/assets/FolderPicker.B5KdvRYl.css +1 -0
  491. package/dist/web/_app/immutable/assets/GalleryView.DgvSjS0I.css +1 -0
  492. package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
  493. package/dist/web/_app/immutable/assets/KanbanView.D0QbZFd6.css +1 -0
  494. package/dist/web/_app/immutable/assets/SettingsDialog.DYWYMFSO.css +1 -0
  495. package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
  496. package/dist/web/_app/immutable/assets/StopFilledAlt.CkPrHdPD.css +1 -0
  497. package/dist/web/_app/immutable/assets/TimelineView.DA-H6dvv.css +1 -0
  498. package/dist/web/_app/immutable/assets/WorkspaceView.BS1ildu7.css +1 -0
  499. package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
  500. package/dist/web/_app/immutable/assets/formatting.vV0ne105.css +1 -0
  501. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.CvHOgSBP.woff +0 -0
  502. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.DMJ8VG8y.woff2 +0 -0
  503. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.CB9ihrfo.woff +0 -0
  504. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.DSY6xOcd.woff2 +0 -0
  505. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CZTNEAuW.woff2 +0 -0
  506. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CsGl1sm0.woff +0 -0
  507. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CDDApCn2.woff2 +0 -0
  508. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CYLoc0-x.woff +0 -0
  509. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.BNK2_mGO.woff2 +0 -0
  510. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.DpEwFAQM.woff +0 -0
  511. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.6ng42L7E.woff2 +0 -0
  512. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.BgVn5rGT.woff +0 -0
  513. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.Cu4Hd6ag.woff +0 -0
  514. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.CuJfVYMP.woff2 +0 -0
  515. package/dist/web/_app/immutable/assets/inline-list.cqga56xT.css +1 -0
  516. package/dist/web/_app/immutable/assets/list-columns.BrRrAiZ7.css +1 -0
  517. package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
  518. package/dist/web/_app/immutable/assets/sheet.DJPuqnTg.css +1 -0
  519. package/dist/web/_app/immutable/assets/speech-dictation.C5CYFhS1.css +1 -0
  520. package/dist/web/_app/immutable/chunks/0edH8sO82.js +1 -0
  521. package/dist/web/_app/immutable/chunks/0iDDDyaZ.js +1 -0
  522. package/dist/web/_app/immutable/chunks/7-y0CE1z.js +1 -0
  523. package/dist/web/_app/immutable/chunks/7Bu427my2.js +184 -0
  524. package/dist/web/_app/immutable/chunks/B-V5eMSw2.js +1 -0
  525. package/dist/web/_app/immutable/chunks/B-i9_YVM.js +1 -0
  526. package/dist/web/_app/immutable/chunks/B15-kvCe.js +1 -0
  527. package/dist/web/_app/immutable/chunks/B4cFqqUS.js +3 -0
  528. package/dist/web/_app/immutable/chunks/B6Lt-qaJ.js +1 -0
  529. package/dist/web/_app/immutable/chunks/B7hznOQp.js +1 -0
  530. package/dist/web/_app/immutable/chunks/B7tbGyiU2.js +1 -0
  531. package/dist/web/_app/immutable/chunks/B8-Lm86o2.js +1 -0
  532. package/dist/web/_app/immutable/chunks/BBxt8lpa.js +1 -0
  533. package/dist/web/_app/immutable/chunks/BCaRi2AF.js +1 -0
  534. package/dist/web/_app/immutable/chunks/BJReLGMs.js +1 -0
  535. package/dist/web/_app/immutable/chunks/BKzV82vD2.js +83 -0
  536. package/dist/web/_app/immutable/chunks/BLHrJvbG.js +1 -0
  537. package/dist/web/_app/immutable/chunks/BQULA6er.js +4 -0
  538. package/dist/web/_app/immutable/chunks/BQW-EDgP2.js +224 -0
  539. package/dist/web/_app/immutable/chunks/BR6jMpLB.js +1 -0
  540. package/dist/web/_app/immutable/chunks/BUBMGU8t2.js +2 -0
  541. package/dist/web/_app/immutable/chunks/BVnuLlVg.js +1 -0
  542. package/dist/web/_app/immutable/chunks/BYokDzwE.js +1 -0
  543. package/dist/web/_app/immutable/chunks/B_Avv9jQ2.js +1 -0
  544. package/dist/web/_app/immutable/chunks/Bbp76jaT2.js +1 -0
  545. package/dist/web/_app/immutable/chunks/BddNmQ8j.js +1 -0
  546. package/dist/web/_app/immutable/chunks/BiJjH5mJ.js +2 -0
  547. package/dist/web/_app/immutable/chunks/BlyFGPFV.js +22 -0
  548. package/dist/web/_app/immutable/chunks/Bt88HrRx.js +1 -0
  549. package/dist/web/_app/immutable/chunks/Bu2iU6hh.js +67 -0
  550. package/dist/web/_app/immutable/chunks/Buih1pxI.js +1 -0
  551. package/dist/web/_app/immutable/chunks/BwwLJVvR.js +1 -0
  552. package/dist/web/_app/immutable/chunks/C0RpyyYZ.js +7 -0
  553. package/dist/web/_app/immutable/chunks/C2l-EXsT2.js +1 -0
  554. package/dist/web/_app/immutable/chunks/C35TIzaB.js +1 -0
  555. package/dist/web/_app/immutable/chunks/C3OdK8z_2.js +1 -0
  556. package/dist/web/_app/immutable/chunks/C6Nx0jpM.js +1 -0
  557. package/dist/web/_app/immutable/chunks/CA7O0J_u2.js +1 -0
  558. package/dist/web/_app/immutable/chunks/CAwjrHdk.js +23 -0
  559. package/dist/web/_app/immutable/chunks/CCLR-AJL2.js +185 -0
  560. package/dist/web/_app/immutable/chunks/CD0X7XPW.js +6 -0
  561. package/dist/web/_app/immutable/chunks/CDTjuBSm2.js +1 -0
  562. package/dist/web/_app/immutable/chunks/CSUrYOis.js +1 -0
  563. package/dist/web/_app/immutable/chunks/CUPSJObs.js +1 -0
  564. package/dist/web/_app/immutable/chunks/CUoGvuxK2.js +2 -0
  565. package/dist/web/_app/immutable/chunks/CWh8aehb.js +1 -0
  566. package/dist/web/_app/immutable/chunks/CY4XVBP0.js +1 -0
  567. package/dist/web/_app/immutable/chunks/CYTTTma0.js +3 -0
  568. package/dist/web/_app/immutable/chunks/CaoriuNq.js +1 -0
  569. package/dist/web/_app/immutable/chunks/CcsSt9AW2.js +1 -0
  570. package/dist/web/_app/immutable/chunks/Cd4VfAZC.js +2 -0
  571. package/dist/web/_app/immutable/chunks/CePZ1985.js +1 -0
  572. package/dist/web/_app/immutable/chunks/Cei8CKT4.js +1 -0
  573. package/dist/web/_app/immutable/chunks/CheXrbDk.js +1 -0
  574. package/dist/web/_app/immutable/chunks/CkLfUXwy.js +1 -0
  575. package/dist/web/_app/immutable/chunks/Cl-W0JYt.js +2 -0
  576. package/dist/web/_app/immutable/chunks/Cna7tYp-.js +1 -0
  577. package/dist/web/_app/immutable/chunks/Czwe4sGU2.js +3 -0
  578. package/dist/web/_app/immutable/chunks/D41CbXmM.js +1 -0
  579. package/dist/web/_app/immutable/chunks/D83_Ss42.js +1 -0
  580. package/dist/web/_app/immutable/chunks/D9NgbGbO2.js +9 -0
  581. package/dist/web/_app/immutable/chunks/DA-BuZei.js +2 -0
  582. package/dist/web/_app/immutable/chunks/DAXW5iLp.js +1 -0
  583. package/dist/web/_app/immutable/chunks/DCNJWlho2.js +1 -0
  584. package/dist/web/_app/immutable/chunks/DCtgLRl52.js +1 -0
  585. package/dist/web/_app/immutable/chunks/DH0epITQ2.js +1 -0
  586. package/dist/web/_app/immutable/chunks/DIb5rAPU2.js +1 -0
  587. package/dist/web/_app/immutable/chunks/DOmH4G9o2.js +14 -0
  588. package/dist/web/_app/immutable/chunks/DQMWa2t7.js +1 -0
  589. package/dist/web/_app/immutable/chunks/DQ_Xokap2.js +1 -0
  590. package/dist/web/_app/immutable/chunks/DR1K6PIm.js +1 -0
  591. package/dist/web/_app/immutable/chunks/DTCHhxD5.js +1 -0
  592. package/dist/web/_app/immutable/chunks/DU7XA-cL2.js +1 -0
  593. package/dist/web/_app/immutable/chunks/DVcy5Pp82.js +1 -0
  594. package/dist/web/_app/immutable/chunks/DWygwzcO2.js +1 -0
  595. package/dist/web/_app/immutable/chunks/DYXDRmoo2.js +1 -0
  596. package/dist/web/_app/immutable/chunks/DZEmjBTb.js +5 -0
  597. package/dist/web/_app/immutable/chunks/DaoOQFPb.js +1 -0
  598. package/dist/web/_app/immutable/chunks/DdfvtDOY.js +1 -0
  599. package/dist/web/_app/immutable/chunks/DevZTY1l.js +1 -0
  600. package/dist/web/_app/immutable/chunks/DiMQob8p.js +1 -0
  601. package/dist/web/_app/immutable/chunks/DiQJ9DLy.js +1 -0
  602. package/dist/web/_app/immutable/chunks/Dj5oP_ik.js +2 -0
  603. package/dist/web/_app/immutable/chunks/DjTJ4D_0.js +3 -0
  604. package/dist/web/_app/immutable/chunks/Dk4TeNwu.js +1 -0
  605. package/dist/web/_app/immutable/chunks/Dng3OcRd2.js +1 -0
  606. package/dist/web/_app/immutable/chunks/Do1OCNEG.js +1 -0
  607. package/dist/web/_app/immutable/chunks/Do6qOOng.js +1 -0
  608. package/dist/web/_app/immutable/chunks/DoQwt-f9.js +1 -0
  609. package/dist/web/_app/immutable/chunks/Dqg3k9HI2.js +1 -0
  610. package/dist/web/_app/immutable/chunks/DsnqOT222.js +1 -0
  611. package/dist/web/_app/immutable/chunks/DvJSCDuZ2.js +1 -0
  612. package/dist/web/_app/immutable/chunks/DvPuaTCl.js +5 -0
  613. package/dist/web/_app/immutable/chunks/DvYQu1SV.js +1 -0
  614. package/dist/web/_app/immutable/chunks/HdjeJPly2.js +1 -0
  615. package/dist/web/_app/immutable/chunks/JDw4tOUY.js +1 -0
  616. package/dist/web/_app/immutable/chunks/KBbDg4lS2.js +1 -0
  617. package/dist/web/_app/immutable/chunks/KQXQLJf32.js +1 -0
  618. package/dist/web/_app/immutable/chunks/LGnNalpn2.js +2 -0
  619. package/dist/web/_app/immutable/chunks/SH5Fg0Xu.js +1 -0
  620. package/dist/web/_app/immutable/chunks/Shyla9c12.js +2 -0
  621. package/dist/web/_app/immutable/chunks/VQbAelHN.js +1 -0
  622. package/dist/web/_app/immutable/chunks/apNT0aug2.js +1 -0
  623. package/dist/web/_app/immutable/chunks/e0ySQvQ6.js +1 -0
  624. package/dist/web/_app/immutable/chunks/eNB_sIHC2.js +1 -0
  625. package/dist/web/_app/immutable/chunks/g09ZrevW2.js +1 -0
  626. package/dist/web/_app/immutable/chunks/h4WWBpcD2.js +2692 -0
  627. package/dist/web/_app/immutable/chunks/kLub81jO.js +1 -0
  628. package/dist/web/_app/immutable/chunks/kW0z_eo62.js +1 -0
  629. package/dist/web/_app/immutable/chunks/oBQOivfH.js +1 -0
  630. package/dist/web/_app/immutable/chunks/ss8hcwTT.js +1 -0
  631. package/dist/web/_app/immutable/chunks/sub7ikQV.js +2 -0
  632. package/dist/web/_app/immutable/chunks/uuFM-ygL.js +1 -0
  633. package/dist/web/_app/immutable/chunks/v7me-ydg.js +2 -0
  634. package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
  635. package/dist/web/_app/immutable/chunks/yWi6xIp8.js +1 -0
  636. package/dist/web/_app/immutable/chunks/zl16E4yc2.js +1 -0
  637. package/dist/web/_app/immutable/entry/app.Bgniax9U.js +2 -0
  638. package/dist/web/_app/immutable/entry/start.DeD3x0AC.js +1 -0
  639. package/dist/web/_app/immutable/nodes/0.D7f7eDDY.js +2 -0
  640. package/dist/web/_app/immutable/nodes/1.nDAGsQWA.js +1 -0
  641. package/dist/web/_app/immutable/nodes/10.DFbhcPKT.js +1 -0
  642. package/dist/web/_app/immutable/nodes/11.CDErrkBt.js +1 -0
  643. package/dist/web/_app/immutable/nodes/12.QmphOXE2.js +1 -0
  644. package/dist/web/_app/immutable/nodes/13.Bq5rDhPs.js +1 -0
  645. package/dist/web/_app/immutable/nodes/14.BlcHqgr6.js +1 -0
  646. package/dist/web/_app/immutable/nodes/15.COK_-D-x.js +1 -0
  647. package/dist/web/_app/immutable/nodes/2.DOsCYNHa.js +109 -0
  648. package/dist/web/_app/immutable/nodes/3.BgE1sIyr.js +2 -0
  649. package/dist/web/_app/immutable/nodes/4.DvgaHeI4.js +11 -0
  650. package/dist/web/_app/immutable/nodes/5.CrjeBZES.js +1 -0
  651. package/dist/web/_app/immutable/nodes/6.DoHxsiEE.js +1 -0
  652. package/dist/web/_app/immutable/nodes/7.04fnxKIo.js +1 -0
  653. package/dist/web/_app/immutable/nodes/8.D35_cY6C.js +1 -0
  654. package/dist/web/_app/immutable/nodes/9.BRionwW6.js +1 -0
  655. package/dist/web/_app/version.json +1 -1
  656. package/dist/web/favicon-16.png +0 -0
  657. package/dist/web/favicon-180.png +0 -0
  658. package/dist/web/favicon-32.png +0 -0
  659. package/dist/web/favicon-48.png +0 -0
  660. package/dist/web/favicon-512.png +0 -0
  661. package/dist/web/favicon.ico +0 -0
  662. package/dist/web/favicon.svg +8 -0
  663. package/dist/web/index.html +56 -19
  664. package/dist/web/studiograph-logomark.svg +29 -0
  665. package/package.json +34 -14
  666. package/dist/agent/skills/enrich-entities.md +0 -136
  667. package/dist/agent/skills/obsidian-source-setup.md +0 -246
  668. package/dist/agent/skills/skill-loader.d.ts +0 -48
  669. package/dist/agent/skills/skill-loader.js +0 -166
  670. package/dist/agent/skills/skill-loader.js.map +0 -1
  671. package/dist/agent/skills/sync-configuration.md +0 -119
  672. package/dist/agent/skills/sync-setup.md +0 -82
  673. package/dist/agent/tools/sync-tools.d.ts +0 -35
  674. package/dist/agent/tools/sync-tools.js +0 -992
  675. package/dist/agent/tools/sync-tools.js.map +0 -1
  676. package/dist/auth/github.d.ts +0 -56
  677. package/dist/auth/github.js +0 -169
  678. package/dist/auth/github.js.map +0 -1
  679. package/dist/cli/commands/access.d.ts +0 -11
  680. package/dist/cli/commands/access.js +0 -156
  681. package/dist/cli/commands/access.js.map +0 -1
  682. package/dist/cli/commands/app.d.ts +0 -7
  683. package/dist/cli/commands/app.js +0 -268
  684. package/dist/cli/commands/app.js.map +0 -1
  685. package/dist/cli/commands/auth.d.ts +0 -10
  686. package/dist/cli/commands/auth.js +0 -79
  687. package/dist/cli/commands/auth.js.map +0 -1
  688. package/dist/cli/commands/clear.d.ts +0 -5
  689. package/dist/cli/commands/clear.js +0 -36
  690. package/dist/cli/commands/clear.js.map +0 -1
  691. package/dist/cli/commands/collection.d.ts +0 -10
  692. package/dist/cli/commands/collection.js +0 -187
  693. package/dist/cli/commands/collection.js.map +0 -1
  694. package/dist/cli/commands/enrich.d.ts +0 -11
  695. package/dist/cli/commands/enrich.js +0 -135
  696. package/dist/cli/commands/enrich.js.map +0 -1
  697. package/dist/cli/commands/graphrag.d.ts +0 -12
  698. package/dist/cli/commands/graphrag.js +0 -122
  699. package/dist/cli/commands/graphrag.js.map +0 -1
  700. package/dist/cli/commands/join.d.ts +0 -9
  701. package/dist/cli/commands/join.js +0 -255
  702. package/dist/cli/commands/join.js.map +0 -1
  703. package/dist/cli/commands/members.d.ts +0 -11
  704. package/dist/cli/commands/members.js +0 -230
  705. package/dist/cli/commands/members.js.map +0 -1
  706. package/dist/cli/commands/org.d.ts +0 -10
  707. package/dist/cli/commands/org.js +0 -132
  708. package/dist/cli/commands/org.js.map +0 -1
  709. package/dist/cli/commands/provision.d.ts +0 -8
  710. package/dist/cli/commands/provision.js +0 -116
  711. package/dist/cli/commands/provision.js.map +0 -1
  712. package/dist/cli/commands/resolve.d.ts +0 -8
  713. package/dist/cli/commands/resolve.js +0 -85
  714. package/dist/cli/commands/resolve.js.map +0 -1
  715. package/dist/cli/commands/review.d.ts +0 -19
  716. package/dist/cli/commands/review.js +0 -128
  717. package/dist/cli/commands/review.js.map +0 -1
  718. package/dist/cli/commands/source.d.ts +0 -16
  719. package/dist/cli/commands/source.js +0 -159
  720. package/dist/cli/commands/source.js.map +0 -1
  721. package/dist/cli/commands/start.d.ts +0 -7
  722. package/dist/cli/commands/start.js +0 -589
  723. package/dist/cli/commands/start.js.map +0 -1
  724. package/dist/cli/commands/sync-collection.d.ts +0 -14
  725. package/dist/cli/commands/sync-collection.js +0 -355
  726. package/dist/cli/commands/sync-collection.js.map +0 -1
  727. package/dist/cli/commands/sync-entities.d.ts +0 -13
  728. package/dist/cli/commands/sync-entities.js +0 -242
  729. package/dist/cli/commands/sync-entities.js.map +0 -1
  730. package/dist/cli/commands/team.d.ts +0 -12
  731. package/dist/cli/commands/team.js +0 -185
  732. package/dist/cli/commands/team.js.map +0 -1
  733. package/dist/cli/commands/update.d.ts +0 -8
  734. package/dist/cli/commands/update.js +0 -155
  735. package/dist/cli/commands/update.js.map +0 -1
  736. package/dist/cli/commands/user.d.ts +0 -7
  737. package/dist/cli/commands/user.js +0 -153
  738. package/dist/cli/commands/user.js.map +0 -1
  739. package/dist/cli/scaffolding.d.ts +0 -12
  740. package/dist/cli/scaffolding.js +0 -397
  741. package/dist/cli/scaffolding.js.map +0 -1
  742. package/dist/cli/sync-review-interactive.d.ts +0 -31
  743. package/dist/cli/sync-review-interactive.js +0 -393
  744. package/dist/cli/sync-review-interactive.js.map +0 -1
  745. package/dist/core/migration-runner.d.ts +0 -42
  746. package/dist/core/migration-runner.js +0 -232
  747. package/dist/core/migration-runner.js.map +0 -1
  748. package/dist/core/migration-types.d.ts +0 -101
  749. package/dist/core/migration-types.js +0 -21
  750. package/dist/core/migration-types.js.map +0 -1
  751. package/dist/core/migrations/20260219-formalize-memory-location.d.ts +0 -2
  752. package/dist/core/migrations/20260219-formalize-memory-location.js +0 -35
  753. package/dist/core/migrations/20260219-formalize-memory-location.js.map +0 -1
  754. package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +0 -12
  755. package/dist/core/migrations/20260220-add-workspace-metadata.js +0 -65
  756. package/dist/core/migrations/20260220-add-workspace-metadata.js.map +0 -1
  757. package/dist/core/migrations/20260220-add-workspace-readme.d.ts +0 -11
  758. package/dist/core/migrations/20260220-add-workspace-readme.js +0 -82
  759. package/dist/core/migrations/20260220-add-workspace-readme.js.map +0 -1
  760. package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +0 -9
  761. package/dist/core/migrations/20260220-migrate-yaml-to-json.js +0 -64
  762. package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +0 -1
  763. package/dist/core/migrations/index.d.ts +0 -11
  764. package/dist/core/migrations/index.js +0 -23
  765. package/dist/core/migrations/index.js.map +0 -1
  766. package/dist/integrations/asana.d.ts +0 -26
  767. package/dist/integrations/asana.js +0 -78
  768. package/dist/integrations/asana.js.map +0 -1
  769. package/dist/integrations/figma-local.d.ts +0 -16
  770. package/dist/integrations/figma-local.js +0 -10
  771. package/dist/integrations/figma-local.js.map +0 -1
  772. package/dist/integrations/figma.d.ts +0 -17
  773. package/dist/integrations/figma.js +0 -17
  774. package/dist/integrations/figma.js.map +0 -1
  775. package/dist/integrations/granola.d.ts +0 -24
  776. package/dist/integrations/granola.js +0 -60
  777. package/dist/integrations/granola.js.map +0 -1
  778. package/dist/integrations/linear.d.ts +0 -14
  779. package/dist/integrations/linear.js +0 -80
  780. package/dist/integrations/linear.js.map +0 -1
  781. package/dist/integrations/paper-local.d.ts +0 -14
  782. package/dist/integrations/paper-local.js +0 -10
  783. package/dist/integrations/paper-local.js.map +0 -1
  784. package/dist/integrations/paper.d.ts +0 -2
  785. package/dist/integrations/paper.js +0 -10
  786. package/dist/integrations/paper.js.map +0 -1
  787. package/dist/integrations/pipedrive.d.ts +0 -26
  788. package/dist/integrations/pipedrive.js +0 -97
  789. package/dist/integrations/pipedrive.js.map +0 -1
  790. package/dist/integrations/registry.d.ts +0 -15
  791. package/dist/integrations/registry.js +0 -27
  792. package/dist/integrations/registry.js.map +0 -1
  793. package/dist/integrations/types.d.ts +0 -38
  794. package/dist/integrations/types.js +0 -9
  795. package/dist/integrations/types.js.map +0 -1
  796. package/dist/lib/lib/utils.d.ts +0 -2
  797. package/dist/lib/lib/utils.js +0 -6
  798. package/dist/lib/lib/utils.js.map +0 -1
  799. package/dist/mcp/connectors/asana.d.ts +0 -2
  800. package/dist/mcp/connectors/asana.js +0 -20
  801. package/dist/mcp/connectors/asana.js.map +0 -1
  802. package/dist/mcp/connectors/definitions.d.ts +0 -45
  803. package/dist/mcp/connectors/definitions.js +0 -32
  804. package/dist/mcp/connectors/definitions.js.map +0 -1
  805. package/dist/mcp/connectors/figma.d.ts +0 -5
  806. package/dist/mcp/connectors/figma.js +0 -21
  807. package/dist/mcp/connectors/figma.js.map +0 -1
  808. package/dist/mcp/connectors/gdrive.d.ts +0 -2
  809. package/dist/mcp/connectors/gdrive.js +0 -20
  810. package/dist/mcp/connectors/gdrive.js.map +0 -1
  811. package/dist/mcp/connectors/granola.d.ts +0 -2
  812. package/dist/mcp/connectors/granola.js +0 -12
  813. package/dist/mcp/connectors/granola.js.map +0 -1
  814. package/dist/mcp/connectors/linear.d.ts +0 -2
  815. package/dist/mcp/connectors/linear.js +0 -19
  816. package/dist/mcp/connectors/linear.js.map +0 -1
  817. package/dist/mcp/connectors/obsidian.d.ts +0 -2
  818. package/dist/mcp/connectors/obsidian.js +0 -19
  819. package/dist/mcp/connectors/obsidian.js.map +0 -1
  820. package/dist/mcp/connectors/pipedrive.d.ts +0 -2
  821. package/dist/mcp/connectors/pipedrive.js +0 -20
  822. package/dist/mcp/connectors/pipedrive.js.map +0 -1
  823. package/dist/mcp/connectors/slack.d.ts +0 -2
  824. package/dist/mcp/connectors/slack.js +0 -21
  825. package/dist/mcp/connectors/slack.js.map +0 -1
  826. package/dist/mcp/server-oauth-provider.d.ts +0 -56
  827. package/dist/mcp/server-oauth-provider.js +0 -142
  828. package/dist/mcp/server-oauth-provider.js.map +0 -1
  829. package/dist/server/chrome/chrome.css +0 -691
  830. package/dist/server/chrome/chrome.js +0 -374
  831. package/dist/server/collab-authority.d.ts +0 -70
  832. package/dist/server/collab-authority.js +0 -218
  833. package/dist/server/collab-authority.js.map +0 -1
  834. package/dist/server/collab.d.ts +0 -29
  835. package/dist/server/collab.js +0 -195
  836. package/dist/server/collab.js.map +0 -1
  837. package/dist/server/commit-scheduler.d.ts +0 -39
  838. package/dist/server/commit-scheduler.js +0 -113
  839. package/dist/server/commit-scheduler.js.map +0 -1
  840. package/dist/server/plugin-loader.d.ts +0 -53
  841. package/dist/server/plugin-loader.js +0 -155
  842. package/dist/server/plugin-loader.js.map +0 -1
  843. package/dist/server/routes/collab.d.ts +0 -6
  844. package/dist/server/routes/collab.js +0 -10
  845. package/dist/server/routes/collab.js.map +0 -1
  846. package/dist/server/routes/git-api.d.ts +0 -9
  847. package/dist/server/routes/git-api.js +0 -82
  848. package/dist/server/routes/git-api.js.map +0 -1
  849. package/dist/server/routes/meeting-ingest-api.d.ts +0 -15
  850. package/dist/server/routes/meeting-ingest-api.js +0 -323
  851. package/dist/server/routes/meeting-ingest-api.js.map +0 -1
  852. package/dist/server/routes/sync-api.d.ts +0 -26
  853. package/dist/server/routes/sync-api.js +0 -814
  854. package/dist/server/routes/sync-api.js.map +0 -1
  855. package/dist/server/routes/webhook.d.ts +0 -14
  856. package/dist/server/routes/webhook.js +0 -102
  857. package/dist/server/routes/webhook.js.map +0 -1
  858. package/dist/services/github-provisioner.d.ts +0 -36
  859. package/dist/services/github-provisioner.js +0 -126
  860. package/dist/services/github-provisioner.js.map +0 -1
  861. package/dist/services/github-service.d.ts +0 -99
  862. package/dist/services/github-service.js +0 -310
  863. package/dist/services/github-service.js.map +0 -1
  864. package/dist/services/insights.d.ts +0 -38
  865. package/dist/services/insights.js +0 -246
  866. package/dist/services/insights.js.map +0 -1
  867. package/dist/services/sync/collection-sync.d.ts +0 -60
  868. package/dist/services/sync/collection-sync.js +0 -509
  869. package/dist/services/sync/collection-sync.js.map +0 -1
  870. package/dist/services/sync/commit.d.ts +0 -60
  871. package/dist/services/sync/commit.js +0 -354
  872. package/dist/services/sync/commit.js.map +0 -1
  873. package/dist/services/sync/context-index.d.ts +0 -69
  874. package/dist/services/sync/context-index.js +0 -280
  875. package/dist/services/sync/context-index.js.map +0 -1
  876. package/dist/services/sync/data-fetcher.d.ts +0 -31
  877. package/dist/services/sync/data-fetcher.js +0 -12
  878. package/dist/services/sync/data-fetcher.js.map +0 -1
  879. package/dist/services/sync/derive.d.ts +0 -34
  880. package/dist/services/sync/derive.js +0 -164
  881. package/dist/services/sync/derive.js.map +0 -1
  882. package/dist/services/sync/enrichment-state.d.ts +0 -31
  883. package/dist/services/sync/enrichment-state.js +0 -63
  884. package/dist/services/sync/enrichment-state.js.map +0 -1
  885. package/dist/services/sync/enrichment.d.ts +0 -25
  886. package/dist/services/sync/enrichment.js +0 -121
  887. package/dist/services/sync/enrichment.js.map +0 -1
  888. package/dist/services/sync/entity-refresh.d.ts +0 -30
  889. package/dist/services/sync/entity-refresh.js +0 -275
  890. package/dist/services/sync/entity-refresh.js.map +0 -1
  891. package/dist/services/sync/frontmatter-extractor.d.ts +0 -40
  892. package/dist/services/sync/frontmatter-extractor.js +0 -279
  893. package/dist/services/sync/frontmatter-extractor.js.map +0 -1
  894. package/dist/services/sync/graph-match-state.d.ts +0 -33
  895. package/dist/services/sync/graph-match-state.js +0 -61
  896. package/dist/services/sync/graph-match-state.js.map +0 -1
  897. package/dist/services/sync/graph-match.d.ts +0 -53
  898. package/dist/services/sync/graph-match.js +0 -316
  899. package/dist/services/sync/graph-match.js.map +0 -1
  900. package/dist/services/sync/graphrag-client.d.ts +0 -43
  901. package/dist/services/sync/graphrag-client.js +0 -94
  902. package/dist/services/sync/graphrag-client.js.map +0 -1
  903. package/dist/services/sync/graphrag-config.d.ts +0 -16
  904. package/dist/services/sync/graphrag-config.js +0 -39
  905. package/dist/services/sync/graphrag-config.js.map +0 -1
  906. package/dist/services/sync/graphrag-context.d.ts +0 -14
  907. package/dist/services/sync/graphrag-context.js +0 -109
  908. package/dist/services/sync/graphrag-context.js.map +0 -1
  909. package/dist/services/sync/graphrag-indexer.d.ts +0 -30
  910. package/dist/services/sync/graphrag-indexer.js +0 -358
  911. package/dist/services/sync/graphrag-indexer.js.map +0 -1
  912. package/dist/services/sync/llm.d.ts +0 -32
  913. package/dist/services/sync/llm.js +0 -115
  914. package/dist/services/sync/llm.js.map +0 -1
  915. package/dist/services/sync/mcp-client.d.ts +0 -71
  916. package/dist/services/sync/mcp-client.js +0 -299
  917. package/dist/services/sync/mcp-client.js.map +0 -1
  918. package/dist/services/sync/model-factory.d.ts +0 -13
  919. package/dist/services/sync/model-factory.js +0 -38
  920. package/dist/services/sync/model-factory.js.map +0 -1
  921. package/dist/services/sync/name-quality.d.ts +0 -31
  922. package/dist/services/sync/name-quality.js +0 -60
  923. package/dist/services/sync/name-quality.js.map +0 -1
  924. package/dist/services/sync/output-schemas.d.ts +0 -92
  925. package/dist/services/sync/output-schemas.js +0 -43
  926. package/dist/services/sync/output-schemas.js.map +0 -1
  927. package/dist/services/sync/prompts.d.ts +0 -19
  928. package/dist/services/sync/prompts.js +0 -128
  929. package/dist/services/sync/prompts.js.map +0 -1
  930. package/dist/services/sync/reconciler.d.ts +0 -48
  931. package/dist/services/sync/reconciler.js +0 -294
  932. package/dist/services/sync/reconciler.js.map +0 -1
  933. package/dist/services/sync/rest-client.d.ts +0 -40
  934. package/dist/services/sync/rest-client.js +0 -100
  935. package/dist/services/sync/rest-client.js.map +0 -1
  936. package/dist/services/sync/source-config.d.ts +0 -67
  937. package/dist/services/sync/source-config.js +0 -304
  938. package/dist/services/sync/source-config.js.map +0 -1
  939. package/dist/services/sync/source-definitions/asana.d.ts +0 -14
  940. package/dist/services/sync/source-definitions/asana.js +0 -42
  941. package/dist/services/sync/source-definitions/asana.js.map +0 -1
  942. package/dist/services/sync/source-definitions/definitions.d.ts +0 -8
  943. package/dist/services/sync/source-definitions/definitions.js +0 -8
  944. package/dist/services/sync/source-definitions/definitions.js.map +0 -1
  945. package/dist/services/sync/source-definitions/gdrive.d.ts +0 -16
  946. package/dist/services/sync/source-definitions/gdrive.js +0 -68
  947. package/dist/services/sync/source-definitions/gdrive.js.map +0 -1
  948. package/dist/services/sync/source-definitions/granola.d.ts +0 -2
  949. package/dist/services/sync/source-definitions/granola.js +0 -21
  950. package/dist/services/sync/source-definitions/granola.js.map +0 -1
  951. package/dist/services/sync/source-definitions/linear.d.ts +0 -2
  952. package/dist/services/sync/source-definitions/linear.js +0 -62
  953. package/dist/services/sync/source-definitions/linear.js.map +0 -1
  954. package/dist/services/sync/source-definitions/obsidian.d.ts +0 -2
  955. package/dist/services/sync/source-definitions/obsidian.js +0 -55
  956. package/dist/services/sync/source-definitions/obsidian.js.map +0 -1
  957. package/dist/services/sync/source-definitions/pipedrive.d.ts +0 -2
  958. package/dist/services/sync/source-definitions/pipedrive.js +0 -43
  959. package/dist/services/sync/source-definitions/pipedrive.js.map +0 -1
  960. package/dist/services/sync/staging.d.ts +0 -53
  961. package/dist/services/sync/staging.js +0 -130
  962. package/dist/services/sync/staging.js.map +0 -1
  963. package/dist/services/sync/structured-extractor.d.ts +0 -57
  964. package/dist/services/sync/structured-extractor.js +0 -584
  965. package/dist/services/sync/structured-extractor.js.map +0 -1
  966. package/dist/services/sync/sync-runner.d.ts +0 -32
  967. package/dist/services/sync/sync-runner.js +0 -195
  968. package/dist/services/sync/sync-runner.js.map +0 -1
  969. package/dist/services/sync/sync-state.d.ts +0 -43
  970. package/dist/services/sync/sync-state.js +0 -154
  971. package/dist/services/sync/sync-state.js.map +0 -1
  972. package/dist/services/sync/types.d.ts +0 -381
  973. package/dist/services/sync/types.js +0 -8
  974. package/dist/services/sync/types.js.map +0 -1
  975. package/dist/services/sync/unstructured-extractor.d.ts +0 -27
  976. package/dist/services/sync/unstructured-extractor.js +0 -185
  977. package/dist/services/sync/unstructured-extractor.js.map +0 -1
  978. package/dist/utils/merge-resolver.d.ts +0 -59
  979. package/dist/utils/merge-resolver.js +0 -303
  980. package/dist/utils/merge-resolver.js.map +0 -1
  981. package/dist/utils/workspace-config.d.ts +0 -8
  982. package/dist/utils/workspace-config.js +0 -22
  983. package/dist/utils/workspace-config.js.map +0 -1
  984. package/dist/web/_app/immutable/assets/0.DdizXOKi.css +0 -1
  985. package/dist/web/_app/immutable/assets/10.BUrHkYry.css +0 -1
  986. package/dist/web/_app/immutable/assets/2.n7-yW_Fs.css +0 -1
  987. package/dist/web/_app/immutable/assets/3.BtaZagnv.css +0 -1
  988. package/dist/web/_app/immutable/assets/4.DT7X0x5S.css +0 -1
  989. package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
  990. package/dist/web/_app/immutable/assets/6.CquhUpOu.css +0 -1
  991. package/dist/web/_app/immutable/assets/7.CjbDRbuG.css +0 -1
  992. package/dist/web/_app/immutable/assets/8.S1QdUGNM.css +0 -1
  993. package/dist/web/_app/immutable/assets/9.CT4xL4K3.css +0 -1
  994. package/dist/web/_app/immutable/assets/Copy.FS8bdfxr.css +0 -1
  995. package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
  996. package/dist/web/_app/immutable/assets/ViewToolbar.D-QW2oKe.css +0 -1
  997. package/dist/web/_app/immutable/assets/index.D6tMDJWk.css +0 -1
  998. package/dist/web/_app/immutable/chunks/37NdyH6G.js +0 -32
  999. package/dist/web/_app/immutable/chunks/4Hhzb6pv.js +0 -1
  1000. package/dist/web/_app/immutable/chunks/72bZS3G9.js +0 -1
  1001. package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
  1002. package/dist/web/_app/immutable/chunks/B-7hHz7B.js +0 -1
  1003. package/dist/web/_app/immutable/chunks/B340SUKR.js +0 -1
  1004. package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
  1005. package/dist/web/_app/immutable/chunks/BDoWDZaG.js +0 -1
  1006. package/dist/web/_app/immutable/chunks/BFyl1ZHO.js +0 -1
  1007. package/dist/web/_app/immutable/chunks/BS2rFAVq.js +0 -1
  1008. package/dist/web/_app/immutable/chunks/BSsDC_p4.js +0 -1
  1009. package/dist/web/_app/immutable/chunks/BTX2Jr8_.js +0 -1
  1010. package/dist/web/_app/immutable/chunks/BWNY8zw6.js +0 -2
  1011. package/dist/web/_app/immutable/chunks/BdPUVvAi.js +0 -1
  1012. package/dist/web/_app/immutable/chunks/BmsJVLyy.js +0 -1
  1013. package/dist/web/_app/immutable/chunks/BoAosqzE.js +0 -1
  1014. package/dist/web/_app/immutable/chunks/Bs-tL5OR.js +0 -1
  1015. package/dist/web/_app/immutable/chunks/Bsacq2UX.js +0 -1
  1016. package/dist/web/_app/immutable/chunks/BuewkNdS.js +0 -4
  1017. package/dist/web/_app/immutable/chunks/ByunV8un.js +0 -1
  1018. package/dist/web/_app/immutable/chunks/C7VoTosa.js +0 -2
  1019. package/dist/web/_app/immutable/chunks/CDV5Q7RN.js +0 -1
  1020. package/dist/web/_app/immutable/chunks/CJ8__CWt.js +0 -1
  1021. package/dist/web/_app/immutable/chunks/CJUKmosC.js +0 -5
  1022. package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
  1023. package/dist/web/_app/immutable/chunks/CT6oIU-C.js +0 -1
  1024. package/dist/web/_app/immutable/chunks/CTRxNfZk.js +0 -1
  1025. package/dist/web/_app/immutable/chunks/CWQRQXxy.js +0 -1
  1026. package/dist/web/_app/immutable/chunks/CXH6iFbA.js +0 -1
  1027. package/dist/web/_app/immutable/chunks/CX_61fY8.js +0 -5
  1028. package/dist/web/_app/immutable/chunks/CYrVHOHA.js +0 -1
  1029. package/dist/web/_app/immutable/chunks/CdeYcEuU.js +0 -1
  1030. package/dist/web/_app/immutable/chunks/CmCtpZ1Y.js +0 -1
  1031. package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
  1032. package/dist/web/_app/immutable/chunks/CrdV0ttd.js +0 -1
  1033. package/dist/web/_app/immutable/chunks/CscoF-YL.js +0 -18
  1034. package/dist/web/_app/immutable/chunks/Cx4YdFMk.js +0 -1
  1035. package/dist/web/_app/immutable/chunks/D7ZqAKi9.js +0 -3
  1036. package/dist/web/_app/immutable/chunks/DGbA7IXh.js +0 -2
  1037. package/dist/web/_app/immutable/chunks/DbbB6Up5.js +0 -1
  1038. package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
  1039. package/dist/web/_app/immutable/chunks/DtM5cEDu.js +0 -1
  1040. package/dist/web/_app/immutable/chunks/Eqahi7_S.js +0 -2
  1041. package/dist/web/_app/immutable/chunks/FFlLQIiS.js +0 -1
  1042. package/dist/web/_app/immutable/chunks/O9Eb9k00.js +0 -1
  1043. package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
  1044. package/dist/web/_app/immutable/chunks/QF8MAmnc.js +0 -1
  1045. package/dist/web/_app/immutable/chunks/UjzxCpxn.js +0 -1
  1046. package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
  1047. package/dist/web/_app/immutable/chunks/Y90OgS-9.js +0 -1
  1048. package/dist/web/_app/immutable/chunks/cLyZlkXv.js +0 -1
  1049. package/dist/web/_app/immutable/chunks/iDtAARVW.js +0 -2
  1050. package/dist/web/_app/immutable/chunks/oC_W7W7p.js +0 -1
  1051. package/dist/web/_app/immutable/chunks/rJdWIgh-.js +0 -1
  1052. package/dist/web/_app/immutable/chunks/tvOsokaa.js +0 -1
  1053. package/dist/web/_app/immutable/chunks/uLEXaPwE.js +0 -1
  1054. package/dist/web/_app/immutable/chunks/vSaooFHB.js +0 -1
  1055. package/dist/web/_app/immutable/entry/app.DAR-mtfg.js +0 -2
  1056. package/dist/web/_app/immutable/entry/start.xDnyRaR1.js +0 -1
  1057. package/dist/web/_app/immutable/nodes/0.D0aV-Zro.js +0 -2
  1058. package/dist/web/_app/immutable/nodes/1.C7QoM8qD.js +0 -1
  1059. package/dist/web/_app/immutable/nodes/10.DrDOAjOD.js +0 -1
  1060. package/dist/web/_app/immutable/nodes/2.B0OgNuKW.js +0 -168
  1061. package/dist/web/_app/immutable/nodes/3.BZ4qHGZi.js +0 -1
  1062. package/dist/web/_app/immutable/nodes/4.hm-mxuuj.js +0 -12
  1063. package/dist/web/_app/immutable/nodes/5.Bdbt4fjx.js +0 -4
  1064. package/dist/web/_app/immutable/nodes/6.BXrCI40c.js +0 -2
  1065. package/dist/web/_app/immutable/nodes/7.Chd4i9bm.js +0 -2
  1066. package/dist/web/_app/immutable/nodes/8.B8SF-aNs.js +0 -1
  1067. package/dist/web/_app/immutable/nodes/9.YDeu-RnO.js +0 -1
@@ -18,13 +18,379 @@ import * as syncProtocol from 'y-protocols/sync.js';
18
18
  import * as awarenessProtocol from 'y-protocols/awareness.js';
19
19
  import * as encoding from 'lib0/encoding';
20
20
  import * as decoding from 'lib0/decoding';
21
+ import { createHash } from 'node:crypto';
22
+ import { applyTextDiff } from './yjs-text-diff.js';
23
+ function sha256(s) {
24
+ return createHash('sha256').update(s, 'utf-8').digest('hex');
25
+ }
21
26
  const MSG_SYNC = 0;
22
27
  const MSG_AWARENESS = 1;
28
+ /**
29
+ * MSG_CHUNK wraps a fragment of a larger logical message. Chunked frames
30
+ * have layout: [4B msgId][2B seq][2B total][1B origMsgType][chunkPayload].
31
+ * Used to keep individual WS frames under Safari/WebKit's binary-frame
32
+ * threshold (~4KB after deflate), where larger frames get truncated and
33
+ * blow up Yjs's varint decoder with `RangeError: Length out of range of
34
+ * buffer`. The client reassembles chunks and dispatches as if the
35
+ * original `origMsgType` frame had arrived intact.
36
+ */
37
+ const MSG_CHUNK = 2;
38
+ /** Threshold above which an outbound payload is split into MSG_CHUNK
39
+ * frames. 4KB stays well under the smallest reported Safari WebSocket
40
+ * binary-frame failure size, while keeping the common keystroke/awareness
41
+ * traffic on the single-frame fast path. */
42
+ const MAX_CHUNK_PAYLOAD = 4096;
43
+ /**
44
+ * Grace period before destroying an idle Y.Doc (ms).
45
+ * Keep long enough that async server-side processing (LLM meeting summary,
46
+ * agent mutations, etc.) can push updates into the Y.Doc via
47
+ * applyAgentContent while the client is transiently disconnected.
48
+ */
49
+ const DOC_IDLE_TIMEOUT = 120_000;
50
+ /**
51
+ * After a client connects to a fresh (server-restart or first-open) Y.Doc,
52
+ * wait this long for the client's sync-step-2 to arrive before seeding
53
+ * from disk. If the client has state (reconnect after server restart),
54
+ * their sync populates the Y.Doc and we skip the disk seed — preventing
55
+ * the CRDT merge that would otherwise produce duplicated content when
56
+ * two origins insert the same bytes.
57
+ */
58
+ const SEED_WAIT_MS = 500;
59
+ /**
60
+ * Origins for which server-initiated `ydoc.transact` updates are relayed
61
+ * to all connected clients. The broadcast observer registered in `doLoad`
62
+ * filters by this set; updates from other origins (including `ws-client`,
63
+ * which `handleMessage` already relays peer-to-peer) are skipped to avoid
64
+ * double-sends and infinite-loop hazards.
65
+ */
66
+ const BROADCAST_ORIGINS = new Set([
67
+ 'server-sync-disk-merge', // reconcileFromDisk (boot / git-pull / dev-tools)
68
+ 'server-agent-write', // applyAgentContent post-commit broadcast
69
+ ]);
70
+ /**
71
+ * Thrown by `assertWritable` when broadcast is disabled AND a doc has
72
+ * active clients AND the operator has not explicitly opted into the
73
+ * degraded mode via `STUDIOGRAPH_ALLOW_DEGRADED_WRITES`. Surfaces a hard
74
+ * error to the caller (MCP / agent / event processor) instead of silently
75
+ * mutating the server's Y.Doc out of sync with connected editors.
76
+ */
77
+ export class BroadcastDisabledLiveClientsError extends Error {
78
+ docName;
79
+ code = 'BROADCAST_DISABLED_LIVE_CLIENTS';
80
+ constructor(docName) {
81
+ super(`Refusing body write to ${docName}: YJS broadcast is disabled (STUDIOGRAPH_YJS_BROADCAST=0) ` +
82
+ `but ${docName} has active editors. Server-side writes would diverge from connected clients. ` +
83
+ `Set STUDIOGRAPH_ALLOW_DEGRADED_WRITES=1 to override at the cost of editor data loss.`);
84
+ this.docName = docName;
85
+ this.name = 'BroadcastDisabledLiveClientsError';
86
+ }
87
+ }
88
+ /**
89
+ * Thrown by `assertWritable` when a connected client has unsaved typing
90
+ * in the live Y.Doc (i.e. `sha256(ytext) !== mdRevisionHash`) and a
91
+ * server-write would clobber those keystrokes via `applyTextDiff`.
92
+ *
93
+ * The architectural reality: `update_entity` ships a whole-body target.
94
+ * `applyTextDiff` preserves chars in unchanged regions but discards chars
95
+ * inside regions the agent rewrote. If the user's pending typing falls in
96
+ * such a region, it's lost — Phase 2's per-doc lock + MSG_SYNC queue can't
97
+ * help because the agent's content was already generated against a pre-
98
+ * typing snapshot. The only safe move is to refuse and surface the typed
99
+ * error so the caller (MCP / agent) can wait or ask the user.
100
+ *
101
+ * Triggered ONLY for `source: 'server-write'` paths — autosave is the
102
+ * client's own write and never refused.
103
+ *
104
+ * A future edit-region tool (small string replacements with baseRevision)
105
+ * would compose with the lock + queue + diff machinery and not need this
106
+ * guard. Until then, whole-body server-writes refuse when typing is in
107
+ * flight.
108
+ */
109
+ export class LiveEditorPendingError extends Error {
110
+ docName;
111
+ code = 'LIVE_EDITOR_PENDING';
112
+ constructor(docName) {
113
+ super(`Refusing server-write to ${docName}: a connected editor has unsaved ` +
114
+ `typing that hasn't reached disk yet. Applying a whole-body target now ` +
115
+ `would discard those keystrokes in any region this write rewrites. ` +
116
+ `Retry after the typing pauses (autosave fires ~800ms after the last ` +
117
+ `keystroke), or ask the user before proceeding.`);
118
+ this.docName = docName;
119
+ this.name = 'LiveEditorPendingError';
120
+ }
121
+ }
23
122
  export class YjsManager {
24
123
  workspaceManager;
124
+ persistence;
25
125
  docs = new Map();
26
- constructor(workspaceManager) {
126
+ /**
127
+ * In-flight `getOrCreate` promises, keyed by docName. Concurrent calls for
128
+ * the same docName await the same promise instead of building two Y.Docs
129
+ * (which would race on the persistence file and split client traffic).
130
+ */
131
+ loadingPromises = new Map();
132
+ /**
133
+ * Whether the update-broadcast observer is registered. Read once at
134
+ * construction from `STUDIOGRAPH_YJS_BROADCAST` (default ON). Flipping the
135
+ * env var requires a restart to take effect — dynamic re-check would let
136
+ * connected editors silently diverge when the flag is toggled mid-session.
137
+ */
138
+ broadcastEnabled;
139
+ /**
140
+ * Operator opt-in to accept degraded-mode data loss (broadcast off +
141
+ * server-side writes while clients are connected). Off by default —
142
+ * forcing operators to make the data-loss trade-off explicit.
143
+ */
144
+ allowDegradedWrites;
145
+ /**
146
+ * Per-doc lock chain (Phase 2). Each `withDocLock(docName, fn)` appends
147
+ * to this chain so server-side writes for the same doc serialize. Client
148
+ * `handleMessage` updates do NOT acquire the lock — instead they queue
149
+ * into {@link msgSyncQueue} while the lock is held and apply on release.
150
+ */
151
+ docLocks = new Map();
152
+ /**
153
+ * Per-doc MSG_SYNC buffer. While `withDocLock` is held for a doc, inbound
154
+ * client sync frames for that doc are pushed here instead of applied
155
+ * directly. On lock release, frames are drained in arrival order via the
156
+ * normal `handleMessage` path with origin `'ws-client'`.
157
+ *
158
+ * This is the Codex pass-3 #1 fix: without queueing, a client insert
159
+ * arriving mid-lock would land in `entry.ydoc` BEFORE `applyAgentContent`
160
+ * runs, and the agent's full-body diff would delete that just-typed char.
161
+ * With queueing, the client's insert lands on the post-agent ytext as a
162
+ * fresh CRDT op at its original anchor.
163
+ */
164
+ msgSyncQueue = new Map();
165
+ constructor(workspaceManager, persistence) {
27
166
  this.workspaceManager = workspaceManager;
167
+ this.persistence = persistence;
168
+ this.broadcastEnabled = process.env.STUDIOGRAPH_YJS_BROADCAST !== '0';
169
+ this.allowDegradedWrites = process.env.STUDIOGRAPH_ALLOW_DEGRADED_WRITES === '1';
170
+ }
171
+ /** Whether the update-broadcast observer is active. Exposed for diagnostics. */
172
+ isBroadcastEnabled() {
173
+ return this.broadcastEnabled;
174
+ }
175
+ /**
176
+ * Pre-write guard for server-write body paths. Throws if EITHER:
177
+ *
178
+ * (a) Broadcast is disabled, the doc has active clients, and the
179
+ * operator hasn't opted into degraded-mode writes — server-side
180
+ * writes would silently diverge from connected editors.
181
+ * → `BroadcastDisabledLiveClientsError`
182
+ *
183
+ * (b) A connected editor has unsaved typing in the live Y.Doc
184
+ * (sha256(ytext) !== mdRevisionHash) — applying a whole-body
185
+ * target now would discard those keystrokes via `applyTextDiff`
186
+ * in any region this write rewrites.
187
+ * → `LiveEditorPendingError`
188
+ *
189
+ * Called from `graph.update`'s body-write path via the `assertWritable`
190
+ * callback, gated to `source === 'server-write'`. Autosave is the
191
+ * client's own write and is never refused.
192
+ */
193
+ assertWritable(docName) {
194
+ const entry = this.docs.get(docName);
195
+ // (a) Broadcast-off + live clients guard.
196
+ if (!this.broadcastEnabled && !this.allowDegradedWrites) {
197
+ if (entry && entry.clients.size > 0) {
198
+ throw new BroadcastDisabledLiveClientsError(docName);
199
+ }
200
+ }
201
+ // (b) Live editor with unsaved typing guard. Only meaningful when:
202
+ // - a Y.Doc is loaded AND has at least one connected client
203
+ // (without an editor watching, no keystrokes-in-flight to protect), AND
204
+ // - the doc is seeded (an unseeded entry has Y.Text='' which would
205
+ // spuriously diverge from the disk-content hash before the seed
206
+ // timer or first client sync populates it).
207
+ if (entry && entry.clients.size > 0 && entry.seeded) {
208
+ const ytextContent = entry.ydoc.getText('content').toString();
209
+ const ytextHash = sha256(ytextContent);
210
+ if (ytextHash !== entry.mdRevisionHash) {
211
+ throw new LiveEditorPendingError(docName);
212
+ }
213
+ }
214
+ }
215
+ /**
216
+ * Acquire a per-doc lock and run `fn` to completion. While the lock is
217
+ * held, inbound client MSG_SYNC frames for the same docName are queued
218
+ * (see {@link msgSyncQueue}) and applied after the lock releases.
219
+ *
220
+ * Contract: server-side writes serialize against other server-side
221
+ * writes for the same doc. Client typing does NOT block — frames are
222
+ * buffered and applied in arrival order on release. The Codex pass-3 #1
223
+ * trace proved this is necessary: without queueing, a client keystroke
224
+ * arriving mid-lock would be deleted by the agent's subsequent full-body
225
+ * diff (the keystroke lives in ytext but not in the agent's target).
226
+ *
227
+ * Per-doc only — other docs' handleMessage traffic is unaffected.
228
+ *
229
+ * Failures inside `fn` propagate to the caller; the lock releases either
230
+ * way so the queued sync drain still runs.
231
+ */
232
+ async withDocLock(docName, fn) {
233
+ const prev = this.docLocks.get(docName) ?? Promise.resolve();
234
+ let resolveSelf;
235
+ const self = new Promise(resolve => { resolveSelf = resolve; });
236
+ this.docLocks.set(docName, self);
237
+ try {
238
+ await prev.catch(() => { });
239
+ try {
240
+ return await fn();
241
+ }
242
+ finally {
243
+ // Drain queued MSG_SYNC frames in arrival order BEFORE releasing
244
+ // the lock. This guarantees no other server-write holder sees a
245
+ // half-drained queue.
246
+ this.drainMsgSyncQueue(docName);
247
+ }
248
+ }
249
+ finally {
250
+ resolveSelf(undefined);
251
+ // Only clear if we're still the tail — a later lock-acquirer may
252
+ // have appended after us.
253
+ if (this.docLocks.get(docName) === self) {
254
+ this.docLocks.delete(docName);
255
+ }
256
+ }
257
+ }
258
+ /** Whether a server-write lock is currently held for the doc. */
259
+ isLocked(docName) {
260
+ return this.docLocks.has(docName);
261
+ }
262
+ /**
263
+ * Buffer an inbound MSG_SYNC frame for later application. Called from
264
+ * `handleMessage` when the doc is locked.
265
+ */
266
+ enqueueMsgSync(docName, sender, payload) {
267
+ let q = this.msgSyncQueue.get(docName);
268
+ if (!q) {
269
+ q = [];
270
+ this.msgSyncQueue.set(docName, q);
271
+ }
272
+ q.push({ sender, payload });
273
+ }
274
+ /**
275
+ * Drain any queued MSG_SYNC frames for `docName`, applying them via the
276
+ * normal handleMessage path. Called from `withDocLock` on release.
277
+ */
278
+ drainMsgSyncQueue(docName) {
279
+ const q = this.msgSyncQueue.get(docName);
280
+ if (!q || q.length === 0)
281
+ return;
282
+ this.msgSyncQueue.delete(docName);
283
+ for (const { sender, payload } of q) {
284
+ // Re-enter handleMessage. Since the lock is being released by the
285
+ // caller above (resolveSelf runs after this drain), the lock check
286
+ // inside handleMessage MUST NOT see this doc as locked. We use a
287
+ // direct call to the apply-sync logic instead of handleMessage to
288
+ // avoid the re-entrant lock check.
289
+ try {
290
+ this.applyClientSync(docName, sender, payload);
291
+ }
292
+ catch (err) {
293
+ console.warn(`[yjs] queued MSG_SYNC drain for ${docName} failed`, err);
294
+ }
295
+ }
296
+ }
297
+ /**
298
+ * Apply a client sync message directly, bypassing the lock check. Used
299
+ * by `drainMsgSyncQueue`. Mirrors the MSG_SYNC branch of
300
+ * {@link handleMessage} — keep in sync if that branch changes.
301
+ */
302
+ applyClientSync(docName, sender, payload) {
303
+ const entry = this.docs.get(docName);
304
+ if (!entry)
305
+ return;
306
+ const decoder = decoding.createDecoder(payload);
307
+ const encoder = encoding.createEncoder();
308
+ syncProtocol.readSyncMessage(decoder, encoder, entry.ydoc, 'ws-client');
309
+ if (!entry.seeded && entry.ydoc.getText('content').length > 0) {
310
+ entry.seeded = true;
311
+ if (entry.seedTimer) {
312
+ clearTimeout(entry.seedTimer);
313
+ entry.seedTimer = undefined;
314
+ }
315
+ const parsed = this.parseDocName(docName);
316
+ if (parsed)
317
+ entry.mdRevisionHash = sha256(this.readDiskContent(parsed));
318
+ this.broadcastDocReady(docName);
319
+ }
320
+ if (encoding.length(encoder) > 0) {
321
+ this.sendToClient(sender, docName, MSG_SYNC, encoding.toUint8Array(encoder));
322
+ }
323
+ for (const client of entry.clients) {
324
+ if (client === sender || client.readyState !== 1)
325
+ continue;
326
+ this.sendToClient(client, docName, MSG_SYNC, payload);
327
+ }
328
+ }
329
+ /**
330
+ * Apply a server-write target body to the live Y.Doc.
331
+ *
332
+ * Called from `graph.update`'s server-write branch AFTER disk + commit
333
+ * have succeeded. The disk-first ordering is deliberate: clients only see
334
+ * server-initiated changes that are durable. If applying here fails,
335
+ * disk and commit are unaffected — but live clients are out of sync.
336
+ *
337
+ * Returns `{ applied: 'no-doc' | 'unseeded' | 'ok' }`. For the first two,
338
+ * the caller already wrote disk; no live editor needs the broadcast.
339
+ *
340
+ * On `'ok'`: sets `entry.mdRevisionHash = sha256(target)` BEFORE the
341
+ * transact wraps, applies the diff with origin `'server-agent-write'`
342
+ * (broadcast-allowlisted), returns success.
343
+ *
344
+ * On failure (rare — applyTextDiff is just delete/insert ops), sends a
345
+ * `doc_conflict` JSON frame to all clients and rethrows. Conflict UI
346
+ * is the user's signal that disk and Y.Doc diverged.
347
+ */
348
+ applyAgentContent(docName, target) {
349
+ const entry = this.docs.get(docName);
350
+ if (!entry)
351
+ return { applied: 'no-doc' };
352
+ if (!entry.seeded)
353
+ return { applied: 'unseeded' };
354
+ try {
355
+ const ytext = entry.ydoc.getText('content');
356
+ // Set the hash BEFORE the transact. applyTextDiff makes ytext === target
357
+ // after the transact, so sha256(target) is the post-state hash. The
358
+ // persistence observer fires during the transact and reads the live
359
+ // hash via the resolver — it will see the new hash either way (Phase
360
+ // 1c flush-time resolver), but pinning it before is defense in depth.
361
+ entry.mdRevisionHash = sha256(target);
362
+ applyTextDiff(entry.ydoc, ytext, target, 'server-agent-write');
363
+ return { applied: 'ok' };
364
+ }
365
+ catch (err) {
366
+ // applyTextDiff itself doesn't throw for valid strings, but if Yjs
367
+ // somehow rejects the transact we surface conflict UI to clients so
368
+ // they don't keep typing into a divergent Y.Doc and back-stomp disk.
369
+ this.sendDocConflict(docName, 'apply-agent-content-failed');
370
+ throw err;
371
+ }
372
+ }
373
+ /**
374
+ * Send a `doc_conflict` JSON frame to every connected client of a doc.
375
+ * Editor handles by entering readonly conflict UI: "another writer made
376
+ * a change we couldn't sync to your editor; reload to continue."
377
+ *
378
+ * Used by `applyAgentContent` failure path. Distinct from `doc_ready`
379
+ * (the heartbeat) — conflict implies user must take action.
380
+ */
381
+ sendDocConflict(docName, reason) {
382
+ const entry = this.docs.get(docName);
383
+ if (!entry)
384
+ return;
385
+ const msg = JSON.stringify({ type: 'doc_conflict', docName, reason });
386
+ for (const client of entry.clients) {
387
+ if (client.readyState !== 1)
388
+ continue;
389
+ try {
390
+ client.send(msg);
391
+ }
392
+ catch { /* non-fatal */ }
393
+ }
28
394
  }
29
395
  /**
30
396
  * Parse a docName ("repo/entityType/entityId") into its components.
@@ -36,65 +402,322 @@ export class YjsManager {
36
402
  return { repo: parts[0], entityType: parts[1], entityId: parts.slice(2).join('/') };
37
403
  }
38
404
  /**
39
- * Get or create a Y.Doc for an entity. Seeds from disk on first access.
405
+ * Get or create a Y.Doc for an entity.
406
+ *
407
+ * Async because persistence loads from disk. Concurrent calls for the same
408
+ * docName await the same in-flight promise so we don't build two Y.Docs.
409
+ *
410
+ * If a persisted snapshot exists, applies it to the fresh Y.Doc and marks
411
+ * `seeded = true` immediately — reconnecting clients then see a server
412
+ * state vector that already includes their pre-restart ops, so sync-step-2
413
+ * is a no-op and the duplication race is closed.
414
+ *
415
+ * If no snapshot exists (first-ever open of this entity, or persistence
416
+ * disabled), leaves `seeded = false`. The existing deferred-seed path in
417
+ * addClient + handleMessage will populate the Y.Doc from the .md file.
40
418
  */
41
- getOrCreate(docName) {
419
+ async getOrCreate(docName) {
42
420
  const existing = this.docs.get(docName);
43
421
  if (existing)
44
422
  return existing;
45
- // Load entity content from disk
423
+ const inFlight = this.loadingPromises.get(docName);
424
+ if (inFlight)
425
+ return inFlight;
426
+ const promise = this.doLoad(docName);
427
+ this.loadingPromises.set(docName, promise);
428
+ try {
429
+ return await promise;
430
+ }
431
+ finally {
432
+ this.loadingPromises.delete(docName);
433
+ }
434
+ }
435
+ async doLoad(docName) {
46
436
  const parsed = this.parseDocName(docName);
47
437
  if (!parsed)
48
438
  return null;
49
- const graph = this.workspaceManager.getGraph(parsed.repo);
50
- if (!graph)
439
+ // Repo must exist before we allocate anything.
440
+ if (!this.workspaceManager.getGraph(parsed.repo))
51
441
  return null;
52
- let diskContent = '';
53
- try {
54
- const entity = graph.get(parsed.entityType, parsed.entityId);
55
- diskContent = entity?.document?.content ?? '';
56
- }
57
- catch {
58
- // Entity not found — start with empty doc
59
- }
60
442
  const ydoc = new Y.Doc();
61
- const ytext = ydoc.getText('content');
62
443
  const awareness = new awarenessProtocol.Awareness(ydoc);
63
- // Seed Y.Doc with disk content (server is the single seeding authority)
64
- if (diskContent.length > 0) {
65
- ydoc.transact(() => {
66
- ytext.insert(0, diskContent);
67
- }, 'server-seed');
444
+ let seeded = false;
445
+ let mdRevisionHash = '';
446
+ if (this.persistence) {
447
+ try {
448
+ const loaded = await this.persistence.load(docName);
449
+ if (loaded) {
450
+ // Tag the load with a known origin so the persistence-write observer
451
+ // (registered below) doesn't re-encode and re-write what we just read.
452
+ Y.applyUpdate(ydoc, loaded.state, 'persistence-load');
453
+ seeded = true;
454
+ mdRevisionHash = loaded.meta.mdRevisionHash;
455
+ // Reconcile snapshot vs current .md. If the .md was rewritten while
456
+ // the server was down (agent script, git pull, manual edit), the
457
+ // snapshot is stale relative to disk — smart-merge brings the Y.Doc
458
+ // forward, preserving op continuity in unchanged regions.
459
+ const diskContent = this.readDiskContent(parsed);
460
+ const diskHash = sha256(diskContent);
461
+ if (diskHash !== mdRevisionHash) {
462
+ applyTextDiff(ydoc, ydoc.getText('content'), diskContent, 'startup-reconcile');
463
+ mdRevisionHash = diskHash;
464
+ }
465
+ }
466
+ }
467
+ catch (err) {
468
+ console.warn(`[yjs] persistence.load(${docName}) failed; falling back to .md seed`, err);
469
+ }
470
+ }
471
+ const entry = {
472
+ ydoc,
473
+ awareness,
474
+ clients: new Set(),
475
+ wsClientIds: new Map(),
476
+ seeded,
477
+ mdRevisionHash,
478
+ };
479
+ // Snapshot writer: any non-load update schedules a debounced flush.
480
+ // The hash resolver is invoked at FLUSH time, not schedule time — a
481
+ // server-side transact fires this listener before the calling code
482
+ // resumes to bump `entry.mdRevisionHash`, so capturing the hash at
483
+ // schedule time would persist the pre-mutation value. Resolver pattern
484
+ // (see HashResolver in yjs-persistence) reads the post-state at flush.
485
+ if (this.persistence) {
486
+ const persistence = this.persistence;
487
+ ydoc.on('update', (_update, origin) => {
488
+ if (origin === 'persistence-load')
489
+ return;
490
+ const e = this.docs.get(docName);
491
+ if (!e)
492
+ return;
493
+ persistence.scheduleWrite(docName, ydoc, () => {
494
+ const live = this.docs.get(docName);
495
+ return live ? live.mdRevisionHash : '';
496
+ });
497
+ });
498
+ }
499
+ // Update-broadcast observer (Phase 1a). Relays server-initiated transacts
500
+ // to every connected client. MUST be registered AFTER the persistence
501
+ // observer above so persistence's snapshot scheduling fires first — the
502
+ // flush-time hash resolver makes order non-load-bearing for correctness
503
+ // but pinning it documents intent.
504
+ //
505
+ // Origin filter: only `server-sync-disk-merge` (existing path) and
506
+ // `server-agent-write` (Phase 2 path) broadcast. `ws-client` updates are
507
+ // already relayed peer-to-peer by `handleMessage`; broadcasting them
508
+ // here would double-send. `persistence-load`, `server-seed`, and
509
+ // `startup-reconcile` either have no connected clients yet or are
510
+ // already broadcast manually.
511
+ //
512
+ // Encoding: use the listener's `update` bytes directly via
513
+ // `syncProtocol.writeUpdate`. Do NOT call `Y.encodeStateAsUpdate(ydoc, _)`
514
+ // — full-state re-encode would be wasteful and the second arg is a
515
+ // state vector, not an update.
516
+ //
517
+ // Gated by `STUDIOGRAPH_YJS_BROADCAST` (default on). When off, the
518
+ // observer is not registered; server-side writes refuse to mutate live
519
+ // docs via `assertWritable` instead (fail-closed).
520
+ if (this.broadcastEnabled) {
521
+ ydoc.on('update', (update, origin) => {
522
+ if (!BROADCAST_ORIGINS.has(origin))
523
+ return;
524
+ const e = this.docs.get(docName);
525
+ if (!e)
526
+ return;
527
+ const encoder = encoding.createEncoder();
528
+ syncProtocol.writeUpdate(encoder, update);
529
+ const payload = encoding.toUint8Array(encoder);
530
+ for (const client of e.clients) {
531
+ if (client.readyState !== 1)
532
+ continue;
533
+ try {
534
+ this.sendToClient(client, docName, MSG_SYNC, payload);
535
+ }
536
+ catch { /* per-client send failures must not break the relay loop */ }
537
+ }
538
+ });
68
539
  }
69
- const entry = { ydoc, awareness, clients: new Set() };
70
540
  this.docs.set(docName, entry);
71
541
  return entry;
72
542
  }
543
+ readDiskContent(parsed) {
544
+ try {
545
+ const graph = this.workspaceManager.getGraph(parsed.repo);
546
+ if (!graph)
547
+ return '';
548
+ const entity = graph.get(parsed.entityType, parsed.entityId);
549
+ return entity?.document?.content ?? '';
550
+ }
551
+ catch {
552
+ return '';
553
+ }
554
+ }
73
555
  /**
74
- * Add a client to a document. Sends initial sync state to the client.
556
+ * Send a JSON `doc_ready` notice to every connected client of `docName`,
557
+ * carrying the authoritative ytext length the client should match before
558
+ * unlocking its editor. This is the seed-success heartbeat the client
559
+ * uses to confirm its local apply actually landed — without it, a frame
560
+ * that arrived but failed to decode (e.g. Safari/WebKit fragmentation
561
+ * issue) would silently leave the editor unlocked on an empty Y.Doc and
562
+ * the next keystroke + autosave would overwrite the disk file.
75
563
  */
76
- addClient(docName, ws) {
77
- const entry = this.getOrCreate(docName);
564
+ broadcastDocReady(docName) {
565
+ const entry = this.docs.get(docName);
78
566
  if (!entry)
79
567
  return;
568
+ const expectedLength = entry.ydoc.getText('content').length;
569
+ const msg = JSON.stringify({ type: 'doc_ready', docName, expectedLength });
570
+ for (const client of entry.clients) {
571
+ if (client.readyState !== 1)
572
+ continue;
573
+ try {
574
+ client.send(msg);
575
+ }
576
+ catch { /* non-fatal */ }
577
+ }
578
+ }
579
+ /**
580
+ * Send `doc_ready` to a single client. Used in addClient when the entry
581
+ * is already seeded — the new joiner needs the heartbeat to unlock its
582
+ * editor without waiting for the next state transition.
583
+ */
584
+ sendDocReadyToClient(docName, ws) {
585
+ const entry = this.docs.get(docName);
586
+ if (!entry || ws.readyState !== 1)
587
+ return;
588
+ const expectedLength = entry.ydoc.getText('content').length;
589
+ try {
590
+ ws.send(JSON.stringify({ type: 'doc_ready', docName, expectedLength }));
591
+ }
592
+ catch { /* non-fatal */ }
593
+ }
594
+ /**
595
+ * If the Y.Doc is still empty (no client sync has populated it), load
596
+ * content from disk and mark the entry as seeded. Broadcast the seeded
597
+ * state to all connected clients as a sync-step-2 so they see it.
598
+ *
599
+ * Runs ~SEED_WAIT_MS after a client connects. Short-circuits if any
600
+ * earlier sync already flipped the `seeded` flag.
601
+ */
602
+ maybeSeedFromDisk(docName) {
603
+ const entry = this.docs.get(docName);
604
+ if (!entry || entry.seeded)
605
+ return;
606
+ const ytext = entry.ydoc.getText('content');
607
+ if (ytext.length > 0) {
608
+ // A client sync populated the doc during the wait — nothing to do.
609
+ entry.seeded = true;
610
+ this.broadcastDocReady(docName);
611
+ return;
612
+ }
613
+ const parsed = this.parseDocName(docName);
614
+ if (!parsed)
615
+ return;
616
+ const diskContent = this.readDiskContent(parsed);
617
+ if (diskContent.length === 0) {
618
+ entry.seeded = true;
619
+ entry.mdRevisionHash = sha256('');
620
+ this.broadcastDocReady(docName);
621
+ return;
622
+ }
623
+ entry.ydoc.transact(() => {
624
+ ytext.insert(0, diskContent);
625
+ }, 'server-seed');
626
+ entry.seeded = true;
627
+ entry.mdRevisionHash = sha256(diskContent);
628
+ // Broadcast the newly-seeded state to every connected client so they
629
+ // see the content. Writing sync-step-2 from the now-populated Y.Doc
630
+ // sends the delta (the characters we just inserted).
631
+ const encoder = encoding.createEncoder();
632
+ syncProtocol.writeSyncStep2(encoder, entry.ydoc);
633
+ const payload = encoding.toUint8Array(encoder);
634
+ for (const client of entry.clients) {
635
+ if (client.readyState !== 1)
636
+ continue;
637
+ this.sendToClient(client, docName, MSG_SYNC, payload);
638
+ }
639
+ // Heartbeat: tell clients the authoritative length so they only unlock
640
+ // their editor if their local apply matches. Without this, a client that
641
+ // received the broadcast but failed to decode it (Safari fragmentation
642
+ // bug) would unlock on an empty Y.Doc and overwrite disk on next save.
643
+ this.broadcastDocReady(docName);
644
+ }
645
+ /**
646
+ * Add a client to a document. Async because `getOrCreate` may need to load a
647
+ * persisted snapshot from disk.
648
+ *
649
+ * Protocol (ordered carefully to make first paint resilient):
650
+ * 1. Server: load doc (snapshot or fresh) — `getOrCreate`.
651
+ * 2. Server: send sync-step-1 + sync-step-2 (full state) + awareness
652
+ * FIRST. The client's editor populates and unlocks the moment the
653
+ * sync-step-2 lands; it doesn't need to wait for the ack to render.
654
+ * 3. Server: send `collab:joined` ack JSON LAST. This tells the client
655
+ * it's safe to send its own sync-step-1 + awareness, the load-race
656
+ * protection codex flagged. Sending content before the ack means a
657
+ * delayed/dropped ack still leaves the editor populated — only the
658
+ * client's outbound state vector is gated.
659
+ * 4. Client: receives sync-step-2 → editor renders. Then `collab:joined`
660
+ * → client sends its own sync-step-1 + awareness.
661
+ * 5. Server: applies client sync, relays to peers.
662
+ */
663
+ async addClient(docName, ws) {
664
+ const entry = await this.getOrCreate(docName);
665
+ if (!entry) {
666
+ // Couldn't find or create the doc (unknown repo, etc). Don't ack —
667
+ // client will time out waiting and remain in its readonly seed-gate state.
668
+ return;
669
+ }
670
+ // Cancel idle destruction timer — a client is joining.
671
+ if (entry.idleTimer) {
672
+ clearTimeout(entry.idleTimer);
673
+ entry.idleTimer = undefined;
674
+ }
80
675
  entry.clients.add(ws);
81
- // Send sync-step-1 to the new client (our state vector)
82
- // so the client can respond with what we're missing (sync-step-2)
676
+ // Send sync-step-1 (our state vector) so the client can reply with what
677
+ // we're missing.
83
678
  const encoder = encoding.createEncoder();
84
679
  syncProtocol.writeSyncStep1(encoder, entry.ydoc);
85
680
  this.sendToClient(ws, docName, MSG_SYNC, encoding.toUint8Array(encoder));
86
- // Also send sync-step-2 immediately (our full state)
87
- // so the client gets our content without a round trip
681
+ // Send sync-step-2 (our full state) so the client gets our content
682
+ // without a round trip this is what unlocks the editor on the client.
88
683
  const encoder2 = encoding.createEncoder();
89
684
  syncProtocol.writeSyncStep2(encoder2, entry.ydoc);
90
685
  this.sendToClient(ws, docName, MSG_SYNC, encoding.toUint8Array(encoder2));
91
- // Send current awareness states to the new client
686
+ // Existing peer cursors.
92
687
  const awarenessStates = entry.awareness.getStates();
93
688
  if (awarenessStates.size > 0) {
94
689
  const clients = Array.from(awarenessStates.keys());
95
690
  const update = awarenessProtocol.encodeAwarenessUpdate(entry.awareness, clients);
96
691
  this.sendToClient(ws, docName, MSG_AWARENESS, update);
97
692
  }
693
+ // If we're joining an already-seeded doc (a peer is already editing),
694
+ // the new client needs the doc_ready heartbeat right away so it can
695
+ // unlock once the sync-step-2 we just sent lands locally. Without this,
696
+ // a late joiner would stay readonly forever waiting for a transition
697
+ // that already happened.
698
+ if (entry.seeded) {
699
+ this.sendDocReadyToClient(docName, ws);
700
+ }
701
+ // Ack the join AFTER content + heartbeat. The ack is what tells the
702
+ // client it's safe to send its own sync-step-1 + awareness. Sending
703
+ // content before the ack means editor first-paint can survive a
704
+ // delayed or lost ack. (doc_ready above unlocks the editor; this ack
705
+ // unlocks outbound traffic.)
706
+ try {
707
+ ws.send(JSON.stringify({ type: 'collab:joined', docName }));
708
+ }
709
+ catch { /* WS might have closed mid-load — non-fatal */ }
710
+ // Deferred disk seed. If the client has its own state (reconnect after
711
+ // server restart but before persistence existed, or persistence disabled),
712
+ // their sync-step-2 will populate the Y.Doc before this timer fires and
713
+ // maybeSeedFromDisk becomes a no-op. If they don't (first-ever open),
714
+ // we seed and broadcast.
715
+ if (!entry.seeded && !entry.seedTimer) {
716
+ entry.seedTimer = setTimeout(() => {
717
+ entry.seedTimer = undefined;
718
+ this.maybeSeedFromDisk(docName);
719
+ }, SEED_WAIT_MS);
720
+ }
98
721
  }
99
722
  /**
100
723
  * Remove a client from a document. Destroys Y.Doc when last client leaves.
@@ -103,11 +726,55 @@ export class YjsManager {
103
726
  const entry = this.docs.get(docName);
104
727
  if (!entry)
105
728
  return;
729
+ // Remove awareness states owned by this WS and broadcast removal to remaining clients
730
+ const clientIds = entry.wsClientIds.get(ws);
731
+ if (clientIds && clientIds.size > 0) {
732
+ const ids = Array.from(clientIds);
733
+ // Remove states (sets them to null internally) then encode the removal update
734
+ awarenessProtocol.removeAwarenessStates(entry.awareness, ids, 'ws-close');
735
+ // After removal, states are null — encodeAwarenessUpdate will encode null states
736
+ // which tells peers to remove those cursors. Meta still has the clock.
737
+ try {
738
+ const update = awarenessProtocol.encodeAwarenessUpdate(entry.awareness, ids);
739
+ for (const client of entry.clients) {
740
+ if (client === ws || client.readyState !== 1)
741
+ continue;
742
+ this.sendToClient(client, docName, MSG_AWARENESS, update);
743
+ }
744
+ }
745
+ catch { /* meta missing for some clients — states are already removed locally */ }
746
+ }
747
+ entry.wsClientIds.delete(ws);
106
748
  entry.clients.delete(ws);
107
749
  if (entry.clients.size === 0) {
108
- entry.awareness.destroy();
109
- entry.ydoc.destroy();
110
- this.docs.delete(docName);
750
+ // Don't destroy immediately — wait for grace period so reconnecting
751
+ // clients can resume the same Y.Doc without re-seeding (which causes
752
+ // content duplication due to mismatched Yjs state).
753
+ entry.idleTimer = setTimeout(() => {
754
+ // Only destroy if still idle (no new clients joined)
755
+ if (entry.clients.size === 0) {
756
+ if (entry.seedTimer) {
757
+ clearTimeout(entry.seedTimer);
758
+ entry.seedTimer = undefined;
759
+ }
760
+ this.docs.delete(docName);
761
+ // Drain pending persistence writes BEFORE destroying the Y.Doc — a
762
+ // debounced flush could still be holding a reference and we want
763
+ // its bytes to land on disk. Destroy is async, but we don't await
764
+ // here (the timer callback is fire-and-forget); the persistence
765
+ // layer's per-doc chain serializes writes anyway.
766
+ if (this.persistence) {
767
+ this.persistence.drain(docName).finally(() => {
768
+ entry.awareness.destroy();
769
+ entry.ydoc.destroy();
770
+ });
771
+ }
772
+ else {
773
+ entry.awareness.destroy();
774
+ entry.ydoc.destroy();
775
+ }
776
+ }
777
+ }, DOC_IDLE_TIMEOUT);
111
778
  }
112
779
  }
113
780
  /**
@@ -130,10 +797,44 @@ export class YjsManager {
130
797
  if (!entry)
131
798
  return;
132
799
  if (msgType === MSG_SYNC) {
133
- // Apply sync message to server Y.Doc
800
+ // Phase 2: if a server-side write holds the per-doc lock, queue the
801
+ // client sync frame instead of applying it. The Codex pass-3 #1 trace
802
+ // showed that applying a client insert mid-lock leaves the just-typed
803
+ // chars in ytext, and the subsequent applyAgentContent diff against
804
+ // the agent's target deletes them. Queueing defers application until
805
+ // AFTER applyAgentContent — the insert then lands as a fresh CRDT op
806
+ // at its original anchor on top of the new agent content, producing
807
+ // "AAA → client X → agent BBB → final BBBX" instead of "BBB".
808
+ if (this.isLocked(docName)) {
809
+ this.enqueueMsgSync(docName, sender, payload);
810
+ return;
811
+ }
812
+ // Apply sync message to server Y.Doc. The client is gated readonly
813
+ // until it receives our doc_ready (with expectedLength matching the
814
+ // seeded ytext.length), so a keystroke can't race the deferred-seed
815
+ // window into the server. Reconnect clients with retained state push
816
+ // it via sync-step-2 here, which marks `seeded = true` below and the
817
+ // deferred-seed timer becomes a no-op.
134
818
  const decoder = decoding.createDecoder(payload);
135
819
  const encoder = encoding.createEncoder();
136
820
  syncProtocol.readSyncMessage(decoder, encoder, entry.ydoc, 'ws-client');
821
+ // If a client's sync populated the Y.Doc, suppress the deferred
822
+ // disk seed — otherwise we'd double-insert the same content via
823
+ // the CRDT. Record the current disk hash so the persistence snapshot
824
+ // has a baseline for future divergence detection.
825
+ if (!entry.seeded && entry.ydoc.getText('content').length > 0) {
826
+ entry.seeded = true;
827
+ if (entry.seedTimer) {
828
+ clearTimeout(entry.seedTimer);
829
+ entry.seedTimer = undefined;
830
+ }
831
+ const parsed = this.parseDocName(docName);
832
+ if (parsed)
833
+ entry.mdRevisionHash = sha256(this.readDiskContent(parsed));
834
+ // Tell every client (including the sender) the new authoritative
835
+ // length so their editors can unlock on a verified seed.
836
+ this.broadcastDocReady(docName);
837
+ }
137
838
  // If the sync produced a response, send it back to the sender
138
839
  if (encoding.length(encoder) > 0) {
139
840
  this.sendToClient(sender, docName, MSG_SYNC, encoding.toUint8Array(encoder));
@@ -146,6 +847,27 @@ export class YjsManager {
146
847
  }
147
848
  }
148
849
  else if (msgType === MSG_AWARENESS) {
850
+ // Track which awareness clientIDs belong to this WS
851
+ try {
852
+ const decoder = decoding.createDecoder(payload);
853
+ const len = decoding.readVarUint(decoder);
854
+ for (let i = 0; i < len; i++) {
855
+ const clientId = decoding.readVarUint(decoder);
856
+ let ids = entry.wsClientIds.get(sender);
857
+ if (!ids) {
858
+ ids = new Set();
859
+ entry.wsClientIds.set(sender, ids);
860
+ }
861
+ ids.add(clientId);
862
+ // Skip the rest of this entry (clock + state JSON)
863
+ decoding.readVarUint(decoder); // clock
864
+ const stateJson = decoding.readVarString(decoder);
865
+ // If state is null/empty, client is leaving — remove from tracking
866
+ if (stateJson === 'null' || stateJson.length === 0)
867
+ ids.delete(clientId);
868
+ }
869
+ }
870
+ catch { /* best-effort tracking, don't break relay */ }
149
871
  // Apply awareness to server's awareness instance
150
872
  awarenessProtocol.applyAwarenessUpdate(entry.awareness, payload, sender);
151
873
  // Relay to all OTHER clients
@@ -157,9 +879,18 @@ export class YjsManager {
157
879
  }
158
880
  }
159
881
  /**
160
- * Encode and send a framed binary message to a client.
882
+ * Encode and send a framed binary message to a client. Payloads above
883
+ * `MAX_CHUNK_PAYLOAD` are split into MSG_CHUNK frames; smaller ones go
884
+ * through the single-frame fast path unchanged.
161
885
  */
162
886
  sendToClient(ws, docName, msgType, payload) {
887
+ if (payload.length <= MAX_CHUNK_PAYLOAD) {
888
+ this.sendSingleFrame(ws, docName, msgType, payload);
889
+ return;
890
+ }
891
+ this.sendChunkedFrames(ws, docName, msgType, payload);
892
+ }
893
+ sendSingleFrame(ws, docName, msgType, payload) {
163
894
  const nameBytes = Buffer.from(docName, 'utf8');
164
895
  const frame = Buffer.alloc(2 + nameBytes.length + 1 + payload.length);
165
896
  frame.writeUInt16BE(nameBytes.length, 0);
@@ -171,6 +902,54 @@ export class YjsManager {
171
902
  }
172
903
  catch { /* non-fatal */ }
173
904
  }
905
+ sendChunkedFrames(ws, docName, msgType, payload) {
906
+ const total = Math.ceil(payload.length / MAX_CHUNK_PAYLOAD);
907
+ if (total > 0xFFFF) {
908
+ // Logical message larger than 65535 chunks (~256MB at 4KB chunks).
909
+ // Falling back to a single frame is no worse than the pre-chunking
910
+ // behavior, and we'd rather not silently truncate.
911
+ console.warn(`[yjs] payload too large to chunk (${payload.length} bytes, ${total} chunks); sending single frame`);
912
+ this.sendSingleFrame(ws, docName, msgType, payload);
913
+ return;
914
+ }
915
+ // 4-byte random message ID — collision risk is negligible within the
916
+ // ~30s reassembly window the client tolerates.
917
+ const msgId = Buffer.from([
918
+ Math.floor(Math.random() * 256),
919
+ Math.floor(Math.random() * 256),
920
+ Math.floor(Math.random() * 256),
921
+ Math.floor(Math.random() * 256),
922
+ ]);
923
+ const nameBytes = Buffer.from(docName, 'utf8');
924
+ for (let seq = 0; seq < total; seq++) {
925
+ const start = seq * MAX_CHUNK_PAYLOAD;
926
+ const end = Math.min(start + MAX_CHUNK_PAYLOAD, payload.length);
927
+ const chunk = payload.subarray(start, end);
928
+ // Frame: [2B nameLen][docName][1B MSG_CHUNK][4B msgId][2B seq][2B total][1B origMsgType][chunk]
929
+ const headerLen = 2 + nameBytes.length + 1 + 4 + 2 + 2 + 1;
930
+ const frame = Buffer.alloc(headerLen + chunk.length);
931
+ let off = 0;
932
+ frame.writeUInt16BE(nameBytes.length, off);
933
+ off += 2;
934
+ nameBytes.copy(frame, off);
935
+ off += nameBytes.length;
936
+ frame[off] = MSG_CHUNK;
937
+ off += 1;
938
+ msgId.copy(frame, off);
939
+ off += 4;
940
+ frame.writeUInt16BE(seq, off);
941
+ off += 2;
942
+ frame.writeUInt16BE(total, off);
943
+ off += 2;
944
+ frame[off] = msgType;
945
+ off += 1;
946
+ Buffer.from(chunk).copy(frame, off);
947
+ try {
948
+ ws.send(frame);
949
+ }
950
+ catch { /* non-fatal */ }
951
+ }
952
+ }
174
953
  /**
175
954
  * Get current Y.Doc text content for a document (for debugging/autosave).
176
955
  */
@@ -181,10 +960,102 @@ export class YjsManager {
181
960
  return entry.ydoc.getText('content').toString();
182
961
  }
183
962
  /**
184
- * Destroy all Y.Docs (server shutdown).
963
+ * Authoritative live body for a document, or null when there's nothing
964
+ * trustworthy to read. Unlike {@link getText}, this returns null unless the
965
+ * entry exists AND is seeded — an unseeded Y.Doc carries Y.Text='' before
966
+ * its first client sync, and reporting that as the body would masquerade an
967
+ * empty doc as a real (empty) entry.
968
+ *
969
+ * This is the read side of the live-vs-disk gap: a user's freshly-placed
970
+ * image/asset embed lives in the Y.Doc and only reaches disk after the
971
+ * autosave debounce + commit. `graph.get` reads disk, so callers that need
972
+ * to see what the user is actually looking at (get_entity, the asset-drop
973
+ * guard) consult this first and fall back to disk when it returns null.
974
+ */
975
+ peekLiveBody(docName) {
976
+ const entry = this.docs.get(docName);
977
+ if (!entry || !entry.seeded)
978
+ return null;
979
+ return entry.ydoc.getText('content').toString();
980
+ }
981
+ /**
982
+ * Reconcile an active Y.Doc with the latest .md file on disk. EXPLICIT
983
+ * external-disk-change primitive — call this from named sites only:
984
+ * startup boot, git-pull event handlers, dev-tools "reload from disk".
985
+ *
986
+ * NOT called from the normal write path. Server-side body writes (MCP,
987
+ * agent, event processor) route through {@link applyAgentContent}, which
988
+ * applies the target body under the per-doc lock AFTER disk + commit
989
+ * land. Reconcile here is for changes the server didn't originate.
990
+ *
991
+ * Uses Yjs-aware text diffing (see {@link applyTextDiff}). Chars in
992
+ * UNCHANGED regions retain their original `(clientID, clock)`. Cursor
993
+ * anchors via `Y.createRelativePositionFromTypeIndex` in unchanged regions
994
+ * stay valid. Y.UndoManager stacks referencing those chars stay coherent.
995
+ *
996
+ * KNOWN LIMIT: chars in CHANGED regions are still discarded. If a user has
997
+ * typed `world ` into a "Hello " doc but autosave hasn't fired yet, the
998
+ * Y.Doc has "Hello world " while disk still has "Hello ". When an external
999
+ * write lands "Hi " on disk and we reconcile, the diff becomes
1000
+ * `[delete "Hello "][insert "Hi "][equal "world "]`. The user's "world "
1001
+ * survives because it's an unchanged region; their typing in the head is
1002
+ * gone because that's the changed region. This is the irreducible residue
1003
+ * of "make ytext match disk" semantics for external sources.
1004
+ *
1005
+ * No-ops when no Y.Doc is currently active for docName — clients that open
1006
+ * later will pick up the .md content via fresh seeding in `getOrCreate`.
1007
+ */
1008
+ reconcileFromDisk(docName) {
1009
+ const entry = this.docs.get(docName);
1010
+ if (!entry) {
1011
+ console.log(`[yjs] reconcileFromDisk: no active doc for ${docName} — client will seed from disk on next visit`);
1012
+ return;
1013
+ }
1014
+ const parsed = this.parseDocName(docName);
1015
+ if (!parsed)
1016
+ return;
1017
+ const diskContent = this.readDiskContent(parsed);
1018
+ const ytext = entry.ydoc.getText('content');
1019
+ if (ytext.toString() === diskContent) {
1020
+ // Still want to keep mdRevisionHash in sync even on a no-op so the
1021
+ // persistence layer's divergence-detection logic doesn't false-fire.
1022
+ entry.mdRevisionHash = sha256(diskContent);
1023
+ return;
1024
+ }
1025
+ console.log(`[yjs] reconcileFromDisk: smart-merging ${docName} (${diskContent.length} chars, ${entry.clients.size} clients)`);
1026
+ applyTextDiff(entry.ydoc, ytext, diskContent, 'server-sync-disk-merge');
1027
+ entry.mdRevisionHash = sha256(diskContent);
1028
+ // Refresh clients' expected-length heartbeat so editors that were locked
1029
+ // due to a previous failed seed can unlock on the broadcast update.
1030
+ this.broadcastDocReady(docName);
1031
+ }
1032
+ /**
1033
+ * Record that the .md body for an entity was just written to disk. Called
1034
+ * from `graph.update`'s `onBodyWritten` callback.
1035
+ *
1036
+ * Updates `entry.mdRevisionHash` if the doc is currently loaded so the
1037
+ * next persistence snapshot captures the post-write state. No-op when
1038
+ * the doc isn't loaded — the next `doLoad` will compute the hash from
1039
+ * the disk content on demand.
1040
+ */
1041
+ recordDiskBody(docName, body) {
1042
+ const entry = this.docs.get(docName);
1043
+ if (!entry)
1044
+ return;
1045
+ entry.mdRevisionHash = sha256(body);
1046
+ }
1047
+ /**
1048
+ * Destroy all Y.Docs (server shutdown). Drains pending persistence writes
1049
+ * before tearing down so a debounced snapshot can't be lost on shutdown.
185
1050
  */
186
- destroy() {
1051
+ async destroy() {
1052
+ if (this.persistence)
1053
+ await this.persistence.destroy();
187
1054
  for (const [, entry] of this.docs) {
1055
+ if (entry.idleTimer)
1056
+ clearTimeout(entry.idleTimer);
1057
+ if (entry.seedTimer)
1058
+ clearTimeout(entry.seedTimer);
188
1059
  entry.awareness.destroy();
189
1060
  entry.ydoc.destroy();
190
1061
  }