studiograph 1.3.47 → 1.3.48-beta.0

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 (1057) 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.DDqq11xY.css +2 -0
  477. package/dist/web/_app/immutable/assets/12.DlIf1mKh.css +1 -0
  478. package/dist/web/_app/immutable/assets/13.7d-Q37wc.css +1 -0
  479. package/dist/web/_app/immutable/assets/14.CmLrbzZp.css +1 -0
  480. package/dist/web/_app/immutable/assets/2.CGK2ky-K.css +1 -0
  481. package/dist/web/_app/immutable/assets/3.CV0abekd.css +1 -0
  482. package/dist/web/_app/immutable/assets/4.fGsEpo95.css +1 -0
  483. package/dist/web/_app/immutable/assets/AgentOverlay.DqzjAOm4.css +1 -0
  484. package/dist/web/_app/immutable/assets/AssetManagerModal.BKJfPAPk.css +1 -0
  485. package/dist/web/_app/immutable/assets/CalendarView.bNewSxkH.css +1 -0
  486. package/dist/web/_app/immutable/assets/FolderMembersPanel.DX1oBeF_.css +1 -0
  487. package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
  488. package/dist/web/_app/immutable/assets/FolderPicker.B5KdvRYl.css +1 -0
  489. package/dist/web/_app/immutable/assets/GalleryView.DgvSjS0I.css +1 -0
  490. package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
  491. package/dist/web/_app/immutable/assets/KanbanView.D0QbZFd6.css +1 -0
  492. package/dist/web/_app/immutable/assets/Markdown.B4lW7Llh.css +1 -0
  493. package/dist/web/_app/immutable/assets/SettingsDialog.DYWYMFSO.css +1 -0
  494. package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
  495. package/dist/web/_app/immutable/assets/StopFilledAlt.clodJdp5.css +1 -0
  496. package/dist/web/_app/immutable/assets/TimelineView.DA-H6dvv.css +1 -0
  497. package/dist/web/_app/immutable/assets/WorkspaceView.BS1ildu7.css +1 -0
  498. package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
  499. package/dist/web/_app/immutable/assets/formatting.B912lpdG.css +1 -0
  500. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.CvHOgSBP.woff +0 -0
  501. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.DMJ8VG8y.woff2 +0 -0
  502. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.CB9ihrfo.woff +0 -0
  503. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.DSY6xOcd.woff2 +0 -0
  504. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CZTNEAuW.woff2 +0 -0
  505. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CsGl1sm0.woff +0 -0
  506. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CDDApCn2.woff2 +0 -0
  507. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CYLoc0-x.woff +0 -0
  508. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.BNK2_mGO.woff2 +0 -0
  509. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.DpEwFAQM.woff +0 -0
  510. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.6ng42L7E.woff2 +0 -0
  511. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.BgVn5rGT.woff +0 -0
  512. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.Cu4Hd6ag.woff +0 -0
  513. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.CuJfVYMP.woff2 +0 -0
  514. package/dist/web/_app/immutable/assets/inline-list.cqga56xT.css +1 -0
  515. package/dist/web/_app/immutable/assets/list-columns.DCMVmy_Q.css +1 -0
  516. package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
  517. package/dist/web/_app/immutable/assets/sheet.DJPuqnTg.css +1 -0
  518. package/dist/web/_app/immutable/assets/speech-dictation.C5CYFhS1.css +1 -0
  519. package/dist/web/_app/immutable/chunks/0iDDDyaZ.js +1 -0
  520. package/dist/web/_app/immutable/chunks/2LgrBrpS2.js +2 -0
  521. package/dist/web/_app/immutable/chunks/3EfPAYzi2.js +1 -0
  522. package/dist/web/_app/immutable/chunks/7Bu427my2.js +184 -0
  523. package/dist/web/_app/immutable/chunks/96h3ktuk.js +1 -0
  524. package/dist/web/_app/immutable/chunks/A6FJA1AF.js +1 -0
  525. package/dist/web/_app/immutable/chunks/B-FAwCqe2.js +1 -0
  526. package/dist/web/_app/immutable/chunks/B-V5eMSw2.js +1 -0
  527. package/dist/web/_app/immutable/chunks/B-i9_YVM.js +1 -0
  528. package/dist/web/_app/immutable/chunks/B15-kvCe2.js +1 -0
  529. package/dist/web/_app/immutable/chunks/B1KZ7zY32.js +2 -0
  530. package/dist/web/_app/immutable/chunks/B4gpzeQ2.js +1 -0
  531. package/dist/web/_app/immutable/chunks/B6Lt-qaJ2.js +1 -0
  532. package/dist/web/_app/immutable/chunks/B7tbGyiU2.js +1 -0
  533. package/dist/web/_app/immutable/chunks/BBxt8lpa.js +1 -0
  534. package/dist/web/_app/immutable/chunks/BCaRi2AF.js +1 -0
  535. package/dist/web/_app/immutable/chunks/BJ6Z7eAM.js +2 -0
  536. package/dist/web/_app/immutable/chunks/BM_vIwVC.js +83 -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/BVnuLlVg.js +1 -0
  541. package/dist/web/_app/immutable/chunks/BddNmQ8j.js +1 -0
  542. package/dist/web/_app/immutable/chunks/BeuunHPO.js +1 -0
  543. package/dist/web/_app/immutable/chunks/BhTmSo4n2.js +1 -0
  544. package/dist/web/_app/immutable/chunks/BikW7mty2.js +1 -0
  545. package/dist/web/_app/immutable/chunks/BkyFvJvz.js +1 -0
  546. package/dist/web/_app/immutable/chunks/BlyFGPFV.js +22 -0
  547. package/dist/web/_app/immutable/chunks/Bo5dghSu.js +3 -0
  548. package/dist/web/_app/immutable/chunks/BpPyho8Y.js +3 -0
  549. package/dist/web/_app/immutable/chunks/BsuvyNDN2.js +2 -0
  550. package/dist/web/_app/immutable/chunks/BuKi0vpu2.js +7 -0
  551. package/dist/web/_app/immutable/chunks/BuuYnIjE.js +1 -0
  552. package/dist/web/_app/immutable/chunks/By4lVKNC.js +2 -0
  553. package/dist/web/_app/immutable/chunks/ByQGCIwO.js +5 -0
  554. package/dist/web/_app/immutable/chunks/ByidpUhu.js +1 -0
  555. package/dist/web/_app/immutable/chunks/C35TIzaB.js +1 -0
  556. package/dist/web/_app/immutable/chunks/C5dM5op-.js +1 -0
  557. package/dist/web/_app/immutable/chunks/C6Nx0jpM.js +1 -0
  558. package/dist/web/_app/immutable/chunks/C6pVyOEl2.js +1 -0
  559. package/dist/web/_app/immutable/chunks/C80GKPZ9.js +1 -0
  560. package/dist/web/_app/immutable/chunks/C94TJqPI.js +1 -0
  561. package/dist/web/_app/immutable/chunks/C9PETsiT.js +1 -0
  562. package/dist/web/_app/immutable/chunks/CAuAQ81a2.js +1 -0
  563. package/dist/web/_app/immutable/chunks/CBnzSITi2.js +1 -0
  564. package/dist/web/_app/immutable/chunks/CC9p2p6w.js +1 -0
  565. package/dist/web/_app/immutable/chunks/CCLR-AJL2.js +185 -0
  566. package/dist/web/_app/immutable/chunks/CD0X7XPW.js +6 -0
  567. package/dist/web/_app/immutable/chunks/CDTjuBSm.js +1 -0
  568. package/dist/web/_app/immutable/chunks/CH-KYFIm.js +64 -0
  569. package/dist/web/_app/immutable/chunks/CHj8fObQ2.js +9 -0
  570. package/dist/web/_app/immutable/chunks/CK-UnH-n2.js +1 -0
  571. package/dist/web/_app/immutable/chunks/CKH5BEAh.js +1 -0
  572. package/dist/web/_app/immutable/chunks/CPSupDJp2.js +2 -0
  573. package/dist/web/_app/immutable/chunks/CSUrYOis.js +1 -0
  574. package/dist/web/_app/immutable/chunks/CYTTTma0.js +3 -0
  575. package/dist/web/_app/immutable/chunks/Cbaut_us2.js +1 -0
  576. package/dist/web/_app/immutable/chunks/CiIpSx5n2.js +1 -0
  577. package/dist/web/_app/immutable/chunks/CkLfUXwy.js +1 -0
  578. package/dist/web/_app/immutable/chunks/CokE4L8B2.js +1 -0
  579. package/dist/web/_app/immutable/chunks/CpLdnbh3.js +1 -0
  580. package/dist/web/_app/immutable/chunks/CvDrXJk9.js +1 -0
  581. package/dist/web/_app/immutable/chunks/D00MFB9_2.js +1 -0
  582. package/dist/web/_app/immutable/chunks/D41CbXmM.js +1 -0
  583. package/dist/web/_app/immutable/chunks/D5Hj-MPO2.js +1 -0
  584. package/dist/web/_app/immutable/chunks/D6nLEmZy2.js +1 -0
  585. package/dist/web/_app/immutable/chunks/D71ZlQBM2.js +2 -0
  586. package/dist/web/_app/immutable/chunks/D9ql9vXU.js +1 -0
  587. package/dist/web/_app/immutable/chunks/DAXW5iLp.js +1 -0
  588. package/dist/web/_app/immutable/chunks/DBzQ8LyQ2.js +2 -0
  589. package/dist/web/_app/immutable/chunks/DIb5rAPU2.js +1 -0
  590. package/dist/web/_app/immutable/chunks/DOmH4G9o.js +14 -0
  591. package/dist/web/_app/immutable/chunks/DQMWa2t72.js +1 -0
  592. package/dist/web/_app/immutable/chunks/DRsswX8S.js +1 -0
  593. package/dist/web/_app/immutable/chunks/DTCHhxD5.js +1 -0
  594. package/dist/web/_app/immutable/chunks/DUwgGBxa.js +1 -0
  595. package/dist/web/_app/immutable/chunks/DVcy5Pp82.js +1 -0
  596. package/dist/web/_app/immutable/chunks/DWygwzcO.js +1 -0
  597. package/dist/web/_app/immutable/chunks/DYXDRmoo.js +1 -0
  598. package/dist/web/_app/immutable/chunks/DZ-YyRVM.js +1 -0
  599. package/dist/web/_app/immutable/chunks/D_HVOuHV.js +1 -0
  600. package/dist/web/_app/immutable/chunks/DaoOQFPb.js +1 -0
  601. package/dist/web/_app/immutable/chunks/DdLkNvPf.js +23 -0
  602. package/dist/web/_app/immutable/chunks/DiMQob8p.js +1 -0
  603. package/dist/web/_app/immutable/chunks/DiQJ9DLy.js +1 -0
  604. package/dist/web/_app/immutable/chunks/DlORZqfE.js +1 -0
  605. package/dist/web/_app/immutable/chunks/DmeYl7eL.js +2 -0
  606. package/dist/web/_app/immutable/chunks/Dng3OcRd2.js +1 -0
  607. package/dist/web/_app/immutable/chunks/DoKMFfJd.js +1 -0
  608. package/dist/web/_app/immutable/chunks/DpzG2mVI2.js +1 -0
  609. package/dist/web/_app/immutable/chunks/DvJSCDuZ2.js +1 -0
  610. package/dist/web/_app/immutable/chunks/DvPuaTCl2.js +5 -0
  611. package/dist/web/_app/immutable/chunks/ItgU4ei5.js +1 -0
  612. package/dist/web/_app/immutable/chunks/JJDMrjj62.js +1 -0
  613. package/dist/web/_app/immutable/chunks/OTTMDMTW.js +1 -0
  614. package/dist/web/_app/immutable/chunks/RmiWpCin2.js +1 -0
  615. package/dist/web/_app/immutable/chunks/ZTiqmKJy2.js +1 -0
  616. package/dist/web/_app/immutable/chunks/ahC5WoXX2.js +1 -0
  617. package/dist/web/_app/immutable/chunks/e3SY5t2O2.js +2692 -0
  618. package/dist/web/_app/immutable/chunks/g09ZrevW.js +1 -0
  619. package/dist/web/_app/immutable/chunks/go8N1nWD2.js +3 -0
  620. package/dist/web/_app/immutable/chunks/nTAmRNKw2.js +1 -0
  621. package/dist/web/_app/immutable/chunks/oBQOivfH2.js +1 -0
  622. package/dist/web/_app/immutable/chunks/oUTRxd0f.js +1 -0
  623. package/dist/web/_app/immutable/chunks/s_7BJJYy.js +2 -0
  624. package/dist/web/_app/immutable/chunks/uuFM-ygL.js +1 -0
  625. package/dist/web/_app/immutable/chunks/v7me-ydg.js +2 -0
  626. package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
  627. package/dist/web/_app/immutable/chunks/zl16E4yc2.js +1 -0
  628. package/dist/web/_app/immutable/entry/app.CbuUtkoM.js +2 -0
  629. package/dist/web/_app/immutable/entry/start.DeZyKwOT.js +1 -0
  630. package/dist/web/_app/immutable/nodes/0.C4PMtdx9.js +2 -0
  631. package/dist/web/_app/immutable/nodes/1.BwVfPLMn.js +1 -0
  632. package/dist/web/_app/immutable/nodes/10.DPr_SYan.js +1 -0
  633. package/dist/web/_app/immutable/nodes/11.CJAmEchE.js +1 -0
  634. package/dist/web/_app/immutable/nodes/12.ChMWXPMk.js +1 -0
  635. package/dist/web/_app/immutable/nodes/13.8vOKq8ue.js +1 -0
  636. package/dist/web/_app/immutable/nodes/14.BOSNmj9h.js +1 -0
  637. package/dist/web/_app/immutable/nodes/2.7N4BLwhX.js +109 -0
  638. package/dist/web/_app/immutable/nodes/3.Cd-tx8Ej.js +2 -0
  639. package/dist/web/_app/immutable/nodes/4.DtuT-syy.js +14 -0
  640. package/dist/web/_app/immutable/nodes/5.YwNHOrkt.js +1 -0
  641. package/dist/web/_app/immutable/nodes/6.BSPlYQuq.js +1 -0
  642. package/dist/web/_app/immutable/nodes/7.DPXzwW0H.js +1 -0
  643. package/dist/web/_app/immutable/nodes/8.Dhpk7w3X.js +1 -0
  644. package/dist/web/_app/immutable/nodes/9.Dd4iAQN5.js +1 -0
  645. package/dist/web/_app/version.json +1 -1
  646. package/dist/web/favicon-16.png +0 -0
  647. package/dist/web/favicon-180.png +0 -0
  648. package/dist/web/favicon-32.png +0 -0
  649. package/dist/web/favicon-48.png +0 -0
  650. package/dist/web/favicon-512.png +0 -0
  651. package/dist/web/favicon.ico +0 -0
  652. package/dist/web/favicon.svg +8 -0
  653. package/dist/web/index.html +54 -19
  654. package/dist/web/studiograph-logomark.svg +29 -0
  655. package/package.json +34 -14
  656. package/dist/agent/skills/enrich-entities.md +0 -136
  657. package/dist/agent/skills/obsidian-source-setup.md +0 -246
  658. package/dist/agent/skills/skill-loader.d.ts +0 -48
  659. package/dist/agent/skills/skill-loader.js +0 -166
  660. package/dist/agent/skills/skill-loader.js.map +0 -1
  661. package/dist/agent/skills/sync-configuration.md +0 -119
  662. package/dist/agent/skills/sync-setup.md +0 -82
  663. package/dist/agent/tools/sync-tools.d.ts +0 -35
  664. package/dist/agent/tools/sync-tools.js +0 -992
  665. package/dist/agent/tools/sync-tools.js.map +0 -1
  666. package/dist/auth/github.d.ts +0 -56
  667. package/dist/auth/github.js +0 -169
  668. package/dist/auth/github.js.map +0 -1
  669. package/dist/cli/commands/access.d.ts +0 -11
  670. package/dist/cli/commands/access.js +0 -156
  671. package/dist/cli/commands/access.js.map +0 -1
  672. package/dist/cli/commands/app.d.ts +0 -7
  673. package/dist/cli/commands/app.js +0 -268
  674. package/dist/cli/commands/app.js.map +0 -1
  675. package/dist/cli/commands/auth.d.ts +0 -10
  676. package/dist/cli/commands/auth.js +0 -79
  677. package/dist/cli/commands/auth.js.map +0 -1
  678. package/dist/cli/commands/clear.d.ts +0 -5
  679. package/dist/cli/commands/clear.js +0 -36
  680. package/dist/cli/commands/clear.js.map +0 -1
  681. package/dist/cli/commands/collection.d.ts +0 -10
  682. package/dist/cli/commands/collection.js +0 -187
  683. package/dist/cli/commands/collection.js.map +0 -1
  684. package/dist/cli/commands/enrich.d.ts +0 -11
  685. package/dist/cli/commands/enrich.js +0 -135
  686. package/dist/cli/commands/enrich.js.map +0 -1
  687. package/dist/cli/commands/graphrag.d.ts +0 -12
  688. package/dist/cli/commands/graphrag.js +0 -122
  689. package/dist/cli/commands/graphrag.js.map +0 -1
  690. package/dist/cli/commands/join.d.ts +0 -9
  691. package/dist/cli/commands/join.js +0 -255
  692. package/dist/cli/commands/join.js.map +0 -1
  693. package/dist/cli/commands/members.d.ts +0 -11
  694. package/dist/cli/commands/members.js +0 -230
  695. package/dist/cli/commands/members.js.map +0 -1
  696. package/dist/cli/commands/org.d.ts +0 -10
  697. package/dist/cli/commands/org.js +0 -132
  698. package/dist/cli/commands/org.js.map +0 -1
  699. package/dist/cli/commands/provision.d.ts +0 -8
  700. package/dist/cli/commands/provision.js +0 -116
  701. package/dist/cli/commands/provision.js.map +0 -1
  702. package/dist/cli/commands/resolve.d.ts +0 -8
  703. package/dist/cli/commands/resolve.js +0 -85
  704. package/dist/cli/commands/resolve.js.map +0 -1
  705. package/dist/cli/commands/review.d.ts +0 -19
  706. package/dist/cli/commands/review.js +0 -128
  707. package/dist/cli/commands/review.js.map +0 -1
  708. package/dist/cli/commands/source.d.ts +0 -16
  709. package/dist/cli/commands/source.js +0 -159
  710. package/dist/cli/commands/source.js.map +0 -1
  711. package/dist/cli/commands/start.d.ts +0 -7
  712. package/dist/cli/commands/start.js +0 -589
  713. package/dist/cli/commands/start.js.map +0 -1
  714. package/dist/cli/commands/sync-collection.d.ts +0 -14
  715. package/dist/cli/commands/sync-collection.js +0 -355
  716. package/dist/cli/commands/sync-collection.js.map +0 -1
  717. package/dist/cli/commands/sync-entities.d.ts +0 -13
  718. package/dist/cli/commands/sync-entities.js +0 -242
  719. package/dist/cli/commands/sync-entities.js.map +0 -1
  720. package/dist/cli/commands/team.d.ts +0 -12
  721. package/dist/cli/commands/team.js +0 -185
  722. package/dist/cli/commands/team.js.map +0 -1
  723. package/dist/cli/commands/update.d.ts +0 -8
  724. package/dist/cli/commands/update.js +0 -155
  725. package/dist/cli/commands/update.js.map +0 -1
  726. package/dist/cli/commands/user.d.ts +0 -7
  727. package/dist/cli/commands/user.js +0 -153
  728. package/dist/cli/commands/user.js.map +0 -1
  729. package/dist/cli/scaffolding.d.ts +0 -12
  730. package/dist/cli/scaffolding.js +0 -397
  731. package/dist/cli/scaffolding.js.map +0 -1
  732. package/dist/cli/sync-review-interactive.d.ts +0 -31
  733. package/dist/cli/sync-review-interactive.js +0 -393
  734. package/dist/cli/sync-review-interactive.js.map +0 -1
  735. package/dist/core/migration-runner.d.ts +0 -42
  736. package/dist/core/migration-runner.js +0 -232
  737. package/dist/core/migration-runner.js.map +0 -1
  738. package/dist/core/migration-types.d.ts +0 -101
  739. package/dist/core/migration-types.js +0 -21
  740. package/dist/core/migration-types.js.map +0 -1
  741. package/dist/core/migrations/20260219-formalize-memory-location.d.ts +0 -2
  742. package/dist/core/migrations/20260219-formalize-memory-location.js +0 -35
  743. package/dist/core/migrations/20260219-formalize-memory-location.js.map +0 -1
  744. package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +0 -12
  745. package/dist/core/migrations/20260220-add-workspace-metadata.js +0 -65
  746. package/dist/core/migrations/20260220-add-workspace-metadata.js.map +0 -1
  747. package/dist/core/migrations/20260220-add-workspace-readme.d.ts +0 -11
  748. package/dist/core/migrations/20260220-add-workspace-readme.js +0 -82
  749. package/dist/core/migrations/20260220-add-workspace-readme.js.map +0 -1
  750. package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +0 -9
  751. package/dist/core/migrations/20260220-migrate-yaml-to-json.js +0 -64
  752. package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +0 -1
  753. package/dist/core/migrations/index.d.ts +0 -11
  754. package/dist/core/migrations/index.js +0 -23
  755. package/dist/core/migrations/index.js.map +0 -1
  756. package/dist/integrations/asana.d.ts +0 -26
  757. package/dist/integrations/asana.js +0 -78
  758. package/dist/integrations/asana.js.map +0 -1
  759. package/dist/integrations/figma-local.d.ts +0 -16
  760. package/dist/integrations/figma-local.js +0 -10
  761. package/dist/integrations/figma-local.js.map +0 -1
  762. package/dist/integrations/figma.d.ts +0 -17
  763. package/dist/integrations/figma.js +0 -17
  764. package/dist/integrations/figma.js.map +0 -1
  765. package/dist/integrations/granola.d.ts +0 -24
  766. package/dist/integrations/granola.js +0 -60
  767. package/dist/integrations/granola.js.map +0 -1
  768. package/dist/integrations/linear.d.ts +0 -14
  769. package/dist/integrations/linear.js +0 -80
  770. package/dist/integrations/linear.js.map +0 -1
  771. package/dist/integrations/paper-local.d.ts +0 -14
  772. package/dist/integrations/paper-local.js +0 -10
  773. package/dist/integrations/paper-local.js.map +0 -1
  774. package/dist/integrations/paper.d.ts +0 -2
  775. package/dist/integrations/paper.js +0 -10
  776. package/dist/integrations/paper.js.map +0 -1
  777. package/dist/integrations/pipedrive.d.ts +0 -26
  778. package/dist/integrations/pipedrive.js +0 -97
  779. package/dist/integrations/pipedrive.js.map +0 -1
  780. package/dist/integrations/registry.d.ts +0 -15
  781. package/dist/integrations/registry.js +0 -27
  782. package/dist/integrations/registry.js.map +0 -1
  783. package/dist/integrations/types.d.ts +0 -38
  784. package/dist/integrations/types.js +0 -9
  785. package/dist/integrations/types.js.map +0 -1
  786. package/dist/lib/lib/utils.d.ts +0 -2
  787. package/dist/lib/lib/utils.js +0 -6
  788. package/dist/lib/lib/utils.js.map +0 -1
  789. package/dist/mcp/connectors/asana.d.ts +0 -2
  790. package/dist/mcp/connectors/asana.js +0 -20
  791. package/dist/mcp/connectors/asana.js.map +0 -1
  792. package/dist/mcp/connectors/definitions.d.ts +0 -45
  793. package/dist/mcp/connectors/definitions.js +0 -32
  794. package/dist/mcp/connectors/definitions.js.map +0 -1
  795. package/dist/mcp/connectors/figma.d.ts +0 -5
  796. package/dist/mcp/connectors/figma.js +0 -21
  797. package/dist/mcp/connectors/figma.js.map +0 -1
  798. package/dist/mcp/connectors/gdrive.d.ts +0 -2
  799. package/dist/mcp/connectors/gdrive.js +0 -20
  800. package/dist/mcp/connectors/gdrive.js.map +0 -1
  801. package/dist/mcp/connectors/granola.d.ts +0 -2
  802. package/dist/mcp/connectors/granola.js +0 -12
  803. package/dist/mcp/connectors/granola.js.map +0 -1
  804. package/dist/mcp/connectors/linear.d.ts +0 -2
  805. package/dist/mcp/connectors/linear.js +0 -19
  806. package/dist/mcp/connectors/linear.js.map +0 -1
  807. package/dist/mcp/connectors/obsidian.d.ts +0 -2
  808. package/dist/mcp/connectors/obsidian.js +0 -19
  809. package/dist/mcp/connectors/obsidian.js.map +0 -1
  810. package/dist/mcp/connectors/pipedrive.d.ts +0 -2
  811. package/dist/mcp/connectors/pipedrive.js +0 -20
  812. package/dist/mcp/connectors/pipedrive.js.map +0 -1
  813. package/dist/mcp/connectors/slack.d.ts +0 -2
  814. package/dist/mcp/connectors/slack.js +0 -21
  815. package/dist/mcp/connectors/slack.js.map +0 -1
  816. package/dist/mcp/server-oauth-provider.d.ts +0 -56
  817. package/dist/mcp/server-oauth-provider.js +0 -142
  818. package/dist/mcp/server-oauth-provider.js.map +0 -1
  819. package/dist/server/chrome/chrome.css +0 -691
  820. package/dist/server/chrome/chrome.js +0 -374
  821. package/dist/server/collab-authority.d.ts +0 -70
  822. package/dist/server/collab-authority.js +0 -218
  823. package/dist/server/collab-authority.js.map +0 -1
  824. package/dist/server/collab.d.ts +0 -29
  825. package/dist/server/collab.js +0 -195
  826. package/dist/server/collab.js.map +0 -1
  827. package/dist/server/commit-scheduler.d.ts +0 -39
  828. package/dist/server/commit-scheduler.js +0 -113
  829. package/dist/server/commit-scheduler.js.map +0 -1
  830. package/dist/server/plugin-loader.d.ts +0 -53
  831. package/dist/server/plugin-loader.js +0 -155
  832. package/dist/server/plugin-loader.js.map +0 -1
  833. package/dist/server/routes/collab.d.ts +0 -6
  834. package/dist/server/routes/collab.js +0 -10
  835. package/dist/server/routes/collab.js.map +0 -1
  836. package/dist/server/routes/git-api.d.ts +0 -9
  837. package/dist/server/routes/git-api.js +0 -82
  838. package/dist/server/routes/git-api.js.map +0 -1
  839. package/dist/server/routes/meeting-ingest-api.d.ts +0 -15
  840. package/dist/server/routes/meeting-ingest-api.js +0 -323
  841. package/dist/server/routes/meeting-ingest-api.js.map +0 -1
  842. package/dist/server/routes/sync-api.d.ts +0 -26
  843. package/dist/server/routes/sync-api.js +0 -814
  844. package/dist/server/routes/sync-api.js.map +0 -1
  845. package/dist/server/routes/webhook.d.ts +0 -14
  846. package/dist/server/routes/webhook.js +0 -102
  847. package/dist/server/routes/webhook.js.map +0 -1
  848. package/dist/services/github-provisioner.d.ts +0 -36
  849. package/dist/services/github-provisioner.js +0 -126
  850. package/dist/services/github-provisioner.js.map +0 -1
  851. package/dist/services/github-service.d.ts +0 -99
  852. package/dist/services/github-service.js +0 -310
  853. package/dist/services/github-service.js.map +0 -1
  854. package/dist/services/insights.d.ts +0 -38
  855. package/dist/services/insights.js +0 -246
  856. package/dist/services/insights.js.map +0 -1
  857. package/dist/services/sync/collection-sync.d.ts +0 -60
  858. package/dist/services/sync/collection-sync.js +0 -509
  859. package/dist/services/sync/collection-sync.js.map +0 -1
  860. package/dist/services/sync/commit.d.ts +0 -60
  861. package/dist/services/sync/commit.js +0 -354
  862. package/dist/services/sync/commit.js.map +0 -1
  863. package/dist/services/sync/context-index.d.ts +0 -69
  864. package/dist/services/sync/context-index.js +0 -280
  865. package/dist/services/sync/context-index.js.map +0 -1
  866. package/dist/services/sync/data-fetcher.d.ts +0 -31
  867. package/dist/services/sync/data-fetcher.js +0 -12
  868. package/dist/services/sync/data-fetcher.js.map +0 -1
  869. package/dist/services/sync/derive.d.ts +0 -34
  870. package/dist/services/sync/derive.js +0 -164
  871. package/dist/services/sync/derive.js.map +0 -1
  872. package/dist/services/sync/enrichment-state.d.ts +0 -31
  873. package/dist/services/sync/enrichment-state.js +0 -63
  874. package/dist/services/sync/enrichment-state.js.map +0 -1
  875. package/dist/services/sync/enrichment.d.ts +0 -25
  876. package/dist/services/sync/enrichment.js +0 -121
  877. package/dist/services/sync/enrichment.js.map +0 -1
  878. package/dist/services/sync/entity-refresh.d.ts +0 -30
  879. package/dist/services/sync/entity-refresh.js +0 -275
  880. package/dist/services/sync/entity-refresh.js.map +0 -1
  881. package/dist/services/sync/frontmatter-extractor.d.ts +0 -40
  882. package/dist/services/sync/frontmatter-extractor.js +0 -279
  883. package/dist/services/sync/frontmatter-extractor.js.map +0 -1
  884. package/dist/services/sync/graph-match-state.d.ts +0 -33
  885. package/dist/services/sync/graph-match-state.js +0 -61
  886. package/dist/services/sync/graph-match-state.js.map +0 -1
  887. package/dist/services/sync/graph-match.d.ts +0 -53
  888. package/dist/services/sync/graph-match.js +0 -316
  889. package/dist/services/sync/graph-match.js.map +0 -1
  890. package/dist/services/sync/graphrag-client.d.ts +0 -43
  891. package/dist/services/sync/graphrag-client.js +0 -94
  892. package/dist/services/sync/graphrag-client.js.map +0 -1
  893. package/dist/services/sync/graphrag-config.d.ts +0 -16
  894. package/dist/services/sync/graphrag-config.js +0 -39
  895. package/dist/services/sync/graphrag-config.js.map +0 -1
  896. package/dist/services/sync/graphrag-context.d.ts +0 -14
  897. package/dist/services/sync/graphrag-context.js +0 -109
  898. package/dist/services/sync/graphrag-context.js.map +0 -1
  899. package/dist/services/sync/graphrag-indexer.d.ts +0 -30
  900. package/dist/services/sync/graphrag-indexer.js +0 -358
  901. package/dist/services/sync/graphrag-indexer.js.map +0 -1
  902. package/dist/services/sync/llm.d.ts +0 -32
  903. package/dist/services/sync/llm.js +0 -115
  904. package/dist/services/sync/llm.js.map +0 -1
  905. package/dist/services/sync/mcp-client.d.ts +0 -71
  906. package/dist/services/sync/mcp-client.js +0 -299
  907. package/dist/services/sync/mcp-client.js.map +0 -1
  908. package/dist/services/sync/model-factory.d.ts +0 -13
  909. package/dist/services/sync/model-factory.js +0 -38
  910. package/dist/services/sync/model-factory.js.map +0 -1
  911. package/dist/services/sync/name-quality.d.ts +0 -31
  912. package/dist/services/sync/name-quality.js +0 -60
  913. package/dist/services/sync/name-quality.js.map +0 -1
  914. package/dist/services/sync/output-schemas.d.ts +0 -92
  915. package/dist/services/sync/output-schemas.js +0 -43
  916. package/dist/services/sync/output-schemas.js.map +0 -1
  917. package/dist/services/sync/prompts.d.ts +0 -19
  918. package/dist/services/sync/prompts.js +0 -128
  919. package/dist/services/sync/prompts.js.map +0 -1
  920. package/dist/services/sync/reconciler.d.ts +0 -48
  921. package/dist/services/sync/reconciler.js +0 -294
  922. package/dist/services/sync/reconciler.js.map +0 -1
  923. package/dist/services/sync/rest-client.d.ts +0 -40
  924. package/dist/services/sync/rest-client.js +0 -100
  925. package/dist/services/sync/rest-client.js.map +0 -1
  926. package/dist/services/sync/source-config.d.ts +0 -67
  927. package/dist/services/sync/source-config.js +0 -304
  928. package/dist/services/sync/source-config.js.map +0 -1
  929. package/dist/services/sync/source-definitions/asana.d.ts +0 -14
  930. package/dist/services/sync/source-definitions/asana.js +0 -42
  931. package/dist/services/sync/source-definitions/asana.js.map +0 -1
  932. package/dist/services/sync/source-definitions/definitions.d.ts +0 -8
  933. package/dist/services/sync/source-definitions/definitions.js +0 -8
  934. package/dist/services/sync/source-definitions/definitions.js.map +0 -1
  935. package/dist/services/sync/source-definitions/gdrive.d.ts +0 -16
  936. package/dist/services/sync/source-definitions/gdrive.js +0 -68
  937. package/dist/services/sync/source-definitions/gdrive.js.map +0 -1
  938. package/dist/services/sync/source-definitions/granola.d.ts +0 -2
  939. package/dist/services/sync/source-definitions/granola.js +0 -21
  940. package/dist/services/sync/source-definitions/granola.js.map +0 -1
  941. package/dist/services/sync/source-definitions/linear.d.ts +0 -2
  942. package/dist/services/sync/source-definitions/linear.js +0 -62
  943. package/dist/services/sync/source-definitions/linear.js.map +0 -1
  944. package/dist/services/sync/source-definitions/obsidian.d.ts +0 -2
  945. package/dist/services/sync/source-definitions/obsidian.js +0 -55
  946. package/dist/services/sync/source-definitions/obsidian.js.map +0 -1
  947. package/dist/services/sync/source-definitions/pipedrive.d.ts +0 -2
  948. package/dist/services/sync/source-definitions/pipedrive.js +0 -43
  949. package/dist/services/sync/source-definitions/pipedrive.js.map +0 -1
  950. package/dist/services/sync/staging.d.ts +0 -53
  951. package/dist/services/sync/staging.js +0 -130
  952. package/dist/services/sync/staging.js.map +0 -1
  953. package/dist/services/sync/structured-extractor.d.ts +0 -57
  954. package/dist/services/sync/structured-extractor.js +0 -584
  955. package/dist/services/sync/structured-extractor.js.map +0 -1
  956. package/dist/services/sync/sync-runner.d.ts +0 -32
  957. package/dist/services/sync/sync-runner.js +0 -195
  958. package/dist/services/sync/sync-runner.js.map +0 -1
  959. package/dist/services/sync/sync-state.d.ts +0 -43
  960. package/dist/services/sync/sync-state.js +0 -154
  961. package/dist/services/sync/sync-state.js.map +0 -1
  962. package/dist/services/sync/types.d.ts +0 -381
  963. package/dist/services/sync/types.js +0 -8
  964. package/dist/services/sync/types.js.map +0 -1
  965. package/dist/services/sync/unstructured-extractor.d.ts +0 -27
  966. package/dist/services/sync/unstructured-extractor.js +0 -185
  967. package/dist/services/sync/unstructured-extractor.js.map +0 -1
  968. package/dist/utils/merge-resolver.d.ts +0 -59
  969. package/dist/utils/merge-resolver.js +0 -303
  970. package/dist/utils/merge-resolver.js.map +0 -1
  971. package/dist/utils/workspace-config.d.ts +0 -8
  972. package/dist/utils/workspace-config.js +0 -22
  973. package/dist/utils/workspace-config.js.map +0 -1
  974. package/dist/web/_app/immutable/assets/0.DdizXOKi.css +0 -1
  975. package/dist/web/_app/immutable/assets/10.BUrHkYry.css +0 -1
  976. package/dist/web/_app/immutable/assets/2.n7-yW_Fs.css +0 -1
  977. package/dist/web/_app/immutable/assets/3.BtaZagnv.css +0 -1
  978. package/dist/web/_app/immutable/assets/4.DT7X0x5S.css +0 -1
  979. package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
  980. package/dist/web/_app/immutable/assets/6.CquhUpOu.css +0 -1
  981. package/dist/web/_app/immutable/assets/7.CjbDRbuG.css +0 -1
  982. package/dist/web/_app/immutable/assets/8.S1QdUGNM.css +0 -1
  983. package/dist/web/_app/immutable/assets/9.CT4xL4K3.css +0 -1
  984. package/dist/web/_app/immutable/assets/Copy.FS8bdfxr.css +0 -1
  985. package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
  986. package/dist/web/_app/immutable/assets/ViewToolbar.D-QW2oKe.css +0 -1
  987. package/dist/web/_app/immutable/assets/index.D6tMDJWk.css +0 -1
  988. package/dist/web/_app/immutable/chunks/37NdyH6G.js +0 -32
  989. package/dist/web/_app/immutable/chunks/4Hhzb6pv.js +0 -1
  990. package/dist/web/_app/immutable/chunks/72bZS3G9.js +0 -1
  991. package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
  992. package/dist/web/_app/immutable/chunks/B-7hHz7B.js +0 -1
  993. package/dist/web/_app/immutable/chunks/B340SUKR.js +0 -1
  994. package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
  995. package/dist/web/_app/immutable/chunks/BDoWDZaG.js +0 -1
  996. package/dist/web/_app/immutable/chunks/BFyl1ZHO.js +0 -1
  997. package/dist/web/_app/immutable/chunks/BS2rFAVq.js +0 -1
  998. package/dist/web/_app/immutable/chunks/BSsDC_p4.js +0 -1
  999. package/dist/web/_app/immutable/chunks/BTX2Jr8_.js +0 -1
  1000. package/dist/web/_app/immutable/chunks/BWNY8zw6.js +0 -2
  1001. package/dist/web/_app/immutable/chunks/BdPUVvAi.js +0 -1
  1002. package/dist/web/_app/immutable/chunks/BmsJVLyy.js +0 -1
  1003. package/dist/web/_app/immutable/chunks/BoAosqzE.js +0 -1
  1004. package/dist/web/_app/immutable/chunks/Bs-tL5OR.js +0 -1
  1005. package/dist/web/_app/immutable/chunks/Bsacq2UX.js +0 -1
  1006. package/dist/web/_app/immutable/chunks/BuewkNdS.js +0 -4
  1007. package/dist/web/_app/immutable/chunks/ByunV8un.js +0 -1
  1008. package/dist/web/_app/immutable/chunks/C7VoTosa.js +0 -2
  1009. package/dist/web/_app/immutable/chunks/CDV5Q7RN.js +0 -1
  1010. package/dist/web/_app/immutable/chunks/CJ8__CWt.js +0 -1
  1011. package/dist/web/_app/immutable/chunks/CJUKmosC.js +0 -5
  1012. package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
  1013. package/dist/web/_app/immutable/chunks/CT6oIU-C.js +0 -1
  1014. package/dist/web/_app/immutable/chunks/CTRxNfZk.js +0 -1
  1015. package/dist/web/_app/immutable/chunks/CWQRQXxy.js +0 -1
  1016. package/dist/web/_app/immutable/chunks/CXH6iFbA.js +0 -1
  1017. package/dist/web/_app/immutable/chunks/CX_61fY8.js +0 -5
  1018. package/dist/web/_app/immutable/chunks/CYrVHOHA.js +0 -1
  1019. package/dist/web/_app/immutable/chunks/CdeYcEuU.js +0 -1
  1020. package/dist/web/_app/immutable/chunks/CmCtpZ1Y.js +0 -1
  1021. package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
  1022. package/dist/web/_app/immutable/chunks/CrdV0ttd.js +0 -1
  1023. package/dist/web/_app/immutable/chunks/CscoF-YL.js +0 -18
  1024. package/dist/web/_app/immutable/chunks/Cx4YdFMk.js +0 -1
  1025. package/dist/web/_app/immutable/chunks/D7ZqAKi9.js +0 -3
  1026. package/dist/web/_app/immutable/chunks/DGbA7IXh.js +0 -2
  1027. package/dist/web/_app/immutable/chunks/DbbB6Up5.js +0 -1
  1028. package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
  1029. package/dist/web/_app/immutable/chunks/DtM5cEDu.js +0 -1
  1030. package/dist/web/_app/immutable/chunks/Eqahi7_S.js +0 -2
  1031. package/dist/web/_app/immutable/chunks/FFlLQIiS.js +0 -1
  1032. package/dist/web/_app/immutable/chunks/O9Eb9k00.js +0 -1
  1033. package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
  1034. package/dist/web/_app/immutable/chunks/QF8MAmnc.js +0 -1
  1035. package/dist/web/_app/immutable/chunks/UjzxCpxn.js +0 -1
  1036. package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
  1037. package/dist/web/_app/immutable/chunks/Y90OgS-9.js +0 -1
  1038. package/dist/web/_app/immutable/chunks/cLyZlkXv.js +0 -1
  1039. package/dist/web/_app/immutable/chunks/iDtAARVW.js +0 -2
  1040. package/dist/web/_app/immutable/chunks/oC_W7W7p.js +0 -1
  1041. package/dist/web/_app/immutable/chunks/rJdWIgh-.js +0 -1
  1042. package/dist/web/_app/immutable/chunks/tvOsokaa.js +0 -1
  1043. package/dist/web/_app/immutable/chunks/uLEXaPwE.js +0 -1
  1044. package/dist/web/_app/immutable/chunks/vSaooFHB.js +0 -1
  1045. package/dist/web/_app/immutable/entry/app.DAR-mtfg.js +0 -2
  1046. package/dist/web/_app/immutable/entry/start.xDnyRaR1.js +0 -1
  1047. package/dist/web/_app/immutable/nodes/0.D0aV-Zro.js +0 -2
  1048. package/dist/web/_app/immutable/nodes/1.C7QoM8qD.js +0 -1
  1049. package/dist/web/_app/immutable/nodes/10.DrDOAjOD.js +0 -1
  1050. package/dist/web/_app/immutable/nodes/2.B0OgNuKW.js +0 -168
  1051. package/dist/web/_app/immutable/nodes/3.BZ4qHGZi.js +0 -1
  1052. package/dist/web/_app/immutable/nodes/4.hm-mxuuj.js +0 -12
  1053. package/dist/web/_app/immutable/nodes/5.Bdbt4fjx.js +0 -4
  1054. package/dist/web/_app/immutable/nodes/6.BXrCI40c.js +0 -2
  1055. package/dist/web/_app/immutable/nodes/7.Chd4i9bm.js +0 -2
  1056. package/dist/web/_app/immutable/nodes/8.B8SF-aNs.js +0 -1
  1057. package/dist/web/_app/immutable/nodes/9.YDeu-RnO.js +0 -1
@@ -7,11 +7,18 @@
7
7
  * - Manage wikilinks
8
8
  * - Upload assets
9
9
  */
10
- import { Type as T } from '@sinclair/typebox';
10
+ import { Type as T } from 'typebox';
11
11
  import { ENTITY_SCHEMAS } from '../../core/validation.js';
12
+ import { describeZodObject } from '../../core/schema-registry.js';
12
13
  import { lintWorkspace } from '../../services/lint-service.js';
13
14
  import { findOrphans } from '../../services/orphan-service.js';
14
- import { SyncStateManager } from '../../services/sync/sync-state.js';
15
+ import * as access from '../../services/access-control.js';
16
+ import { isCuratedEntityType } from '../../core/entity-types-catalog.js';
17
+ import { getAgentAllowedEntityTypes } from '../prompts/entity-types-section.js';
18
+ import { BridgeError, assertCanChangeUserHandle, validateUserHandleInPayload } from '../../services/user-person-bridge.js';
19
+ import { buildActor, prepareCreatePayload, prepareUpdatePayload, diagnosedUpdate, DroppedAssetError, } from '../../services/entity-mutations.js';
20
+ import { listRepoAssets } from '../../services/asset-listing.js';
21
+ import { assetEmbed } from '../../core/embeds.js';
15
22
  /**
16
23
  * Helper to wrap tool results in AgentToolResult format
17
24
  */
@@ -31,128 +38,226 @@ function cleanData(data) {
31
38
  return rest;
32
39
  }
33
40
  /**
34
- * Per-request user context for collection access filtering.
35
- * When getCurrentUser returns a non-admin user, tools filter results
36
- * to only collections the user has been granted access to.
41
+ * Undo JSON-string escapes that sometimes leak into content when the LLM
42
+ * serializes markdown as a quoted string instead of raw text. Handles `\n`,
43
+ * `\t`, `\r`, `\"`, `\\` in a single pass so escape sequences aren't
44
+ * re-processed. Also strips stray surrounding quotes from a fully-quoted
45
+ * payload.
37
46
  */
38
- /** Check if a user can see a private repo (only the owner can). */
39
- function canSeePrivateRepo(repoConfig, user) {
40
- if (!repoConfig?.private)
41
- return true;
42
- if (!user)
43
- return !repoConfig.owner_id; // API key / open mode — only if no owner set
44
- if (!repoConfig.owner_id)
45
- return false; // Private without owner — hidden from all users
46
- return user.id === repoConfig.owner_id;
47
- }
48
- /** Check if the current user is an admin. Returns an error result if not. */
49
- function adminOnly(getUser) {
50
- const user = getUser();
51
- if (!user)
52
- return null; // API key / open mode → allow
53
- if (user.role === 'admin')
54
- return null;
55
- return 'This operation requires admin access.';
47
+ function sanitizeLlmContent(content) {
48
+ if (!content)
49
+ return '';
50
+ const unescaped = content.replace(/\\([ntr"\\])/g, (_, c) => {
51
+ if (c === 'n')
52
+ return '\n';
53
+ if (c === 't')
54
+ return '\t';
55
+ if (c === 'r')
56
+ return '\r';
57
+ return c;
58
+ });
59
+ return unescaped.replace(/^"+|"+$/g, '');
56
60
  }
61
+ /**
62
+ * Per-request user context for folder access filtering.
63
+ * When getCurrentUser returns a user, tools filter results to only
64
+ * folders the user is a member of (via folder_access).
65
+ */
57
66
  function getAccessibleRepoNames(workspaceManager, getCurrentUser, authService) {
58
67
  const user = getCurrentUser();
59
68
  if (!user)
60
69
  return null; // API key / open mode → no filtering
61
70
  if (!authService)
62
71
  return null;
63
- const allRepos = workspaceManager.getAllRepoConfigs();
64
- if (user.role === 'admin') {
65
- // Admins see all non-private + their own private repos
66
- const hidden = allRepos.filter(r => !canSeePrivateRepo(r, user)).map(r => r.name);
67
- if (hidden.length === 0)
68
- return null; // No filtering needed
69
- const visible = new Set(allRepos.filter(r => canSeePrivateRepo(r, user)).map(r => r.name));
70
- return visible;
71
- }
72
- const allowed = authService.getUserCollections(user.id);
73
- const visible = allRepos.filter(r => canSeePrivateRepo(r, user) && (r.private && r.owner_id === user.id || allowed.includes(r.name)));
74
- return new Set(visible.map(r => r.name));
72
+ // Delegate to the shared helper so personal-folder restrictions and
73
+ // owner-on-shared-folder semantics apply consistently with the HTTP layer.
74
+ return new Set(access.getAccessibleRepos(user, workspaceManager, authService).map(r => r.name));
75
75
  }
76
76
  function canAccessRepo(repoName, workspaceManager, getCurrentUser, authService) {
77
77
  const user = getCurrentUser();
78
- const repoConfig = workspaceManager.getRepoConfig(repoName);
79
- if (!canSeePrivateRepo(repoConfig, user))
80
- return false;
81
78
  if (!user)
82
79
  return true;
83
- if (repoConfig?.private && repoConfig?.owner_id === user.id)
84
- return true;
85
- if (user.role === 'admin')
86
- return true;
87
80
  if (!authService)
88
81
  return true;
89
- return authService.getUserCollections(user.id).includes(repoName);
82
+ return access.hasRepoAccess(user, repoName, workspaceManager, authService);
90
83
  }
91
- export function createGraphTools(workspaceManager, gitUser, workspacePath, onHighlight, onMutation, getCurrentUser, authService) {
84
+ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHighlight, onMutation, getCurrentUser, authService,
85
+ /**
86
+ * Called at the start (`enter`) and end (`leave`) of any mutation tool
87
+ * call. Surfaces the active-agent chip in the sidebar via the WS hub. The
88
+ * orchestrator wires this through to wsHub.handleAgentActivity.
89
+ */
90
+ onAgentActivity) {
92
91
  const getUser = getCurrentUser ?? (() => null);
93
92
  const authSvc = authService ?? null;
93
+ /**
94
+ * Resolve the identity to stamp on writes. If the tool call is running on
95
+ * behalf of a real user (chat / quick-capture from the web), credit them
96
+ * by their handle via the shared `buildActor` so MCP and agent surfaces
97
+ * produce byte-identical git authors for the same user. Fall back to the
98
+ * orchestrator-level gitUser for unauthenticated contexts (CLI, tests,
99
+ * server-only automations).
100
+ */
101
+ function effectiveGitUser() {
102
+ const user = getUser();
103
+ if (user?.handle)
104
+ return buildActor(user);
105
+ return gitUser;
106
+ }
107
+ /** Resolve "private" or "entries" to the current user's actual private folder name. */
108
+ function resolvePrivateRepo(repoName) {
109
+ if (repoName !== 'private' && repoName !== 'entries')
110
+ return repoName;
111
+ const user = getUser();
112
+ if (!user)
113
+ return repoName;
114
+ const personalRepo = workspaceManager.getUserPersonalRepo(user.id);
115
+ return personalRepo?.name ?? repoName;
116
+ }
117
+ /**
118
+ * Eager skills are inlined into every system prompt for everyone with folder
119
+ * access. Creating one in a shared folder requires admin/owner so a rogue
120
+ * member can't bloat everyone's context. Eager skills in the user's own
121
+ * private folder are fine — they only bloat that user's own prompt.
122
+ * Returns an error string or null if the operation is allowed.
123
+ */
124
+ function checkEagerSkillPermission(entityType, data, repoName) {
125
+ if (entityType !== 'skill')
126
+ return null;
127
+ if (!data || data.loading !== 'eager')
128
+ return null;
129
+ const user = getUser();
130
+ if (!user)
131
+ return null; // non-authenticated contexts (CLI, tests) bypass
132
+ const personalRepo = workspaceManager.getUserPersonalRepo(user.id);
133
+ if (personalRepo && personalRepo.name === repoName)
134
+ return null;
135
+ if (authSvc?.isFolderAdmin(user.id, repoName))
136
+ return null;
137
+ if (user.role === 'owner')
138
+ return null;
139
+ return `Creating an eager skill in a shared folder requires folder admin or workspace owner. Save this skill to your private folder (repo: "private") or set loading to "on-demand".`;
140
+ }
141
+ // Compute the set of entity types the agent is allowed to create in this
142
+ // workspace: the full canonical catalog plus any custom types defined via
143
+ // schema_extensions. The launch-time allowlist was removed — the catalog
144
+ // now grows with the user via the New Entry picker's progressive disclosure.
145
+ const builtinTypeKeys = new Set(Object.keys(ENTITY_SCHEMAS));
146
+ const customWorkspaceTypes = workspaceManager.getSchemaRegistry().getAllTypes()
147
+ .filter(t => !builtinTypeKeys.has(t));
148
+ const agentAllowedTypes = getAgentAllowedEntityTypes(customWorkspaceTypes);
149
+ const agentAllowedTypeSet = new Set(agentAllowedTypes);
150
+ function rejectDisallowedCreateType(entityType) {
151
+ if (agentAllowedTypeSet.has(entityType))
152
+ return null;
153
+ if (entityType === 'asset') {
154
+ // The schema enum already excludes `asset` (see
155
+ // getAgentAllowedEntityTypes). This is the runtime defense-in-depth
156
+ // path for clients that bypass the enum.
157
+ return wrapToolResult({
158
+ success: false,
159
+ error: 'Asset entries cannot be created via create_entity — they require a binary blob plus a sidecar text file. Use the import_file tool with a local file path, or have the user upload via the workspace import dialog.',
160
+ });
161
+ }
162
+ const hint = isCuratedEntityType(entityType)
163
+ ? '' // shouldn't happen for any other curated type — they're all allowed
164
+ : ` Allowed types: ${agentAllowedTypes.join(', ')}.`;
165
+ return wrapToolResult({
166
+ success: false,
167
+ error: `Entry type "${entityType}" is not a known canonical or workspace custom type.${hint}`,
168
+ });
169
+ }
94
170
  return [
95
171
  // Create entity
96
172
  {
97
173
  name: 'create_entity',
98
- label: 'Create Entity',
99
- description: 'Create a new entity in a collection. Always validate required fields before calling. Collection is auto-resolved for app-defined entity types.',
174
+ label: 'Create Entry',
175
+ description: 'Create a new entry in a folder. Always validate required fields before calling. Folder is auto-resolved for app-defined entry types.',
100
176
  parameters: T.Object({
101
- repo: T.Optional(T.String({ description: 'Collection name (auto-resolved for app entity types)' })),
102
- entityType: T.String({ description: 'Entity type (project, client, decision, etc.)' }),
177
+ repo: T.Optional(T.String({ description: 'Folder name (auto-resolved for app entity types)' })),
178
+ entityType: T.Union(agentAllowedTypes.map(t => T.Literal(t)), { description: `Entity type. Must be one of: ${agentAllowedTypes.join(', ')}.` }),
103
179
  entityId: T.String({ description: 'Unique entity ID in kebab-case' }),
104
180
  data: T.Object({}, { description: 'Entity data (YAML frontmatter)', additionalProperties: true }),
105
181
  content: T.Optional(T.String({ description: 'Markdown content (optional)' })),
182
+ folder_path: T.Optional(T.String({ description: 'Repo-relative subfolder for the entry (e.g. "clients/acme"). Omit to land at repo root. Parent folders are auto-created.' })),
106
183
  commitMessage: T.Optional(T.String({ description: 'Custom commit message (optional)' })),
107
184
  }),
108
185
  execute: async (toolCallId, params) => {
109
186
  try {
187
+ // Defense in depth: LLMs occasionally pass strings that don't match the
188
+ // enum schema. Runtime check ensures the launch allowlist is enforced
189
+ // even if the schema layer is bypassed.
190
+ const typeRejection = rejectDisallowedCreateType(params.entityType);
191
+ if (typeRejection)
192
+ return typeRejection;
110
193
  let repoName = params.repo;
111
194
  if (!repoName) {
112
- repoName = workspaceManager.getAppForEntityType(params.entityType);
113
- if (!repoName)
114
- return wrapToolResult({ success: false, error: `repo is required — could not auto-resolve repo for type "${params.entityType}"` });
195
+ return wrapToolResult({ success: false, error: `repo is required — must specify which folder to use for type "${params.entityType}"` });
115
196
  }
197
+ repoName = resolvePrivateRepo(repoName);
116
198
  if (!canAccessRepo(repoName, workspaceManager, getUser, authSvc)) {
117
- return wrapToolResult({ success: false, error: `Collection "${repoName}" not found` });
199
+ return wrapToolResult({ success: false, error: `Folder "${repoName}" not found` });
118
200
  }
201
+ const eagerError = checkEagerSkillPermission(params.entityType, params.data, repoName);
202
+ if (eagerError)
203
+ return wrapToolResult({ success: false, error: eagerError });
119
204
  const graph = workspaceManager.getGraph(repoName);
120
205
  // Workspace-level dedup: warn if an entity with this ID already exists elsewhere
121
206
  const existing = workspaceManager.findEntityById(params.entityId);
122
207
  if (existing && existing.repoName !== repoName) {
123
- return wrapToolResult({ success: false, error: `An entity with ID "${params.entityId}" already exists in the "${existing.repoName}" collection (type: ${existing.data?.entity_type}). Use a unique ID or link to the existing entity with [[${params.entityId}]].` });
208
+ return wrapToolResult({ success: false, error: `An entity with ID "${params.entityId}" already exists in the "${existing.repoName}" folder (type: ${existing.data?.entity_type}). Use a unique ID or link to the existing entity with [[${params.entityId}]].` });
124
209
  }
125
- // Add timestamps and user info
126
- const now = new Date().toISOString();
127
- const dataWithMeta = {
128
- ...params.data,
129
- entity_id: params.entityId,
130
- created_at: now,
131
- updated_at: now,
132
- created_by: gitUser.id,
133
- updated_by: gitUser.id,
134
- };
135
- // Sanitize double-escaped newlines from LLM JSON output
136
- const sanitizedContent = (params.content || '').replace(/\\n/g, '\n');
137
- const entity = await graph.create({
210
+ const actor = effectiveGitUser();
211
+ const sanitizedContent = sanitizeLlmContent(params.content);
212
+ // Workspace-wide uniqueness check for `user_handle` on person
213
+ // entities (one user ↔ one person, workspace-wide), plus owner-
214
+ // only authz so a non-owner agent session can't stamp a
215
+ // pre-linked person via generic create_entity.
216
+ if (params.entityType === 'person') {
217
+ try {
218
+ const incoming = params.data ?? {};
219
+ validateUserHandleInPayload(workspaceManager, incoming);
220
+ if (Object.prototype.hasOwnProperty.call(incoming, 'user_handle')) {
221
+ assertCanChangeUserHandle(getUser(), '', incoming.user_handle);
222
+ }
223
+ }
224
+ catch (err) {
225
+ if (err instanceof BridgeError) {
226
+ return wrapToolResult({ success: false, error: err.message, code: err.code, ...err.details });
227
+ }
228
+ throw err;
229
+ }
230
+ }
231
+ const options = prepareCreatePayload({
138
232
  entityType: params.entityType,
139
233
  entityId: params.entityId,
140
- data: dataWithMeta,
234
+ data: params.data ?? {},
141
235
  content: sanitizedContent,
236
+ folderPath: params.folder_path,
142
237
  commitMessage: params.commitMessage,
143
- });
144
- onMutation?.({ action: 'created', repo: repoName, entityType: params.entityType, entityId: params.entityId });
145
- return wrapToolResult({
146
- success: true,
147
- entity: {
148
- entityId: entity.id,
149
- entityType: entity.entityType,
150
- repo: repoName,
151
- path: entity.path,
152
- data: cleanData(entity.data),
153
- },
154
- message: `Created ${params.entityType}: ${params.entityId} in ${repoName}. Auto-committed — ready to push.`,
155
- });
238
+ }, actor);
239
+ // Surface a live "<user>'s agent is acting" chip in the sidebar for
240
+ // the duration of the mutation. `leave` is always emitted via the
241
+ // inner finally so a thrown error doesn't leave the chip stuck.
242
+ onAgentActivity?.('enter', repoName);
243
+ try {
244
+ const entity = await graph.create(options);
245
+ onMutation?.({ action: 'created', repo: repoName, entityType: params.entityType, entityId: params.entityId });
246
+ return wrapToolResult({
247
+ success: true,
248
+ entity: {
249
+ entityId: entity.id,
250
+ entityType: entity.entityType,
251
+ repo: repoName,
252
+ path: entity.path,
253
+ data: cleanData(entity.data),
254
+ },
255
+ message: `Created ${params.entityType}: ${params.entityId} in ${repoName}. Auto-committed — ready to push.`,
256
+ });
257
+ }
258
+ finally {
259
+ onAgentActivity?.('leave', repoName);
260
+ }
156
261
  }
157
262
  catch (error) {
158
263
  return wrapToolResult({
@@ -165,31 +270,51 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
165
270
  // Get entity
166
271
  {
167
272
  name: 'get_entity',
168
- label: 'Get Entity',
169
- description: 'Retrieve full entity details. Use repo, entityType, entityId from search/list results. entityType is optional — if omitted it is read from the file.',
273
+ label: 'Get Entry',
274
+ description: 'Retrieve full entry details. Use repo, entityType, entityId from search/list results. entityType is optional — if omitted it is read from the file.',
170
275
  parameters: T.Object({
171
- repo: T.String({ description: 'Collection name' }),
276
+ repo: T.String({ description: 'Folder name' }),
172
277
  entityType: T.Optional(T.String({ description: 'Entity type (optional — resolved from frontmatter if omitted)' })),
173
278
  entityId: T.String({ description: 'Entity ID' }),
174
279
  }),
175
280
  execute: async (toolCallId, params) => {
176
281
  try {
177
- if (!canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
178
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
282
+ const repo = resolvePrivateRepo(params.repo);
283
+ if (!canAccessRepo(repo, workspaceManager, getUser, authSvc)) {
284
+ return wrapToolResult({ success: false, error: `Folder "${repo}" not found` });
179
285
  }
180
- const graph = workspaceManager.getGraph(params.repo);
181
- const entity = params.entityType
182
- ? graph.get(params.entityType, params.entityId)
183
- : graph.getById(params.entityId);
286
+ const graph = workspaceManager.getGraph(repo);
287
+ // If the agent passes the wrong entityType (e.g. based on stale
288
+ // search results), graph.get computes the wrong filesystem path
289
+ // and throws. Fall back to getById, which scans all type subdirs
290
+ // under the folder and resolves the actual location.
291
+ let entity;
292
+ if (params.entityType) {
293
+ try {
294
+ entity = graph.get(params.entityType, params.entityId);
295
+ }
296
+ catch {
297
+ entity = graph.getById(params.entityId);
298
+ }
299
+ }
300
+ else {
301
+ entity = graph.getById(params.entityId);
302
+ }
303
+ // Prefer the live editor body when a seeded Y.Doc is open. graph.get
304
+ // reads disk, which lags the editor by the autosave debounce — a
305
+ // user's freshly-placed image embed lives in the Y.Doc before it's
306
+ // committed. Returning disk content is what let the agent edit then
307
+ // resend a body missing those embeds, silently dropping images.
308
+ const liveBody = graph.getLiveBody(entity.entityType, entity.id);
184
309
  return wrapToolResult({
185
310
  success: true,
186
311
  entity: {
187
312
  entityId: entity.id,
188
313
  entityType: entity.entityType,
189
- repo: params.repo,
314
+ repo,
190
315
  path: entity.path,
191
316
  data: cleanData(entity.data),
192
- content: entity.document.content,
317
+ content: liveBody ?? entity.document.content,
193
318
  wikilinks: entity.document.wikilinks,
194
319
  },
195
320
  });
@@ -205,59 +330,105 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
205
330
  // Update entity
206
331
  {
207
332
  name: 'update_entity',
208
- label: 'Update Entity',
209
- description: 'Update an existing entity. Collection is auto-resolved for app-defined types.',
333
+ label: 'Update Entry',
334
+ description: 'Update an existing entry. Folder is auto-resolved for app-defined types.',
210
335
  parameters: T.Object({
211
- repo: T.Optional(T.String({ description: 'Collection name (auto-resolved for app entity types)' })),
336
+ repo: T.Optional(T.String({ description: 'Folder name (auto-resolved for app entity types)' })),
212
337
  entityType: T.String({ description: 'Entity type' }),
213
338
  entityId: T.String({ description: 'Entity ID' }),
214
339
  data: T.Optional(T.Object({}, { description: 'Updated data fields', additionalProperties: true })),
215
- content: T.Optional(T.String({ description: 'Updated markdown content' })),
340
+ content: T.Optional(T.String({ description: 'Updated markdown body (replaces the entire body)' })),
216
341
  commitMessage: T.Optional(T.String({ description: 'Custom commit message' })),
342
+ allowImageRemoval: T.Optional(T.Boolean({ description: 'Set true only to deliberately delete image/asset embeds the document currently has; otherwise such a whole-body write is rejected (ASSET_REMOVAL_BLOCKED). Prefer get_entity then patch_entity for small edits.' })),
217
343
  }),
218
344
  execute: async (toolCallId, params) => {
219
345
  try {
220
346
  let repoName = params.repo;
221
347
  if (!repoName) {
222
- repoName = workspaceManager.getAppForEntityType(params.entityType);
223
- if (!repoName)
224
- return wrapToolResult({ success: false, error: `repo is required — could not auto-resolve repo for type "${params.entityType}"` });
348
+ return wrapToolResult({ success: false, error: `repo is required — must specify which folder to use for type "${params.entityType}"` });
225
349
  }
350
+ repoName = resolvePrivateRepo(repoName);
226
351
  if (!canAccessRepo(repoName, workspaceManager, getUser, authSvc)) {
227
- return wrapToolResult({ success: false, error: `Collection "${repoName}" not found` });
352
+ return wrapToolResult({ success: false, error: `Folder "${repoName}" not found` });
228
353
  }
354
+ const eagerError = checkEagerSkillPermission(params.entityType, params.data, repoName);
355
+ if (eagerError)
356
+ return wrapToolResult({ success: false, error: eagerError });
229
357
  const graph = workspaceManager.getGraph(repoName);
230
- // Add update metadata
231
- const dataWithMeta = params.data
232
- ? {
233
- ...params.data,
234
- updated_at: new Date().toISOString(),
235
- updated_by: gitUser.id,
236
- }
237
- : undefined;
238
- // Sanitize double-escaped newlines from LLM JSON output
358
+ const actor = effectiveGitUser();
239
359
  const sanitizedContent = params.content !== undefined
240
- ? params.content.replace(/\\n/g, '\n') : params.content;
241
- const entity = await graph.update({
360
+ ? sanitizeLlmContent(params.content)
361
+ : params.content;
362
+ // Workspace-wide uniqueness check + owner-only authz for
363
+ // `user_handle` on person entities. Generic update_entity must
364
+ // not be a back door around the ownerOnly() gate on the dedicated
365
+ // link/unlink tools — otherwise a member could ask the agent to
366
+ // "set this person's user_handle to mine" and bypass the gate.
367
+ if (params.entityType === 'person' && params.data) {
368
+ try {
369
+ validateUserHandleInPayload(workspaceManager, params.data, { repo: repoName, entityId: params.entityId });
370
+ if (Object.prototype.hasOwnProperty.call(params.data, 'user_handle')) {
371
+ let currentHandle = '';
372
+ try {
373
+ const current = graph.get('person', params.entityId);
374
+ currentHandle = (current?.data?.user_handle ?? '');
375
+ }
376
+ catch { /* new entity / missing — treat as empty */ }
377
+ assertCanChangeUserHandle(getUser(), currentHandle, params.data.user_handle);
378
+ }
379
+ }
380
+ catch (err) {
381
+ if (err instanceof BridgeError) {
382
+ return wrapToolResult({ success: false, error: err.message, code: err.code, ...err.details });
383
+ }
384
+ throw err;
385
+ }
386
+ }
387
+ const options = prepareUpdatePayload({
242
388
  entityType: params.entityType,
243
389
  entityId: params.entityId,
244
- data: dataWithMeta,
390
+ data: params.data,
245
391
  content: sanitizedContent,
246
392
  commitMessage: params.commitMessage,
247
- });
248
- onMutation?.({ action: 'updated', repo: repoName, entityType: params.entityType, entityId: params.entityId });
249
- return wrapToolResult({
250
- success: true,
251
- entity: {
252
- entityId: entity.id,
253
- entityType: entity.entityType,
254
- repo: repoName,
255
- data: cleanData(entity.data),
256
- },
257
- message: `Updated ${params.entityType}: ${params.entityId}. Auto-committed — ready to push.`,
258
- });
393
+ }, actor);
394
+ onAgentActivity?.('enter', repoName);
395
+ try {
396
+ // Shared diagnosed update (c6ef9297 contract): throws
397
+ // SilentDropError when the caller intended a change that left the
398
+ // file byte-identical, surfaced via the outer catch so the agent
399
+ // isn't misled by a success envelope.
400
+ const { entity, frontmatter_changed, content_changed, noop, broadcast } = await diagnosedUpdate(graph, options, { data: params.data, content: sanitizedContent }, { allowAssetRemoval: params.allowImageRemoval });
401
+ onMutation?.({ action: 'updated', repo: repoName, entityType: params.entityType, entityId: params.entityId });
402
+ return wrapToolResult({
403
+ success: true,
404
+ entity: {
405
+ entityId: entity.id,
406
+ entityType: entity.entityType,
407
+ repo: repoName,
408
+ data: cleanData(entity.data),
409
+ },
410
+ frontmatter_changed,
411
+ content_changed,
412
+ noop,
413
+ broadcast,
414
+ message: noop
415
+ ? `No change to ${params.entityType}: ${params.entityId} — on-disk state already matched.`
416
+ : `Updated ${params.entityType}: ${params.entityId}. Auto-committed — ready to push.`,
417
+ });
418
+ }
419
+ finally {
420
+ onAgentActivity?.('leave', repoName);
421
+ }
259
422
  }
260
423
  catch (error) {
424
+ if (error instanceof DroppedAssetError) {
425
+ return wrapToolResult({
426
+ success: false,
427
+ code: 'ASSET_REMOVAL_BLOCKED',
428
+ droppedAssets: error.dropped,
429
+ error: error.message,
430
+ });
431
+ }
261
432
  return wrapToolResult({
262
433
  success: false,
263
434
  error: error instanceof Error ? error.message : 'Unknown error',
@@ -265,13 +436,157 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
265
436
  }
266
437
  },
267
438
  },
439
+ // List assets already uploaded to a folder
440
+ {
441
+ name: 'list_assets',
442
+ label: 'List Assets',
443
+ description: 'List images/files already uploaded to a folder, with a ready-to-paste markdown embed for each. ' +
444
+ 'Use this to find an asset a user placed (e.g. a screenshot) so you can embed it into an entry — ' +
445
+ 'assets live in storage (R2/local), NOT on the local filesystem, so import_file cannot find them. ' +
446
+ 'Each result has an `embed` string: use it verbatim and NEVER write ![[filename]] transclusion syntax ' +
447
+ '(it does not render). Optionally filter by entityType/entityId. This tool only references existing ' +
448
+ 'assets — uploads happen via the workspace UI or import_file.',
449
+ parameters: T.Object({
450
+ repo: T.String({ description: 'Folder name' }),
451
+ entityType: T.Optional(T.String({ description: 'Filter to assets owned by entries of this type' })),
452
+ entityId: T.Optional(T.String({ description: 'Filter to assets owned by this entry id' })),
453
+ }),
454
+ execute: async (toolCallId, params) => {
455
+ try {
456
+ const repoName = resolvePrivateRepo(params.repo);
457
+ if (!canAccessRepo(repoName, workspaceManager, getUser, authSvc)) {
458
+ return wrapToolResult({ success: false, error: `Folder "${repoName}" not found` });
459
+ }
460
+ let assets = await listRepoAssets(repoName, workspaceManager);
461
+ if (params.entityType)
462
+ assets = assets.filter(a => a.entityType === params.entityType);
463
+ if (params.entityId)
464
+ assets = assets.filter(a => a.entityId === params.entityId);
465
+ return wrapToolResult({
466
+ success: true,
467
+ repo: repoName,
468
+ count: assets.length,
469
+ assets: assets.map(a => ({
470
+ asset_id: a.assetId,
471
+ filename: a.filename,
472
+ mime_type: a.contentType,
473
+ entityType: a.entityType,
474
+ entityId: a.entityId,
475
+ entityName: a.entityName,
476
+ url: a.url,
477
+ embed: a.embed,
478
+ })),
479
+ });
480
+ }
481
+ catch (error) {
482
+ return wrapToolResult({ success: false, error: error instanceof Error ? error.message : 'Unknown error' });
483
+ }
484
+ },
485
+ },
486
+ // Embed an already-uploaded asset into an entry body
487
+ {
488
+ name: 'attach_asset_to_entity',
489
+ label: 'Attach Asset',
490
+ description: 'Embed an already-uploaded asset (from list_assets) into an entry body using its render-safe markdown, ' +
491
+ 'without rewriting the whole body. mode "append" adds it at the end; mode "replace_placeholder" swaps dead ' +
492
+ 'placeholder text (e.g. an ![[Foo.png]] written earlier) for the working embed. Drop-guarded: rejects with ' +
493
+ 'ASSET_REMOVAL_BLOCKED if it would remove other image embeds (append only — replace_placeholder is exempt ' +
494
+ 'since the placeholder it removes is the dead reference being fixed).',
495
+ parameters: T.Object({
496
+ repo: T.String({ description: 'Folder name' }),
497
+ entityType: T.String({ description: 'Entity type of the target entry' }),
498
+ entityId: T.String({ description: 'Entity ID of the target entry' }),
499
+ url: T.String({ description: 'Asset url, taken verbatim from list_assets' }),
500
+ alt: T.Optional(T.String({ description: 'Alt text / caption. Defaults to the asset filename.' })),
501
+ mode: T.Optional(T.Union([T.Literal('append'), T.Literal('replace_placeholder')], { description: 'append (default) or replace_placeholder' })),
502
+ placeholder: T.Optional(T.String({ description: 'Required for replace_placeholder: exact text to replace' })),
503
+ expectedCount: T.Optional(T.Number({ description: 'For replace_placeholder: require this many occurrences, else reject' })),
504
+ }),
505
+ execute: async (toolCallId, params) => {
506
+ try {
507
+ const repoName = resolvePrivateRepo(params.repo);
508
+ if (!canAccessRepo(repoName, workspaceManager, getUser, authSvc)) {
509
+ return wrapToolResult({ success: false, error: `Folder "${repoName}" not found` });
510
+ }
511
+ const url = params.url ?? '';
512
+ if (!url.trim())
513
+ return wrapToolResult({ success: false, error: 'url is required' });
514
+ const mode = params.mode ?? 'append';
515
+ if (mode === 'replace_placeholder' && !params.placeholder) {
516
+ return wrapToolResult({ success: false, error: 'mode "replace_placeholder" requires a non-empty placeholder' });
517
+ }
518
+ const filename = params.alt ?? (url.split('/').pop() || 'asset').split('?')[0];
519
+ const embed = assetEmbed(filename, url);
520
+ const graph = workspaceManager.getGraph(repoName);
521
+ const entity = graph.get(params.entityType, params.entityId);
522
+ const currentBody = graph.getLiveBody(params.entityType, params.entityId) ?? entity.document.content;
523
+ let newBody;
524
+ let occurrences;
525
+ let allowAssetRemoval = false;
526
+ if (mode === 'replace_placeholder') {
527
+ const ph = params.placeholder;
528
+ let count = 0;
529
+ for (let i = currentBody.indexOf(ph); i !== -1; i = currentBody.indexOf(ph, i + ph.length))
530
+ count++;
531
+ if (count === 0) {
532
+ return wrapToolResult({ success: false, code: 'NO_MATCH', error: `placeholder not present in ${params.entityType}/${params.entityId}.` });
533
+ }
534
+ if (params.expectedCount !== undefined && count !== params.expectedCount) {
535
+ return wrapToolResult({ success: false, code: 'AMBIGUOUS_MATCH', occurrences: count, error: `Expected ${params.expectedCount} occurrence(s) of placeholder, found ${count}.` });
536
+ }
537
+ occurrences = count;
538
+ newBody = currentBody.split(ph).join(embed);
539
+ // The placeholder we're removing is itself a recognized embed
540
+ // target; swapping it for the working embed is the whole point.
541
+ allowAssetRemoval = true;
542
+ }
543
+ else {
544
+ if (currentBody.includes(embed)) {
545
+ return wrapToolResult({ success: false, code: 'ALREADY_PRESENT', error: `Asset embed already present in ${params.entityType}/${params.entityId}.` });
546
+ }
547
+ newBody = currentBody.trimEnd() + '\n\n' + embed + '\n';
548
+ }
549
+ const options = prepareUpdatePayload({
550
+ entityType: params.entityType,
551
+ entityId: params.entityId,
552
+ content: newBody,
553
+ }, effectiveGitUser());
554
+ onAgentActivity?.('enter', repoName);
555
+ try {
556
+ const { entity: updated, frontmatter_changed, content_changed, noop, broadcast } = await diagnosedUpdate(graph, options, { content: newBody }, { allowAssetRemoval });
557
+ onMutation?.({ action: 'updated', repo: repoName, entityType: params.entityType, entityId: params.entityId });
558
+ return wrapToolResult({
559
+ success: true,
560
+ entity: { entityId: updated.id, entityType: updated.entityType, repo: repoName },
561
+ embed,
562
+ mode,
563
+ occurrences,
564
+ frontmatter_changed,
565
+ content_changed,
566
+ noop,
567
+ broadcast,
568
+ message: `Embedded ${filename} into ${params.entityType}: ${params.entityId}. Auto-committed — ready to push.`,
569
+ });
570
+ }
571
+ finally {
572
+ onAgentActivity?.('leave', repoName);
573
+ }
574
+ }
575
+ catch (error) {
576
+ if (error instanceof DroppedAssetError) {
577
+ return wrapToolResult({ success: false, code: 'ASSET_REMOVAL_BLOCKED', droppedAssets: error.dropped, error: error.message });
578
+ }
579
+ return wrapToolResult({ success: false, error: error instanceof Error ? error.message : 'Unknown error' });
580
+ }
581
+ },
582
+ },
268
583
  // Delete entity
269
584
  {
270
585
  name: 'delete_entity',
271
- label: 'Delete Entity',
272
- description: 'Delete an entity. Use with caution! Collection is auto-resolved for app-defined types.',
586
+ label: 'Delete Entry',
587
+ description: 'Delete an entry. Use with caution! Folder is auto-resolved for app-defined types.',
273
588
  parameters: T.Object({
274
- repo: T.Optional(T.String({ description: 'Collection name (auto-resolved for app entity types)' })),
589
+ repo: T.Optional(T.String({ description: 'Folder name (auto-resolved for app entity types)' })),
275
590
  entityType: T.String({ description: 'Entity type' }),
276
591
  entityId: T.String({ description: 'Entity ID' }),
277
592
  commitMessage: T.Optional(T.String({ description: 'Custom commit message' })),
@@ -280,20 +595,25 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
280
595
  try {
281
596
  let repoName = params.repo;
282
597
  if (!repoName) {
283
- repoName = workspaceManager.getAppForEntityType(params.entityType);
284
- if (!repoName)
285
- return wrapToolResult({ success: false, error: `repo is required — could not auto-resolve repo for type "${params.entityType}"` });
598
+ return wrapToolResult({ success: false, error: `repo is required — must specify which folder to use for type "${params.entityType}"` });
286
599
  }
600
+ repoName = resolvePrivateRepo(repoName);
287
601
  if (!canAccessRepo(repoName, workspaceManager, getUser, authSvc)) {
288
- return wrapToolResult({ success: false, error: `Collection "${repoName}" not found` });
602
+ return wrapToolResult({ success: false, error: `Folder "${repoName}" not found` });
289
603
  }
290
604
  const graph = workspaceManager.getGraph(repoName);
291
- await graph.delete(params.entityType, params.entityId, params.commitMessage);
292
- onMutation?.({ action: 'deleted', repo: repoName, entityType: params.entityType, entityId: params.entityId });
293
- return wrapToolResult({
294
- success: true,
295
- message: `Deleted ${params.entityType}: ${params.entityId}. Auto-committed — ready to push.`,
296
- });
605
+ onAgentActivity?.('enter', repoName);
606
+ try {
607
+ await graph.delete(params.entityType, params.entityId, params.commitMessage);
608
+ onMutation?.({ action: 'deleted', repo: repoName, entityType: params.entityType, entityId: params.entityId });
609
+ return wrapToolResult({
610
+ success: true,
611
+ message: `Deleted ${params.entityType}: ${params.entityId}. Auto-committed — ready to push.`,
612
+ });
613
+ }
614
+ finally {
615
+ onAgentActivity?.('leave', repoName);
616
+ }
297
617
  }
298
618
  catch (error) {
299
619
  return wrapToolResult({
@@ -307,46 +627,93 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
307
627
  {
308
628
  name: 'import_file',
309
629
  label: 'Import File',
310
- description: 'Import a local file as a Studiograph entity. Supports .md and .txt (→ note) and .csv (→ dataset). The file is read from the local filesystem and converted to an entity with appropriate frontmatter.',
630
+ description: 'Import a local file as a Studiograph entry. Text formats become typed entries (.md/.txt → note, .csv → dataset). Binary formats (PDF, images, design files, video, audio, archives) become asset entries.',
311
631
  parameters: T.Object({
312
632
  path: T.String({ description: 'Absolute path or ~/relative path to the file' }),
313
- collection: T.String({ description: 'Target collection name' }),
314
- entityType: T.Optional(T.String({ description: 'Override entity type (default: auto-detect from extension)' })),
633
+ folder: T.String({ description: 'Target folder name' }),
634
+ entityType: T.Optional(T.String({ description: 'Override entity type (default: auto-detect from extension; ignored for asset uploads)' })),
315
635
  entityId: T.Optional(T.String({ description: 'Override entity ID (default: from filename)' })),
316
636
  }),
317
637
  execute: async (toolCallId, params) => {
318
638
  try {
319
- if (!canAccessRepo(params.collection, workspaceManager, getUser, authSvc)) {
320
- return wrapToolResult({ success: false, error: `Collection "${params.collection}" not found` });
639
+ if (!canAccessRepo(params.folder, workspaceManager, getUser, authSvc)) {
640
+ return wrapToolResult({ success: false, error: `Folder "${params.folder}" not found` });
321
641
  }
322
642
  const { readFileSync, existsSync } = await import('fs');
323
- const { resolve } = await import('path');
643
+ const { resolve, basename, sep } = await import('path');
324
644
  const { homedir } = await import('os');
325
645
  const { importFile, isSupportedFile } = await import('../../services/import-service.js');
646
+ const { isAssetUploadExtension } = await import('../../services/assets/base.js');
647
+ const { uploadAsset } = await import('../../services/asset-upload-service.js');
326
648
  const filePath = params.path.startsWith('~/')
327
649
  ? resolve(homedir(), params.path.slice(2))
328
650
  : resolve(params.path);
329
651
  if (!existsSync(filePath)) {
330
652
  return wrapToolResult({ success: false, error: `File not found: ${filePath}` });
331
653
  }
654
+ const graph = workspaceManager.getGraph(params.folder);
655
+ const fname = basename(filePath);
656
+ // Path-exfil guard: the agent reads bytes off disk and uploads
657
+ // them as a workspace asset, accessible via /api/assets/* by any
658
+ // folder member. Without an allowlist, an LLM prompt injection in
659
+ // an imported note can ask the agent to grab ~/.ssh/id_rsa, .env
660
+ // files, kubeconfigs, etc. by renaming them to a permitted
661
+ // extension. Restrict to roots a user would plausibly drop files
662
+ // from: the workspace itself, ~/Downloads, ~/Documents.
663
+ const home = homedir();
664
+ const workspaceRoot = graph.getWorkspaceRoot();
665
+ const allowedRoots = [
666
+ workspaceRoot,
667
+ resolve(home, 'Downloads'),
668
+ resolve(home, 'Documents'),
669
+ ].filter((r) => Boolean(r)).map(r => r.endsWith(sep) ? r : r + sep);
670
+ const isInAllowedRoot = allowedRoots.some(root => filePath === root.slice(0, -1) || filePath.startsWith(root));
671
+ if (!isInAllowedRoot) {
672
+ return wrapToolResult({
673
+ success: false,
674
+ error: `Path "${filePath}" is outside the import allowlist. Files must live under the workspace, ~/Downloads, or ~/Documents.`,
675
+ });
676
+ }
677
+ // Binary extensions → asset wrapper. The text-import path doesn't
678
+ // know how to handle .indd / .pptx / etc. and would either reject
679
+ // them or (for .pdf) mistakenly land them as a `note` entity with
680
+ // extracted body text. Route to uploadAsset for parity with the
681
+ // web import dispatcher.
682
+ if (isAssetUploadExtension(fname)) {
683
+ const buffer = readFileSync(filePath);
684
+ const result = await uploadAsset({
685
+ graph,
686
+ filename: fname,
687
+ buffer,
688
+ workspacePath: graph.getWorkspaceRoot(),
689
+ });
690
+ onMutation?.({ action: 'created', repo: params.folder, entityType: 'asset', entityId: result.entityId });
691
+ return wrapToolResult({
692
+ success: true,
693
+ entityType: 'asset',
694
+ entityId: result.entityId,
695
+ asset_kind: result.asset_kind,
696
+ asset_size: result.asset_size,
697
+ pages: result.pages,
698
+ message: `Imported ${fname} as asset/${result.entityId} in ${params.folder}`,
699
+ });
700
+ }
332
701
  if (!isSupportedFile(filePath)) {
333
- return wrapToolResult({ success: false, error: `Unsupported file type. Supported: .md, .txt, .csv` });
702
+ return wrapToolResult({ success: false, error: `Unsupported file type for ${fname}` });
334
703
  }
335
- const graph = workspaceManager.getGraph(params.collection);
336
704
  const content = readFileSync(filePath);
337
- const { basename } = await import('path');
338
- const result = await importFile(graph, basename(filePath), content, {
705
+ const result = await importFile(graph, fname, content, {
339
706
  entityType: params.entityType,
340
707
  entityId: params.entityId,
341
708
  });
342
709
  if (result.status === 'created') {
343
- onMutation?.({ action: 'created', repo: params.collection, entityType: result.entityType, entityId: result.entityId });
710
+ onMutation?.({ action: 'created', repo: params.folder, entityType: result.entityType, entityId: result.entityId });
344
711
  }
345
712
  return wrapToolResult({
346
713
  success: result.status === 'created',
347
714
  ...result,
348
715
  message: result.status === 'created'
349
- ? `Imported ${basename(filePath)} as ${result.entityType}/${result.entityId} in ${params.collection}`
716
+ ? `Imported ${fname} as ${result.entityType}/${result.entityId} in ${params.folder}`
350
717
  : result.error,
351
718
  });
352
719
  }
@@ -361,10 +728,10 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
361
728
  // Rename entity (change ID)
362
729
  {
363
730
  name: 'rename_entity',
364
- label: 'Rename Entity',
365
- description: 'Rename an entity by changing its ID. Preserves all data, content, and source_ref. The old ID will no longer exist. Collection is auto-resolved for app-defined types.',
731
+ label: 'Rename Entry',
732
+ description: 'Rename an entry by changing its ID. Preserves all data, content, and source_ref. The old ID will no longer exist. Folder is auto-resolved for app-defined types.',
366
733
  parameters: T.Object({
367
- repo: T.Optional(T.String({ description: 'Collection name (auto-resolved for app entity types)' })),
734
+ repo: T.Optional(T.String({ description: 'Folder name (auto-resolved for app entity types)' })),
368
735
  entityType: T.String({ description: 'Entity type' }),
369
736
  oldId: T.String({ description: 'Current entity ID' }),
370
737
  newId: T.String({ description: 'New entity ID (kebab-case)' }),
@@ -373,12 +740,11 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
373
740
  try {
374
741
  let repoName = params.repo;
375
742
  if (!repoName) {
376
- repoName = workspaceManager.getAppForEntityType(params.entityType);
377
- if (!repoName)
378
- return wrapToolResult({ success: false, error: `repo is required — could not auto-resolve repo for type "${params.entityType}"` });
743
+ return wrapToolResult({ success: false, error: `repo is required — must specify which folder to use for type "${params.entityType}"` });
379
744
  }
745
+ repoName = resolvePrivateRepo(repoName);
380
746
  if (!canAccessRepo(repoName, workspaceManager, getUser, authSvc)) {
381
- return wrapToolResult({ success: false, error: `Collection "${repoName}" not found` });
747
+ return wrapToolResult({ success: false, error: `Folder "${repoName}" not found` });
382
748
  }
383
749
  const graph = workspaceManager.getGraph(repoName);
384
750
  const result = await graph.rename(params.entityType, params.oldId, params.newId);
@@ -398,41 +764,41 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
398
764
  }
399
765
  },
400
766
  },
401
- // Move entity between repos
767
+ // Transfer entity across repos (cross-repo move). Distinct from
768
+ // folder-tools' `move_entity`, which relocates within one repo.
402
769
  {
403
- name: 'move_entity',
404
- label: 'Move Entity',
405
- description: 'Move an entity from one collection to another (admin only). Preserves all data, content, and wikilinks.',
770
+ name: 'transfer_entity',
771
+ label: 'Transfer Entry',
772
+ description: 'Move an entry from one repo to another. Preserves all data, content, and wikilinks. Requires access to both folders. For relocating within the same repo (folder_path change), use move_entity instead.',
406
773
  parameters: T.Object({
407
- sourceRepo: T.String({ description: 'Source collection name' }),
408
- targetRepo: T.String({ description: 'Target collection name' }),
774
+ sourceRepo: T.String({ description: 'Source repo name' }),
775
+ targetRepo: T.String({ description: 'Target repo name' }),
409
776
  entityType: T.String({ description: 'Entity type' }),
410
777
  entityId: T.String({ description: 'Entity ID' }),
411
778
  commitMessage: T.Optional(T.String({ description: 'Custom commit message (optional)' })),
412
779
  }),
413
780
  execute: async (toolCallId, params) => {
414
781
  try {
415
- const denied = adminOnly(getUser);
416
- if (denied)
417
- return wrapToolResult({ success: false, error: denied });
418
782
  if (!canAccessRepo(params.sourceRepo, workspaceManager, getUser, authSvc)) {
419
- return wrapToolResult({ success: false, error: `Collection "${params.sourceRepo}" not found` });
783
+ return wrapToolResult({ success: false, error: `Folder "${params.sourceRepo}" not found` });
420
784
  }
421
785
  if (!canAccessRepo(params.targetRepo, workspaceManager, getUser, authSvc)) {
422
- return wrapToolResult({ success: false, error: `Collection "${params.targetRepo}" not found` });
786
+ return wrapToolResult({ success: false, error: `Folder "${params.targetRepo}" not found` });
423
787
  }
424
788
  const sourceGraph = workspaceManager.getGraph(params.sourceRepo);
425
789
  const targetGraph = workspaceManager.getGraph(params.targetRepo);
426
790
  // Read the full entity from source
427
791
  const entity = sourceGraph.get(params.entityType, params.entityId);
428
792
  // Create in target repo
793
+ const actor = effectiveGitUser();
429
794
  const now = new Date().toISOString();
430
795
  await targetGraph.create({
431
796
  entityType: params.entityType,
432
797
  entityId: params.entityId,
433
- data: { ...entity.data, updated_at: now, updated_by: gitUser.id },
798
+ data: { ...entity.data, updated_at: now, updated_by: actor.id },
434
799
  content: entity.document.content || '',
435
800
  commitMessage: params.commitMessage || `Move ${params.entityType} ${params.entityId} from ${params.sourceRepo} to ${params.targetRepo}`,
801
+ user: actor,
436
802
  });
437
803
  // Delete from source repo
438
804
  await sourceGraph.delete(params.entityType, params.entityId, `Move ${params.entityType} ${params.entityId} to ${params.targetRepo}`);
@@ -454,12 +820,12 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
454
820
  // Search entities
455
821
  {
456
822
  name: 'search_entities',
457
- label: 'Search Entities',
458
- description: 'Search for entities across collections with filters.',
823
+ label: 'Search Entries',
824
+ description: 'Search for entries across folders with filters.',
459
825
  parameters: T.Object({
460
826
  query: T.Optional(T.String({ description: 'Search query (full-text)' })),
461
827
  entityType: T.Optional(T.String({ description: 'Filter by entity type' })),
462
- repoNames: T.Optional(T.Array(T.String(), { description: 'Limit to specific collections' })),
828
+ repoNames: T.Optional(T.Array(T.String(), { description: 'Limit to specific folders' })),
463
829
  visibility: T.Optional(T.Array(T.String(), { description: 'Filter by visibility (public, team, admin, restricted)' })),
464
830
  tags: T.Optional(T.Array(T.String(), { description: 'Filter by tags' })),
465
831
  dateRange: T.Optional(T.Object({
@@ -471,9 +837,9 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
471
837
  }),
472
838
  execute: async (toolCallId, params) => {
473
839
  try {
474
- // Scope search to accessible collections
840
+ // Scope search to accessible folders
475
841
  const allowed = getAccessibleRepoNames(workspaceManager, getUser, authSvc);
476
- let repoNames = params.repoNames;
842
+ let repoNames = params.repoNames?.map((r) => resolvePrivateRepo(r));
477
843
  if (allowed) {
478
844
  repoNames = repoNames
479
845
  ? repoNames.filter((r) => allowed.has(r))
@@ -511,8 +877,8 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
511
877
  // List entities
512
878
  {
513
879
  name: 'list_entities',
514
- label: 'List Entities',
515
- description: 'List all entities of a given type (or all types)',
880
+ label: 'List Entries',
881
+ description: 'List all entries of a given type (or all types)',
516
882
  parameters: T.Object({
517
883
  entityType: T.Optional(T.String({ description: 'Entity type to list (omit for all)' })),
518
884
  limit: T.Optional(T.Number({ description: 'Max results' })),
@@ -520,7 +886,7 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
520
886
  execute: async (toolCallId, params) => {
521
887
  try {
522
888
  let results = workspaceManager.list(params.entityType, params.limit);
523
- // Filter to accessible collections
889
+ // Filter to accessible folders
524
890
  const allowed = getAccessibleRepoNames(workspaceManager, getUser, authSvc);
525
891
  if (allowed) {
526
892
  results = results.filter(r => allowed.has(r.repoName));
@@ -547,20 +913,21 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
547
913
  // Get related entities
548
914
  {
549
915
  name: 'get_related',
550
- label: 'Get Related Entities',
551
- description: 'Get entities related to a given entity via wikilinks (cross-collection supported). Pass repo, entityType, entityId from search/list results.',
916
+ label: 'Get Related Entries',
917
+ description: 'Get entries related to a given entry via wikilinks (cross-folder supported). Pass repo, entityType, entityId from search/list results.',
552
918
  parameters: T.Object({
553
- repo: T.String({ description: 'Collection name' }),
919
+ repo: T.String({ description: 'Folder name' }),
554
920
  entityType: T.String({ description: 'Entity type' }),
555
921
  entityId: T.String({ description: 'Entity ID' }),
556
922
  }),
557
923
  execute: async (toolCallId, params) => {
558
924
  try {
559
- if (!canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
560
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
925
+ const repo = resolvePrivateRepo(params.repo);
926
+ if (!canAccessRepo(repo, workspaceManager, getUser, authSvc)) {
927
+ return wrapToolResult({ success: false, error: `Folder "${repo}" not found` });
561
928
  }
562
- let related = workspaceManager.getRelated(params.repo, params.entityType, params.entityId);
563
- // Filter cross-collection results to accessible repos
929
+ let related = workspaceManager.getRelated(repo, params.entityType, params.entityId);
930
+ // Filter cross-folder results to accessible repos
564
931
  const allowed = getAccessibleRepoNames(workspaceManager, getUser, authSvc);
565
932
  if (allowed) {
566
933
  related = related.filter(r => allowed.has(r.repoName));
@@ -588,19 +955,19 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
588
955
  {
589
956
  name: 'get_backlinks',
590
957
  label: 'Get Backlinks',
591
- description: 'Get entities that link to a given entity (cross-collection supported). Pass repo, entityType, entityId from search/list results.',
958
+ description: 'Get entries that link to a given entry (cross-folder supported). Pass repo, entityType, entityId from search/list results.',
592
959
  parameters: T.Object({
593
- repo: T.String({ description: 'Collection name' }),
960
+ repo: T.String({ description: 'Folder name' }),
594
961
  entityType: T.String({ description: 'Entity type' }),
595
962
  entityId: T.String({ description: 'Entity ID' }),
596
963
  }),
597
964
  execute: async (toolCallId, params) => {
598
965
  try {
599
966
  if (!canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
600
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
967
+ return wrapToolResult({ success: false, error: `Folder "${params.repo}" not found` });
601
968
  }
602
969
  let backlinks = workspaceManager.getBacklinks(params.repo, params.entityType, params.entityId);
603
- // Filter cross-collection results to accessible repos
970
+ // Filter cross-folder results to accessible repos
604
971
  const allowed = getAccessibleRepoNames(workspaceManager, getUser, authSvc);
605
972
  if (allowed) {
606
973
  backlinks = backlinks.filter(r => allowed.has(r.repoName));
@@ -628,16 +995,16 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
628
995
  {
629
996
  name: 'validate_wikilinks',
630
997
  label: 'Validate Wikilinks',
631
- description: 'Validate all wikilinks in an entity (checks same collection and cross-collection)',
998
+ description: 'Validate all wikilinks in an entry (checks same folder and cross-folder)',
632
999
  parameters: T.Object({
633
- repo: T.String({ description: 'Collection name' }),
1000
+ repo: T.String({ description: 'Folder name' }),
634
1001
  entityType: T.String({ description: 'Entity type' }),
635
1002
  entityId: T.String({ description: 'Entity ID' }),
636
1003
  }),
637
1004
  execute: async (toolCallId, params) => {
638
1005
  try {
639
1006
  if (!canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
640
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
1007
+ return wrapToolResult({ success: false, error: `Folder "${params.repo}" not found` });
641
1008
  }
642
1009
  const validation = workspaceManager.validateWikilinks(params.repo, params.entityType, params.entityId);
643
1010
  return wrapToolResult({
@@ -672,7 +1039,7 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
672
1039
  const summary = workspaceManager.getSummary();
673
1040
  const allowed = getAccessibleRepoNames(workspaceManager, getUser, authSvc);
674
1041
  if (allowed) {
675
- // Filter summary to accessible collections only
1042
+ // Filter summary to accessible folders only
676
1043
  const filteredByRepo = {};
677
1044
  let filteredTotal = 0;
678
1045
  for (const [repo, count] of Object.entries(summary.entitiesByRepo)) {
@@ -684,19 +1051,19 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
684
1051
  return wrapToolResult({
685
1052
  success: true,
686
1053
  summary: {
687
- totalCollections: allowed.size,
1054
+ totalFolders: allowed.size,
688
1055
  totalEntities: filteredTotal,
689
- entitiesByCollection: filteredByRepo,
1056
+ entitiesByFolder: filteredByRepo,
690
1057
  },
691
1058
  });
692
1059
  }
693
1060
  return wrapToolResult({
694
1061
  success: true,
695
1062
  summary: {
696
- totalCollections: summary.totalRepos,
1063
+ totalFolders: summary.totalRepos,
697
1064
  totalEntities: summary.totalEntities,
698
1065
  entitiesByType: summary.entitiesByType,
699
- entitiesByCollection: summary.entitiesByRepo,
1066
+ entitiesByFolder: summary.entitiesByRepo,
700
1067
  },
701
1068
  });
702
1069
  }
@@ -708,11 +1075,11 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
708
1075
  }
709
1076
  },
710
1077
  },
711
- // List collections
1078
+ // List folders
712
1079
  {
713
1080
  name: 'list_repos',
714
- label: 'List Collections',
715
- description: 'List all collections in the workspace',
1081
+ label: 'List Folders',
1082
+ description: 'List all folders in the workspace',
716
1083
  parameters: T.Object({}),
717
1084
  execute: async (toolCallId, params) => {
718
1085
  try {
@@ -724,12 +1091,12 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
724
1091
  return wrapToolResult({
725
1092
  success: true,
726
1093
  count: repos.length,
727
- collections: repos.map(r => ({
1094
+ folders: repos.map(r => ({
728
1095
  name: r.name,
729
1096
  type: r.type,
730
1097
  description: r.description,
731
1098
  path: r.path,
732
- private: r.private || false,
1099
+ personal: r.personal || false,
733
1100
  })),
734
1101
  });
735
1102
  }
@@ -741,40 +1108,35 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
741
1108
  }
742
1109
  },
743
1110
  },
744
- // Create a new collection
1111
+ // Create a new folder
745
1112
  {
746
- name: 'create_collection',
747
- label: 'Create Collection',
748
- description: 'Create a new collection in the workspace. A collection is a git-backed container for entities. Private collections are only visible to the creating user.',
1113
+ name: 'create_folder',
1114
+ label: 'Create Folder',
1115
+ description: 'Create a new shared folder in the workspace. Folders are git-backed containers for entries. New folders are shared with teammates who have access; the creator is granted admin. Every user already has a personal "My Folder" folder auto-provisioned — do not use this tool to create another one.',
749
1116
  parameters: T.Object({
750
- name: T.String({ description: 'Collection name in kebab-case (e.g., "client-projects")' }),
751
- description: T.Optional(T.String({ description: 'Short description of the collection' })),
752
- private: T.Optional(T.Boolean({ description: 'If true, creates a private collection visible only to you' })),
1117
+ name: T.String({ description: 'Folder name in kebab-case (e.g., "client-projects")' }),
1118
+ description: T.Optional(T.String({ description: 'Short description of the folder' })),
753
1119
  }),
754
1120
  execute: async (toolCallId, params) => {
755
1121
  try {
756
1122
  const user = getUser();
757
- // Non-private collections require admin; private collections can be created by anyone
758
- if (!params.private && user && user.role !== 'admin') {
759
- return wrapToolResult({ success: false, error: 'Only admins can create collections' });
760
- }
761
1123
  if (!/^[a-z0-9][a-z0-9-]*$/.test(params.name)) {
762
- return wrapToolResult({ success: false, error: 'Collection name must be kebab-case (lowercase letters, numbers, hyphens)' });
1124
+ return wrapToolResult({ success: false, error: 'Folder name must be kebab-case (lowercase letters, numbers, hyphens)' });
763
1125
  }
764
1126
  const { Workspace } = await import('../../core/workspace.js');
765
1127
  const workspace = new Workspace(workspacePath);
766
1128
  const repo = await workspace.registerRepo({
767
1129
  name: params.name,
768
1130
  description: params.description,
769
- private: params.private,
770
- ...(params.private && user ? { owner_id: user.id } : {}),
1131
+ owner_id: user?.id,
771
1132
  });
772
- // Reload workspace manager to pick up the new collection
773
1133
  workspaceManager.reloadConfig();
774
- onMutation?.({ action: 'created', repo: repo.name, entityType: '_collection', entityId: repo.name });
1134
+ if (user && authSvc)
1135
+ authSvc.grantFolderAccess(user.id, repo.name, 'admin');
1136
+ onMutation?.({ action: 'created', repo: repo.name, entityType: '_folder', entityId: repo.name });
775
1137
  return wrapToolResult({
776
1138
  success: true,
777
- collection: { name: repo.name, path: repo.path, description: repo.description },
1139
+ folder: { name: repo.name, path: repo.path, description: repo.description },
778
1140
  });
779
1141
  }
780
1142
  catch (error) {
@@ -788,7 +1150,7 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
788
1150
  label: 'Query Dataset',
789
1151
  description: 'Query rows from a dataset entity with optional filtering',
790
1152
  parameters: T.Object({
791
- repo: T.String({ description: 'Collection name' }),
1153
+ repo: T.String({ description: 'Folder name' }),
792
1154
  entityId: T.String({ description: 'Dataset entity ID' }),
793
1155
  filter: T.Optional(T.Object({}, { description: 'Filter conditions (column: value or { gte, lte, contains })', additionalProperties: true })),
794
1156
  limit: T.Optional(T.Number({ description: 'Max rows to return' })),
@@ -796,21 +1158,24 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
796
1158
  execute: async (toolCallId, params) => {
797
1159
  try {
798
1160
  if (!canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
799
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
1161
+ return wrapToolResult({ success: false, error: `Folder "${params.repo}" not found` });
800
1162
  }
801
1163
  const graph = workspaceManager.getGraph(params.repo);
802
- const entity = graph.get('dataset', params.entityId);
803
- const schema = entity.data.schema;
1164
+ // Validates the entity exists and is a dataset before querying.
1165
+ graph.get('dataset', params.entityId);
804
1166
  let rows = graph.getDatasetRows(params.entityId, params.filter);
805
1167
  const total = rows.length;
806
1168
  if (params.limit && params.limit > 0) {
807
1169
  rows = rows.slice(0, params.limit);
808
1170
  }
1171
+ // Columns from the header, not the result rows — so a zero-match
1172
+ // filter or header-only dataset still reports the real columns.
1173
+ const columns = graph.getDatasetColumns(params.entityId);
809
1174
  return wrapToolResult({
810
1175
  success: true,
811
1176
  rows,
812
1177
  total,
813
- schema,
1178
+ columns,
814
1179
  });
815
1180
  }
816
1181
  catch (error) {
@@ -827,7 +1192,7 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
827
1192
  label: 'Append Rows',
828
1193
  description: 'Append rows to a dataset entity',
829
1194
  parameters: T.Object({
830
- repo: T.String({ description: 'Collection name' }),
1195
+ repo: T.String({ description: 'Folder name' }),
831
1196
  entityId: T.String({ description: 'Dataset entity ID' }),
832
1197
  rows: T.Array(T.Object({}, { additionalProperties: true }), { description: 'Rows to append' }),
833
1198
  commitMessage: T.Optional(T.String({ description: 'Custom commit message' })),
@@ -835,13 +1200,14 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
835
1200
  execute: async (toolCallId, params) => {
836
1201
  try {
837
1202
  if (!canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
838
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
1203
+ return wrapToolResult({ success: false, error: `Folder "${params.repo}" not found` });
839
1204
  }
840
1205
  const graph = workspaceManager.getGraph(params.repo);
841
1206
  // Get current row count before appending
842
1207
  const beforeRows = graph.getDatasetRows(params.entityId);
843
1208
  await graph.appendDatasetRows(params.entityId, params.rows, params.commitMessage);
844
1209
  const afterRows = graph.getDatasetRows(params.entityId);
1210
+ onMutation?.({ action: 'updated', repo: params.repo, entityType: 'dataset', entityId: params.entityId });
845
1211
  return wrapToolResult({
846
1212
  success: true,
847
1213
  rowsAdded: afterRows.length - beforeRows.length,
@@ -860,31 +1226,23 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
860
1226
  // Get entity schema
861
1227
  {
862
1228
  name: 'get_entity_schema',
863
- label: 'Get Entity Schema',
864
- description: 'Get the schema definition for an entity type (useful for understanding required fields)',
1229
+ label: 'Get Entry Schema',
1230
+ description: 'Get the authoritative schema for an entry type. Returns each field with its type, whether it is optional, the description from the Zod schema, the full enum value list when applicable, and any default. Call this before writing enum-shaped fields (stage, status, category, priority, etc.) — the validator only accepts the values listed under `enum`.',
865
1231
  parameters: T.Object({
866
1232
  entityType: T.String({ description: 'Entity type' }),
867
1233
  }),
868
1234
  execute: async (toolCallId, params) => {
869
1235
  try {
870
- const schema = ENTITY_SCHEMAS[params.entityType];
871
- if (!schema) {
1236
+ const registry = workspaceManager.getSchemaRegistry();
1237
+ const knownTypes = new Set(registry.getAllTypes());
1238
+ if (!knownTypes.has(params.entityType)) {
872
1239
  return wrapToolResult({
873
1240
  success: false,
874
- error: `Unknown entity type: ${params.entityType}`,
1241
+ error: `Unknown entity type: ${params.entityType}. Known types: ${[...knownTypes].sort().join(', ')}`,
875
1242
  });
876
1243
  }
877
- // Extract schema shape (simplified)
878
- const shape = schema.shape || {};
879
- const fields = {};
880
- for (const [key, value] of Object.entries(shape)) {
881
- const field = value;
882
- fields[key] = {
883
- type: field._def.typeName || 'unknown',
884
- optional: field.isOptional() || false,
885
- description: field._def.description || '',
886
- };
887
- }
1244
+ const schema = registry.getSchema(params.entityType);
1245
+ const fields = describeZodObject(schema);
888
1246
  return wrapToolResult({
889
1247
  success: true,
890
1248
  entityType: params.entityType,
@@ -902,16 +1260,16 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
902
1260
  // Lint entities
903
1261
  {
904
1262
  name: 'lint_entities',
905
- label: 'Lint Entities',
906
- description: 'Check for missing recommended fields across entities. Returns incomplete entities with their missing fields. Use to discover entities that need enrichment. Optionally filter by collection or entity type.',
1263
+ label: 'Lint Entries',
1264
+ description: 'Check for missing recommended fields across entries. Returns incomplete entries with their missing fields. Use to discover entries that need enrichment. Optionally filter by folder or entry type.',
907
1265
  parameters: T.Object({
908
- repo: T.Optional(T.String({ description: 'Optional: limit to specific collection' })),
1266
+ repo: T.Optional(T.String({ description: 'Optional: limit to specific folder' })),
909
1267
  entityType: T.Optional(T.String({ description: 'Optional: limit to specific entity type (e.g. "project", "deal")' })),
910
1268
  }),
911
1269
  execute: async (toolCallId, params) => {
912
1270
  try {
913
1271
  if (params.repo && !canAccessRepo(params.repo, workspaceManager, getUser, authSvc)) {
914
- return wrapToolResult({ success: false, error: `Collection "${params.repo}" not found` });
1272
+ return wrapToolResult({ success: false, error: `Folder "${params.repo}" not found` });
915
1273
  }
916
1274
  let issues = await lintWorkspace(workspaceManager, {
917
1275
  repo: params.repo,
@@ -957,16 +1315,15 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
957
1315
  {
958
1316
  name: 'find_orphans',
959
1317
  label: 'Find Orphans',
960
- description: 'Find entities with zero inbound wikilink references. Optionally tombstone them to exclude from future syncs.',
1318
+ description: 'Find entries with zero inbound wikilink references.',
961
1319
  parameters: T.Object({
962
1320
  entityTypes: T.Optional(T.Array(T.String(), { description: 'Entity types to check (e.g. ["person", "client"])' })),
963
1321
  minAgeDays: T.Optional(T.Number({ description: 'Only flag entities older than N days' })),
964
- repos: T.Optional(T.Array(T.String(), { description: 'Collection names to scan (default: all)' })),
965
- tombstone: T.Optional(T.Boolean({ description: 'Add orphans to sync-state tombstones' })),
1322
+ repos: T.Optional(T.Array(T.String(), { description: 'Folder names to scan (default: all)' })),
966
1323
  }),
967
1324
  execute: async (toolCallId, params) => {
968
1325
  try {
969
- // Scope to accessible collections
1326
+ // Scope to accessible folders
970
1327
  const allowed = getAccessibleRepoNames(workspaceManager, getUser, authSvc);
971
1328
  let repos = params.repos;
972
1329
  if (allowed) {
@@ -977,13 +1334,6 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
977
1334
  minAgeDays: params.minAgeDays,
978
1335
  repos,
979
1336
  });
980
- // Tombstone if requested
981
- if (params.tombstone && workspacePath && result.orphans.length > 0) {
982
- const syncState = new SyncStateManager(workspacePath);
983
- for (const orphan of result.orphans) {
984
- syncState.addTombstone(orphan.entityId);
985
- }
986
- }
987
1337
  // Group by type for summary
988
1338
  const byType = {};
989
1339
  for (const o of result.orphans) {
@@ -993,7 +1343,6 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
993
1343
  success: true,
994
1344
  totalScanned: result.totalScanned,
995
1345
  totalOrphans: result.totalOrphans,
996
- tombstoned: params.tombstone ? result.totalOrphans : 0,
997
1346
  byType,
998
1347
  orphans: result.orphans.slice(0, 50), // limit response size
999
1348
  });
@@ -1009,8 +1358,8 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
1009
1358
  // Highlight entities in graph view
1010
1359
  {
1011
1360
  name: 'highlight_entities',
1012
- label: 'Highlight Entities',
1013
- description: 'Highlight specific entities in the graph view. Pass entity IDs to highlight them (dimming all others). Pass an empty array to clear highlights.',
1361
+ label: 'Highlight Entries',
1362
+ description: 'Highlight specific entries in the graph view. Pass entry IDs to highlight them (dimming all others). Pass an empty array to clear highlights.',
1014
1363
  parameters: T.Object({
1015
1364
  entityIds: T.Array(T.String(), { description: 'Entity IDs to highlight in the graph' }),
1016
1365
  }),
@@ -1025,96 +1374,50 @@ export function createGraphTools(workspaceManager, gitUser, workspacePath, onHig
1025
1374
  });
1026
1375
  },
1027
1376
  },
1028
- // ── View Management Tools ──
1377
+ // Mark onboarding complete
1029
1378
  {
1030
- name: 'list_views',
1031
- label: 'List Views',
1032
- description: 'List the current user\'s saved views.',
1379
+ name: 'mark_onboarded',
1380
+ label: 'Mark Onboarded',
1381
+ description: 'Mark the current user as onboarded. Call this when the interview/onboarding flow is complete.',
1033
1382
  parameters: T.Object({}),
1034
- execute: async () => {
1035
- if (!authSvc)
1036
- return wrapToolResult({ success: false, error: 'Auth service not available' });
1037
- const userId = getUser()?.id ?? 0;
1038
- const views = authSvc.getUserViews(userId);
1039
- return wrapToolResult({ views });
1040
- },
1041
- },
1042
- {
1043
- name: 'create_view',
1044
- label: 'Create View',
1045
- description: 'Create a new saved view for the current user. Views appear as tabs in the toolbar.',
1046
- parameters: T.Object({
1047
- name: T.String({ description: 'View name (e.g. "My Tasks", "Open Projects")' }),
1048
- selectedType: T.Optional(T.String({ description: 'Entity type filter (e.g. "task", "project"). Omit for all types.' })),
1049
- groupBy: T.Optional(T.String({ description: 'Column key to group by (e.g. "status", "priority")' })),
1050
- }),
1051
- execute: async (_toolCallId, params) => {
1383
+ execute: async (_toolCallId) => {
1052
1384
  if (!authSvc)
1053
1385
  return wrapToolResult({ success: false, error: 'Auth service not available' });
1054
1386
  const userId = getUser()?.id ?? 0;
1055
- const config = {
1056
- selectedType: params.selectedType ?? null,
1057
- groupBy: params.groupBy ?? null,
1058
- sortKey: 'name',
1059
- sortAsc: true,
1060
- filters: { text: {}, enum: {}, date: {} },
1061
- };
1062
- const view = authSvc.createUserView(userId, params.name, 'list', config);
1063
- return wrapToolResult({
1064
- success: true,
1065
- view: { id: view.id, name: view.name, viewType: view.viewType, config: view.config },
1066
- message: `Created view "${params.name}". It will appear as a tab in the toolbar.`,
1067
- });
1387
+ authSvc.setOnboarded(userId, true);
1388
+ return wrapToolResult({ success: true, message: 'User marked as onboarded.' });
1068
1389
  },
1069
1390
  },
1391
+ // Update workspace description (ABOUT.md)
1070
1392
  {
1071
- name: 'update_view',
1072
- label: 'Update View',
1073
- description: 'Update an existing saved view\'s name or configuration.',
1393
+ name: 'update_workspace_about',
1394
+ label: 'Update Workspace Description',
1395
+ description: 'Write or update the workspace description (ABOUT.md). Use this to synthesize a description from the knowledge graph after onboarding, or when asked to sync the workspace description. The content should be a concise narrative covering the organization\'s identity, team, capabilities, and values — written in markdown.',
1074
1396
  parameters: T.Object({
1075
- id: T.Number({ description: 'View ID' }),
1076
- name: T.Optional(T.String({ description: 'New view name' })),
1077
- selectedType: T.Optional(T.String({ description: 'Entity type filter (use "all" to clear)' })),
1078
- groupBy: T.Optional(T.String({ description: 'Column key to group by (use "none" to clear)' })),
1397
+ content: T.String({ description: 'The full markdown content for the workspace description' }),
1079
1398
  }),
1080
1399
  execute: async (_toolCallId, params) => {
1081
- if (!authSvc)
1082
- return wrapToolResult({ success: false, error: 'Auth service not available' });
1083
- const userId = getUser()?.id ?? 0;
1084
- const existing = authSvc.getUserView(params.id, userId);
1085
- if (!existing)
1086
- return wrapToolResult({ success: false, error: `View ${params.id} not found` });
1087
- const fields = {};
1088
- if (params.name)
1089
- fields.name = params.name;
1090
- if (params.selectedType !== undefined || params.groupBy !== undefined) {
1091
- const config = { ...existing.config };
1092
- if (params.selectedType !== undefined)
1093
- config.selectedType = params.selectedType === 'all' ? null : params.selectedType;
1094
- if (params.groupBy !== undefined)
1095
- config.groupBy = params.groupBy === 'none' ? null : params.groupBy;
1096
- fields.config = config;
1400
+ try {
1401
+ const { Workspace } = await import('../../core/workspace.js');
1402
+ const workspace = new Workspace(workspacePath);
1403
+ workspace.writeAbout(params.content);
1404
+ onMutation?.({ action: 'updated', repo: '_workspace', entityType: '_workspace', entityId: 'about' });
1405
+ return wrapToolResult({ success: true, message: 'Workspace description updated.' });
1406
+ }
1407
+ catch (err) {
1408
+ return wrapToolResult({ success: false, error: err.message || 'Failed to write ABOUT.md' });
1097
1409
  }
1098
- authSvc.updateUserView(params.id, userId, fields);
1099
- return wrapToolResult({ success: true, message: `Updated view "${existing.name}".` });
1100
1410
  },
1101
1411
  },
1412
+ // Reset conversation
1102
1413
  {
1103
- name: 'delete_view',
1104
- label: 'Delete View',
1105
- description: 'Delete a saved view.',
1106
- parameters: T.Object({
1107
- id: T.Number({ description: 'View ID to delete' }),
1108
- }),
1109
- execute: async (_toolCallId, params) => {
1110
- if (!authSvc)
1111
- return wrapToolResult({ success: false, error: 'Auth service not available' });
1112
- const userId = getUser()?.id ?? 0;
1113
- const existing = authSvc.getUserView(params.id, userId);
1114
- if (!existing)
1115
- return wrapToolResult({ success: false, error: `View ${params.id} not found` });
1116
- authSvc.deleteUserView(params.id, userId);
1117
- return wrapToolResult({ success: true, message: `Deleted view "${existing.name}".` });
1414
+ name: 'reset_conversation',
1415
+ label: 'Reset Conversation',
1416
+ description: 'Clear the current conversation and start fresh. Use when the user asks to "start over", "reset", "clear the chat", or "new conversation".',
1417
+ parameters: T.Object({}),
1418
+ execute: async (_toolCallId) => {
1419
+ onMutation?.({ action: 'deleted', repo: '_conversation', entityType: '_conversation', entityId: 'reset' });
1420
+ return wrapToolResult({ success: true, message: 'Conversation reset.' });
1118
1421
  },
1119
1422
  },
1120
1423
  ];