studiograph 1.3.48-next.21 → 1.3.48-next.211

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 (966) hide show
  1. package/README.md +26 -16
  2. package/dist/agent/agent-pool.d.ts +87 -3
  3. package/dist/agent/agent-pool.js +188 -15
  4. package/dist/agent/agent-pool.js.map +1 -1
  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 +101 -4
  9. package/dist/agent/orchestrator.js +464 -66
  10. package/dist/agent/orchestrator.js.map +1 -1
  11. package/dist/agent/prompts/entity-types-section.d.ts +34 -0
  12. package/dist/agent/prompts/entity-types-section.js +76 -0
  13. package/dist/agent/prompts/entity-types-section.js.map +1 -0
  14. package/dist/agent/prompts/system.md +112 -54
  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/artifact-canvas/skill.md +152 -0
  19. package/dist/agent/skills/entity-schema.md +75 -431
  20. package/dist/agent/skills/interview/entity-templates.md +38 -37
  21. package/dist/agent/skills/interview/question-domains.md +54 -49
  22. package/dist/agent/skills/interview/skill.md +84 -16
  23. package/dist/agent/skills/schema-rules.md +28 -28
  24. package/dist/agent/tools/artifact-tools.d.ts +124 -0
  25. package/dist/agent/tools/artifact-tools.js +207 -0
  26. package/dist/agent/tools/artifact-tools.js.map +1 -0
  27. package/dist/agent/tools/capture-tools.d.ts +31 -0
  28. package/dist/agent/tools/capture-tools.js +40 -0
  29. package/dist/agent/tools/capture-tools.js.map +1 -0
  30. package/dist/agent/tools/folder-tools.d.ts +47 -0
  31. package/dist/agent/tools/folder-tools.js +249 -0
  32. package/dist/agent/tools/folder-tools.js.map +1 -0
  33. package/dist/agent/tools/fs-tools.d.ts +6 -5
  34. package/dist/agent/tools/fs-tools.js +5 -5
  35. package/dist/agent/tools/fs-tools.js.map +1 -1
  36. package/dist/agent/tools/graph-tools.d.ts +48 -72
  37. package/dist/agent/tools/graph-tools.js +852 -329
  38. package/dist/agent/tools/graph-tools.js.map +1 -1
  39. package/dist/agent/tools/history-tools.d.ts +95 -0
  40. package/dist/agent/tools/history-tools.js +461 -0
  41. package/dist/agent/tools/history-tools.js.map +1 -0
  42. package/dist/agent/tools/load-skill.d.ts +6 -5
  43. package/dist/agent/tools/load-skill.js +3 -3
  44. package/dist/agent/tools/load-skill.js.map +1 -1
  45. package/dist/agent/tools/ops-tools.d.ts +5 -4
  46. package/dist/agent/tools/ops-tools.js +130 -236
  47. package/dist/agent/tools/ops-tools.js.map +1 -1
  48. package/dist/agent/tools/permission-tools.d.ts +87 -17
  49. package/dist/agent/tools/permission-tools.js +233 -43
  50. package/dist/agent/tools/permission-tools.js.map +1 -1
  51. package/dist/agent/tools/tool-loader.js +5 -4
  52. package/dist/agent/tools/tool-loader.js.map +1 -1
  53. package/dist/agent/tools/web-tools.js +58 -9
  54. package/dist/agent/tools/web-tools.js.map +1 -1
  55. package/dist/cli/commands/about.d.ts +1 -0
  56. package/dist/cli/commands/about.js +55 -3
  57. package/dist/cli/commands/about.js.map +1 -1
  58. package/dist/cli/commands/admin/audit-workspace.d.ts +23 -0
  59. package/dist/cli/commands/admin/audit-workspace.js +133 -0
  60. package/dist/cli/commands/admin/audit-workspace.js.map +1 -0
  61. package/dist/cli/commands/admin/audit.d.ts +21 -0
  62. package/dist/cli/commands/admin/audit.js +174 -0
  63. package/dist/cli/commands/admin/audit.js.map +1 -0
  64. package/dist/cli/commands/admin/backup.d.ts +54 -0
  65. package/dist/cli/commands/admin/backup.js +207 -0
  66. package/dist/cli/commands/admin/backup.js.map +1 -0
  67. package/dist/cli/commands/admin/folder.d.ts +11 -0
  68. package/dist/cli/commands/{collection.js → admin/folder.js} +33 -32
  69. package/dist/cli/commands/admin/folder.js.map +1 -0
  70. package/dist/cli/commands/admin/index.d.ts +16 -0
  71. package/dist/cli/commands/admin/index.js +46 -0
  72. package/dist/cli/commands/admin/index.js.map +1 -0
  73. package/dist/cli/commands/admin/migrate-assets.d.ts +53 -0
  74. package/dist/cli/commands/admin/migrate-assets.js +184 -0
  75. package/dist/cli/commands/admin/migrate-assets.js.map +1 -0
  76. package/dist/cli/commands/admin/migrate.d.ts +56 -0
  77. package/dist/cli/commands/admin/migrate.js +263 -0
  78. package/dist/cli/commands/admin/migrate.js.map +1 -0
  79. package/dist/cli/commands/admin/restore.d.ts +24 -0
  80. package/dist/cli/commands/admin/restore.js +228 -0
  81. package/dist/cli/commands/admin/restore.js.map +1 -0
  82. package/dist/cli/commands/admin/secrets.d.ts +23 -0
  83. package/dist/cli/commands/admin/secrets.js +256 -0
  84. package/dist/cli/commands/admin/secrets.js.map +1 -0
  85. package/dist/cli/commands/admin/settings.d.ts +28 -0
  86. package/dist/cli/commands/admin/settings.js +284 -0
  87. package/dist/cli/commands/admin/settings.js.map +1 -0
  88. package/dist/cli/commands/admin/token.d.ts +42 -0
  89. package/dist/cli/commands/admin/token.js +126 -0
  90. package/dist/cli/commands/admin/token.js.map +1 -0
  91. package/dist/cli/commands/admin/transfer-ownership.d.ts +15 -0
  92. package/dist/cli/commands/admin/transfer-ownership.js +106 -0
  93. package/dist/cli/commands/admin/transfer-ownership.js.map +1 -0
  94. package/dist/cli/commands/admin/user.d.ts +11 -0
  95. package/dist/cli/commands/admin/user.js +187 -0
  96. package/dist/cli/commands/admin/user.js.map +1 -0
  97. package/dist/cli/commands/clone.d.ts +25 -3
  98. package/dist/cli/commands/clone.js +142 -36
  99. package/dist/cli/commands/clone.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 +5 -1
  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 +54 -6
  113. package/dist/cli/commands/mcp.js.map +1 -1
  114. package/dist/cli/commands/r2.d.ts +3 -0
  115. package/dist/cli/commands/r2.js +223 -204
  116. package/dist/cli/commands/r2.js.map +1 -1
  117. package/dist/cli/commands/redeploy.js +65 -12
  118. package/dist/cli/commands/redeploy.js.map +1 -1
  119. package/dist/cli/commands/reset.d.ts +22 -6
  120. package/dist/cli/commands/reset.js +132 -34
  121. package/dist/cli/commands/reset.js.map +1 -1
  122. package/dist/cli/commands/serve.js +231 -26
  123. package/dist/cli/commands/serve.js.map +1 -1
  124. package/dist/cli/commands/sync.d.ts +1 -1
  125. package/dist/cli/commands/sync.js +237 -227
  126. package/dist/cli/commands/sync.js.map +1 -1
  127. package/dist/cli/crypto-bundle.d.ts +39 -0
  128. package/dist/cli/crypto-bundle.js +94 -0
  129. package/dist/cli/crypto-bundle.js.map +1 -0
  130. package/dist/cli/index.js +24 -26
  131. package/dist/cli/index.js.map +1 -1
  132. package/dist/cli/railway-pin.d.ts +68 -0
  133. package/dist/cli/railway-pin.js +96 -0
  134. package/dist/cli/railway-pin.js.map +1 -0
  135. package/dist/cli/railway-provisioning.d.ts +53 -0
  136. package/dist/cli/railway-provisioning.js +85 -0
  137. package/dist/cli/railway-provisioning.js.map +1 -0
  138. package/dist/cli/setup-wizard.d.ts +30 -49
  139. package/dist/cli/setup-wizard.js +39 -40
  140. package/dist/cli/setup-wizard.js.map +1 -1
  141. package/dist/core/accent-palette.d.ts +22 -0
  142. package/dist/core/accent-palette.js +47 -0
  143. package/dist/core/accent-palette.js.map +1 -0
  144. package/dist/core/artifact-asset-urls.d.ts +51 -0
  145. package/dist/core/artifact-asset-urls.js +79 -0
  146. package/dist/core/artifact-asset-urls.js.map +1 -0
  147. package/dist/core/artifact-bundle.d.ts +69 -0
  148. package/dist/core/artifact-bundle.js +305 -0
  149. package/dist/core/artifact-bundle.js.map +1 -0
  150. package/dist/core/artifact-escape.d.ts +5 -0
  151. package/dist/core/artifact-escape.js +26 -0
  152. package/dist/core/artifact-escape.js.map +1 -0
  153. package/dist/core/artifact-export.d.ts +17 -0
  154. package/dist/core/artifact-export.js +529 -0
  155. package/dist/core/artifact-export.js.map +1 -0
  156. package/dist/core/cell-anchor.d.ts +29 -0
  157. package/dist/core/cell-anchor.js +53 -0
  158. package/dist/core/cell-anchor.js.map +1 -0
  159. package/dist/core/comment-anchor.d.ts +41 -0
  160. package/dist/core/comment-anchor.js +147 -0
  161. package/dist/core/comment-anchor.js.map +1 -0
  162. package/dist/core/commit-messages.d.ts +57 -0
  163. package/dist/core/commit-messages.js +85 -0
  164. package/dist/core/commit-messages.js.map +1 -0
  165. package/dist/core/embeds.d.ts +96 -0
  166. package/dist/core/embeds.js +196 -0
  167. package/dist/core/embeds.js.map +1 -0
  168. package/dist/core/entity-body-templates.d.ts +21 -0
  169. package/dist/core/entity-body-templates.js +67 -0
  170. package/dist/core/entity-body-templates.js.map +1 -0
  171. package/dist/core/entity-types-catalog.d.ts +65 -0
  172. package/dist/core/entity-types-catalog.js +142 -0
  173. package/dist/core/entity-types-catalog.js.map +1 -0
  174. package/dist/core/field-library.d.ts +62 -0
  175. package/dist/core/field-library.js +129 -0
  176. package/dist/core/field-library.js.map +1 -0
  177. package/dist/core/folder-paths.d.ts +41 -0
  178. package/dist/core/folder-paths.js +95 -0
  179. package/dist/core/folder-paths.js.map +1 -0
  180. package/dist/core/folder-sidecar.d.ts +36 -0
  181. package/dist/core/folder-sidecar.js +91 -0
  182. package/dist/core/folder-sidecar.js.map +1 -0
  183. package/dist/core/format-registry.d.ts +170 -0
  184. package/dist/core/format-registry.js +412 -0
  185. package/dist/core/format-registry.js.map +1 -0
  186. package/dist/core/graph.d.ts +773 -14
  187. package/dist/core/graph.js +2269 -308
  188. package/dist/core/graph.js.map +1 -1
  189. package/dist/core/history-diff.d.ts +35 -0
  190. package/dist/core/history-diff.js +114 -0
  191. package/dist/core/history-diff.js.map +1 -0
  192. package/dist/core/refs.d.ts +41 -0
  193. package/dist/core/refs.js +80 -0
  194. package/dist/core/refs.js.map +1 -0
  195. package/dist/core/schema-registry.d.ts +66 -0
  196. package/dist/core/schema-registry.js +198 -37
  197. package/dist/core/schema-registry.js.map +1 -1
  198. package/dist/core/schemas/connector.d.ts +67 -0
  199. package/dist/core/schemas/connector.js +100 -0
  200. package/dist/core/schemas/connector.js.map +1 -0
  201. package/dist/core/schemas/workspace.d.ts +122 -0
  202. package/dist/core/schemas/workspace.js +211 -0
  203. package/dist/core/schemas/workspace.js.map +1 -0
  204. package/dist/core/secrets/SecretStore.d.ts +77 -0
  205. package/dist/core/secrets/SecretStore.js +13 -0
  206. package/dist/core/secrets/SecretStore.js.map +1 -0
  207. package/dist/core/secrets/SettingsResolver.d.ts +54 -0
  208. package/dist/core/secrets/SettingsResolver.js +80 -0
  209. package/dist/core/secrets/SettingsResolver.js.map +1 -0
  210. package/dist/core/secrets/SettingsStore.d.ts +30 -0
  211. package/dist/core/secrets/SettingsStore.js +9 -0
  212. package/dist/core/secrets/SettingsStore.js.map +1 -0
  213. package/dist/core/secrets/SqliteEncryptedStore.d.ts +90 -0
  214. package/dist/core/secrets/SqliteEncryptedStore.js +598 -0
  215. package/dist/core/secrets/SqliteEncryptedStore.js.map +1 -0
  216. package/dist/core/secrets/audit.d.ts +36 -0
  217. package/dist/core/secrets/audit.js +60 -0
  218. package/dist/core/secrets/audit.js.map +1 -0
  219. package/dist/core/secrets/auth-db-migration.d.ts +129 -0
  220. package/dist/core/secrets/auth-db-migration.js +653 -0
  221. package/dist/core/secrets/auth-db-migration.js.map +1 -0
  222. package/dist/core/secrets/bundle.d.ts +141 -0
  223. package/dist/core/secrets/bundle.js +435 -0
  224. package/dist/core/secrets/bundle.js.map +1 -0
  225. package/dist/core/secrets/dual-write.d.ts +81 -0
  226. package/dist/core/secrets/dual-write.js +247 -0
  227. package/dist/core/secrets/dual-write.js.map +1 -0
  228. package/dist/core/secrets/encryption.d.ts +44 -0
  229. package/dist/core/secrets/encryption.js +97 -0
  230. package/dist/core/secrets/encryption.js.map +1 -0
  231. package/dist/core/secrets/index.d.ts +49 -0
  232. package/dist/core/secrets/index.js +74 -0
  233. package/dist/core/secrets/index.js.map +1 -0
  234. package/dist/core/secrets/master-key.d.ts +38 -0
  235. package/dist/core/secrets/master-key.js +122 -0
  236. package/dist/core/secrets/master-key.js.map +1 -0
  237. package/dist/core/secrets/probes/anthropic.d.ts +98 -0
  238. package/dist/core/secrets/probes/anthropic.js +300 -0
  239. package/dist/core/secrets/probes/anthropic.js.map +1 -0
  240. package/dist/core/secrets/probes/brave.d.ts +9 -0
  241. package/dist/core/secrets/probes/brave.js +15 -0
  242. package/dist/core/secrets/probes/brave.js.map +1 -0
  243. package/dist/core/secrets/probes/r2.d.ts +15 -0
  244. package/dist/core/secrets/probes/r2.js +14 -0
  245. package/dist/core/secrets/probes/r2.js.map +1 -0
  246. package/dist/core/secrets/probes/tavily.d.ts +18 -0
  247. package/dist/core/secrets/probes/tavily.js +58 -0
  248. package/dist/core/secrets/probes/tavily.js.map +1 -0
  249. package/dist/core/secrets/probes/voyage.d.ts +13 -0
  250. package/dist/core/secrets/probes/voyage.js +52 -0
  251. package/dist/core/secrets/probes/voyage.js.map +1 -0
  252. package/dist/core/secrets/r2-structural-migration.d.ts +39 -0
  253. package/dist/core/secrets/r2-structural-migration.js +109 -0
  254. package/dist/core/secrets/r2-structural-migration.js.map +1 -0
  255. package/dist/core/secrets/read-flip.d.ts +59 -0
  256. package/dist/core/secrets/read-flip.js +87 -0
  257. package/dist/core/secrets/read-flip.js.map +1 -0
  258. package/dist/core/secrets/registry.d.ts +188 -0
  259. package/dist/core/secrets/registry.js +616 -0
  260. package/dist/core/secrets/registry.js.map +1 -0
  261. package/dist/core/types.d.ts +77 -483
  262. package/dist/core/types.js +25 -3
  263. package/dist/core/types.js.map +1 -1
  264. package/dist/core/user-config.d.ts +75 -12
  265. package/dist/core/user-config.js +155 -14
  266. package/dist/core/user-config.js.map +1 -1
  267. package/dist/core/validation.d.ts +786 -1373
  268. package/dist/core/validation.js +458 -147
  269. package/dist/core/validation.js.map +1 -1
  270. package/dist/core/workspace-manager.d.ts +87 -14
  271. package/dist/core/workspace-manager.js +222 -94
  272. package/dist/core/workspace-manager.js.map +1 -1
  273. package/dist/core/workspace.d.ts +19 -5
  274. package/dist/core/workspace.js +67 -39
  275. package/dist/core/workspace.js.map +1 -1
  276. package/dist/mcp/comment-virtual-entity.d.ts +36 -0
  277. package/dist/mcp/comment-virtual-entity.js +71 -0
  278. package/dist/mcp/comment-virtual-entity.js.map +1 -0
  279. package/dist/mcp/connector-manager.d.ts +72 -2
  280. package/dist/mcp/connector-manager.js +211 -32
  281. package/dist/mcp/connector-manager.js.map +1 -1
  282. package/dist/mcp/oauth-provider.d.ts +0 -5
  283. package/dist/mcp/oauth-provider.js +10 -22
  284. package/dist/mcp/oauth-provider.js.map +1 -1
  285. package/dist/mcp/oauth-registry.d.ts +46 -8
  286. package/dist/mcp/oauth-registry.js +52 -13
  287. package/dist/mcp/oauth-registry.js.map +1 -1
  288. package/dist/mcp/server-discovery.d.ts +73 -0
  289. package/dist/mcp/server-discovery.js +164 -0
  290. package/dist/mcp/server-discovery.js.map +1 -0
  291. package/dist/mcp/server.d.ts +24 -3
  292. package/dist/mcp/server.js +53 -10
  293. package/dist/mcp/server.js.map +1 -1
  294. package/dist/mcp/state-signer.d.ts +62 -0
  295. package/dist/mcp/state-signer.js +205 -0
  296. package/dist/mcp/state-signer.js.map +1 -0
  297. package/dist/mcp/stdio-proxy.d.ts +67 -0
  298. package/dist/mcp/stdio-proxy.js +149 -0
  299. package/dist/mcp/stdio-proxy.js.map +1 -0
  300. package/dist/mcp/tools.d.ts +65 -2
  301. package/dist/mcp/tools.js +1772 -124
  302. package/dist/mcp/tools.js.map +1 -1
  303. package/dist/server/__tests__/helpers/graph-api.d.ts +16 -0
  304. package/dist/server/__tests__/helpers/graph-api.js +16 -0
  305. package/dist/server/__tests__/helpers/graph-api.js.map +1 -0
  306. package/dist/server/artifact-asset-mint.d.ts +41 -0
  307. package/dist/server/artifact-asset-mint.js +59 -0
  308. package/dist/server/artifact-asset-mint.js.map +1 -0
  309. package/dist/server/asset-index-queue.d.ts +98 -0
  310. package/dist/server/asset-index-queue.js +193 -0
  311. package/dist/server/asset-index-queue.js.map +1 -0
  312. package/dist/server/body-write-coordinator.d.ts +161 -0
  313. package/dist/server/body-write-coordinator.js +182 -0
  314. package/dist/server/body-write-coordinator.js.map +1 -0
  315. package/dist/server/cloud-billing-flow.d.ts +32 -0
  316. package/dist/server/cloud-billing-flow.js +75 -0
  317. package/dist/server/cloud-billing-flow.js.map +1 -0
  318. package/dist/server/commit-audit.d.ts +26 -0
  319. package/dist/server/commit-audit.js +30 -0
  320. package/dist/server/commit-audit.js.map +1 -0
  321. package/dist/server/index.d.ts +29 -3
  322. package/dist/server/index.js +657 -269
  323. package/dist/server/index.js.map +1 -1
  324. package/dist/server/middleware/sanitize.d.ts +46 -0
  325. package/dist/server/middleware/sanitize.js +182 -0
  326. package/dist/server/middleware/sanitize.js.map +1 -0
  327. package/dist/server/routes/artifact-export-api.d.ts +11 -0
  328. package/dist/server/routes/artifact-export-api.js +159 -0
  329. package/dist/server/routes/artifact-export-api.js.map +1 -0
  330. package/dist/server/routes/asset-api.d.ts +76 -1
  331. package/dist/server/routes/asset-api.js +761 -61
  332. package/dist/server/routes/asset-api.js.map +1 -1
  333. package/dist/server/routes/audit-api.d.ts +24 -0
  334. package/dist/server/routes/audit-api.js +117 -0
  335. package/dist/server/routes/audit-api.js.map +1 -0
  336. package/dist/server/routes/auth-api.js +532 -63
  337. package/dist/server/routes/auth-api.js.map +1 -1
  338. package/dist/server/routes/capture-api.d.ts +10 -3
  339. package/dist/server/routes/capture-api.js +213 -25
  340. package/dist/server/routes/capture-api.js.map +1 -1
  341. package/dist/server/routes/chat-sessions-api.d.ts +13 -0
  342. package/dist/server/routes/chat-sessions-api.js +455 -0
  343. package/dist/server/routes/chat-sessions-api.js.map +1 -0
  344. package/dist/server/routes/chat.d.ts +35 -1
  345. package/dist/server/routes/chat.js +699 -54
  346. package/dist/server/routes/chat.js.map +1 -1
  347. package/dist/server/routes/comments-api.d.ts +15 -0
  348. package/dist/server/routes/comments-api.js +444 -0
  349. package/dist/server/routes/comments-api.js.map +1 -0
  350. package/dist/server/routes/config-api.d.ts +3 -2
  351. package/dist/server/routes/config-api.js +179 -49
  352. package/dist/server/routes/config-api.js.map +1 -1
  353. package/dist/server/routes/connectors-api.js +177 -42
  354. package/dist/server/routes/connectors-api.js.map +1 -1
  355. package/dist/server/routes/event-ingest-api.d.ts +15 -0
  356. package/dist/server/routes/{meeting-ingest-api.js → event-ingest-api.js} +35 -20
  357. package/dist/server/routes/event-ingest-api.js.map +1 -0
  358. package/dist/server/routes/field-library-api.d.ts +28 -0
  359. package/dist/server/routes/field-library-api.js +126 -0
  360. package/dist/server/routes/field-library-api.js.map +1 -0
  361. package/dist/server/routes/git-http.d.ts +2 -2
  362. package/dist/server/routes/git-http.js +86 -39
  363. package/dist/server/routes/git-http.js.map +1 -1
  364. package/dist/server/routes/graph-api-access.d.ts +57 -0
  365. package/dist/server/routes/graph-api-access.js +112 -0
  366. package/dist/server/routes/graph-api-access.js.map +1 -0
  367. package/dist/server/routes/graph-api.d.ts +1 -1
  368. package/dist/server/routes/graph-api.js +1455 -325
  369. package/dist/server/routes/graph-api.js.map +1 -1
  370. package/dist/server/routes/health.d.ts +18 -0
  371. package/dist/server/routes/health.js +74 -0
  372. package/dist/server/routes/health.js.map +1 -0
  373. package/dist/server/routes/import-batch.d.ts +24 -0
  374. package/dist/server/routes/import-batch.js +33 -0
  375. package/dist/server/routes/import-batch.js.map +1 -0
  376. package/dist/server/routes/insights-api.d.ts +9 -2
  377. package/dist/server/routes/insights-api.js +355 -61
  378. package/dist/server/routes/insights-api.js.map +1 -1
  379. package/dist/server/routes/mcp.d.ts +7 -3
  380. package/dist/server/routes/mcp.js +24 -8
  381. package/dist/server/routes/mcp.js.map +1 -1
  382. package/dist/server/routes/oauth-api.d.ts +67 -0
  383. package/dist/server/routes/oauth-api.js +421 -0
  384. package/dist/server/routes/oauth-api.js.map +1 -0
  385. package/dist/server/routes/permissions-api.d.ts +9 -2
  386. package/dist/server/routes/permissions-api.js +87 -31
  387. package/dist/server/routes/permissions-api.js.map +1 -1
  388. package/dist/server/routes/r2-api.d.ts +25 -0
  389. package/dist/server/routes/r2-api.js +276 -0
  390. package/dist/server/routes/r2-api.js.map +1 -0
  391. package/dist/server/routes/secrets-api.d.ts +36 -0
  392. package/dist/server/routes/secrets-api.js +308 -0
  393. package/dist/server/routes/secrets-api.js.map +1 -0
  394. package/dist/server/routes/settings-api.d.ts +29 -0
  395. package/dist/server/routes/settings-api.js +180 -0
  396. package/dist/server/routes/settings-api.js.map +1 -0
  397. package/dist/server/routes/share-api.d.ts +32 -0
  398. package/dist/server/routes/share-api.js +234 -0
  399. package/dist/server/routes/share-api.js.map +1 -0
  400. package/dist/server/routes/views-api.js +51 -0
  401. package/dist/server/routes/views-api.js.map +1 -1
  402. package/dist/server/routes/workspace-api.d.ts +2 -1
  403. package/dist/server/routes/workspace-api.js +142 -23
  404. package/dist/server/routes/workspace-api.js.map +1 -1
  405. package/dist/server/routes/ws.d.ts +3 -2
  406. package/dist/server/routes/ws.js +68 -17
  407. package/dist/server/routes/ws.js.map +1 -1
  408. package/dist/server/session-manager.d.ts +48 -5
  409. package/dist/server/session-manager.js +182 -14
  410. package/dist/server/session-manager.js.map +1 -1
  411. package/dist/server/ws-hub.d.ts +124 -37
  412. package/dist/server/ws-hub.js +0 -0
  413. package/dist/server/ws-hub.js.map +1 -1
  414. package/dist/server/yjs-manager.d.ts +278 -7
  415. package/dist/server/yjs-manager.js +830 -38
  416. package/dist/server/yjs-manager.js.map +1 -1
  417. package/dist/server/yjs-persistence.d.ts +165 -0
  418. package/dist/server/yjs-persistence.js +557 -0
  419. package/dist/server/yjs-persistence.js.map +1 -0
  420. package/dist/server/yjs-text-diff.d.ts +32 -0
  421. package/dist/server/yjs-text-diff.js +61 -0
  422. package/dist/server/yjs-text-diff.js.map +1 -0
  423. package/dist/services/access-control.d.ts +73 -0
  424. package/dist/services/access-control.js +165 -0
  425. package/dist/services/access-control.js.map +1 -0
  426. package/dist/services/artifact-asset-token.d.ts +69 -0
  427. package/dist/services/artifact-asset-token.js +94 -0
  428. package/dist/services/artifact-asset-token.js.map +1 -0
  429. package/dist/services/artifact-library-sources.d.ts +3 -0
  430. package/dist/services/artifact-library-sources.js +44 -0
  431. package/dist/services/artifact-library-sources.js.map +1 -0
  432. package/dist/services/artifact-render-export.d.ts +97 -0
  433. package/dist/services/artifact-render-export.js +467 -0
  434. package/dist/services/artifact-render-export.js.map +1 -0
  435. package/dist/services/asset-caption-service.d.ts +103 -0
  436. package/dist/services/asset-caption-service.js +186 -0
  437. package/dist/services/asset-caption-service.js.map +1 -0
  438. package/dist/services/asset-delete-authz.d.ts +31 -0
  439. package/dist/services/asset-delete-authz.js +61 -0
  440. package/dist/services/asset-delete-authz.js.map +1 -0
  441. package/dist/services/asset-finalize-service.d.ts +58 -0
  442. package/dist/services/asset-finalize-service.js +216 -0
  443. package/dist/services/asset-finalize-service.js.map +1 -0
  444. package/dist/services/asset-import-service.d.ts +111 -0
  445. package/dist/services/asset-import-service.js +394 -0
  446. package/dist/services/asset-import-service.js.map +1 -0
  447. package/dist/services/asset-index-sweep.d.ts +95 -0
  448. package/dist/services/asset-index-sweep.js +249 -0
  449. package/dist/services/asset-index-sweep.js.map +1 -0
  450. package/dist/services/asset-lifecycle-check.d.ts +22 -0
  451. package/dist/services/asset-lifecycle-check.js +80 -0
  452. package/dist/services/asset-lifecycle-check.js.map +1 -0
  453. package/dist/services/asset-listing.d.ts +72 -0
  454. package/dist/services/asset-listing.js +321 -0
  455. package/dist/services/asset-listing.js.map +1 -0
  456. package/dist/services/asset-presign-service.d.ts +68 -0
  457. package/dist/services/asset-presign-service.js +124 -0
  458. package/dist/services/asset-presign-service.js.map +1 -0
  459. package/dist/services/asset-sidecar-service.d.ts +28 -0
  460. package/dist/services/asset-sidecar-service.js +79 -0
  461. package/dist/services/asset-sidecar-service.js.map +1 -0
  462. package/dist/services/asset-upload-errors.d.ts +41 -0
  463. package/dist/services/asset-upload-errors.js +45 -0
  464. package/dist/services/asset-upload-errors.js.map +1 -0
  465. package/dist/services/asset-upload-service.d.ts +56 -0
  466. package/dist/services/asset-upload-service.js +200 -0
  467. package/dist/services/asset-upload-service.js.map +1 -0
  468. package/dist/services/asset-upload-token.d.ts +58 -0
  469. package/dist/services/asset-upload-token.js +75 -0
  470. package/dist/services/asset-upload-token.js.map +1 -0
  471. package/dist/services/assets/asset-index-service.d.ts +127 -0
  472. package/dist/services/assets/asset-index-service.js +227 -0
  473. package/dist/services/assets/asset-index-service.js.map +1 -0
  474. package/dist/services/assets/base.d.ts +128 -2
  475. package/dist/services/assets/base.js +98 -1
  476. package/dist/services/assets/base.js.map +1 -1
  477. package/dist/services/assets/index.d.ts +114 -1
  478. package/dist/services/assets/index.js +221 -0
  479. package/dist/services/assets/index.js.map +1 -1
  480. package/dist/services/assets/local.d.ts +16 -1
  481. package/dist/services/assets/local.js +110 -1
  482. package/dist/services/assets/local.js.map +1 -1
  483. package/dist/services/assets/r2-sync.d.ts +88 -0
  484. package/dist/services/assets/r2-sync.js +412 -0
  485. package/dist/services/assets/r2-sync.js.map +1 -0
  486. package/dist/services/assets/r2.d.ts +87 -1
  487. package/dist/services/assets/r2.js +203 -1
  488. package/dist/services/assets/r2.js.map +1 -1
  489. package/dist/services/auth-service.d.ts +312 -45
  490. package/dist/services/auth-service.js +1011 -195
  491. package/dist/services/auth-service.js.map +1 -1
  492. package/dist/services/chat-session-service.d.ts +188 -0
  493. package/dist/services/chat-session-service.js +512 -0
  494. package/dist/services/chat-session-service.js.map +1 -0
  495. package/dist/services/cloud-inference-billing.d.ts +64 -0
  496. package/dist/services/cloud-inference-billing.js +313 -0
  497. package/dist/services/cloud-inference-billing.js.map +1 -0
  498. package/dist/services/comment-service.d.ts +97 -0
  499. package/dist/services/comment-service.js +341 -0
  500. package/dist/services/comment-service.js.map +1 -0
  501. package/dist/services/comment-virtual-entity.d.ts +36 -0
  502. package/dist/services/comment-virtual-entity.js +71 -0
  503. package/dist/services/comment-virtual-entity.js.map +1 -0
  504. package/dist/services/convert-service.d.ts +64 -0
  505. package/dist/services/convert-service.js +68 -0
  506. package/dist/services/convert-service.js.map +1 -0
  507. package/dist/services/csv-service.d.ts +22 -17
  508. package/dist/services/csv-service.js +55 -92
  509. package/dist/services/csv-service.js.map +1 -1
  510. package/dist/services/entity-mutations.d.ts +213 -0
  511. package/dist/services/entity-mutations.js +380 -0
  512. package/dist/services/entity-mutations.js.map +1 -0
  513. package/dist/services/{meeting-processor.d.ts → event-processor.d.ts} +15 -8
  514. package/dist/services/{meeting-processor.js → event-processor.js} +124 -65
  515. package/dist/services/event-processor.js.map +1 -0
  516. package/dist/services/extract/docx.d.ts +1 -0
  517. package/dist/services/extract/docx.js +233 -0
  518. package/dist/services/extract/docx.js.map +1 -0
  519. package/dist/services/extract/index.d.ts +9 -0
  520. package/dist/services/extract/index.js +10 -0
  521. package/dist/services/extract/index.js.map +1 -0
  522. package/dist/services/extract/pdf.d.ts +13 -0
  523. package/dist/services/extract/pdf.js +69 -0
  524. package/dist/services/extract/pdf.js.map +1 -0
  525. package/dist/services/folder-creation.d.ts +33 -0
  526. package/dist/services/folder-creation.js +103 -0
  527. package/dist/services/folder-creation.js.map +1 -0
  528. package/dist/services/git.d.ts +58 -0
  529. package/dist/services/git.js +194 -55
  530. package/dist/services/git.js.map +1 -1
  531. package/dist/services/graph-maintenance.js +4 -4
  532. package/dist/services/graph-maintenance.js.map +1 -1
  533. package/dist/services/import-service.d.ts +51 -2
  534. package/dist/services/import-service.js +254 -107
  535. package/dist/services/import-service.js.map +1 -1
  536. package/dist/services/lint-service.js +10 -17
  537. package/dist/services/lint-service.js.map +1 -1
  538. package/dist/services/markdown.d.ts +12 -1
  539. package/dist/services/markdown.js +77 -9
  540. package/dist/services/markdown.js.map +1 -1
  541. package/dist/services/mention-detector.d.ts +23 -0
  542. package/dist/services/mention-detector.js +47 -0
  543. package/dist/services/mention-detector.js.map +1 -0
  544. package/dist/services/model-capabilities.d.ts +41 -0
  545. package/dist/services/model-capabilities.js +107 -0
  546. package/dist/services/model-capabilities.js.map +1 -0
  547. package/dist/services/notification-broadcast.d.ts +32 -0
  548. package/dist/services/notification-broadcast.js +38 -0
  549. package/dist/services/notification-broadcast.js.map +1 -0
  550. package/dist/services/notification-service.d.ts +41 -0
  551. package/dist/services/notification-service.js +100 -0
  552. package/dist/services/notification-service.js.map +1 -0
  553. package/dist/services/oauth-server-store.d.ts +147 -0
  554. package/dist/services/oauth-server-store.js +319 -0
  555. package/dist/services/oauth-server-store.js.map +1 -0
  556. package/dist/services/orphan-service.js +2 -2
  557. package/dist/services/orphan-service.js.map +1 -1
  558. package/dist/services/personal-folder.d.ts +40 -0
  559. package/dist/services/personal-folder.js +101 -0
  560. package/dist/services/personal-folder.js.map +1 -0
  561. package/dist/services/scratch-asset-promote.d.ts +57 -0
  562. package/dist/services/scratch-asset-promote.js +95 -0
  563. package/dist/services/scratch-asset-promote.js.map +1 -0
  564. package/dist/services/scratch-attachment-service.d.ts +196 -0
  565. package/dist/services/scratch-attachment-service.js +347 -0
  566. package/dist/services/scratch-attachment-service.js.map +1 -0
  567. package/dist/services/share-link-service.d.ts +57 -0
  568. package/dist/services/share-link-service.js +142 -0
  569. package/dist/services/share-link-service.js.map +1 -0
  570. package/dist/services/user-person-bridge.d.ts +136 -0
  571. package/dist/services/user-person-bridge.js +340 -0
  572. package/dist/services/user-person-bridge.js.map +1 -0
  573. package/dist/services/vector-service.d.ts +282 -5
  574. package/dist/services/vector-service.js +585 -29
  575. package/dist/services/vector-service.js.map +1 -1
  576. package/dist/services/workspace-access.d.ts +108 -0
  577. package/dist/services/workspace-access.js +149 -0
  578. package/dist/services/workspace-access.js.map +1 -0
  579. package/dist/services/workspace-assets-folder.d.ts +46 -0
  580. package/dist/services/workspace-assets-folder.js +75 -0
  581. package/dist/services/workspace-assets-folder.js.map +1 -0
  582. package/dist/utils/git.d.ts +17 -2
  583. package/dist/utils/git.js +23 -7
  584. package/dist/utils/git.js.map +1 -1
  585. package/dist/utils/log.d.ts +42 -0
  586. package/dist/utils/log.js +137 -0
  587. package/dist/utils/log.js.map +1 -0
  588. package/dist/utils/preflight.js +2 -2
  589. package/dist/utils/preflight.js.map +1 -1
  590. package/dist/utils/version-checker.d.ts +12 -19
  591. package/dist/utils/version-checker.js +14 -104
  592. package/dist/utils/version-checker.js.map +1 -1
  593. package/dist/web/_app/immutable/assets/0.Bs_z3Z86.css +2 -0
  594. package/dist/web/_app/immutable/assets/12.DlIf1mKh.css +1 -0
  595. package/dist/web/_app/immutable/assets/14.7d-Q37wc.css +1 -0
  596. package/dist/web/_app/immutable/assets/15.BwBFdc1D.css +1 -0
  597. package/dist/web/_app/immutable/assets/16.CmLrbzZp.css +1 -0
  598. package/dist/web/_app/immutable/assets/17.DcuK5ZVm.css +1 -0
  599. package/dist/web/_app/immutable/assets/2.DATnR31c.css +1 -0
  600. package/dist/web/_app/immutable/assets/3.Cz4H8n_O.css +1 -0
  601. package/dist/web/_app/immutable/assets/4.aDHteTDy.css +1 -0
  602. package/dist/web/_app/immutable/assets/6.CF1i5Bon.css +1 -0
  603. package/dist/web/_app/immutable/assets/ArtifactEntityView.C4ooklFD.css +1 -0
  604. package/dist/web/_app/immutable/assets/AssetLibraryPicker.BOFW0MvF.css +1 -0
  605. package/dist/web/_app/immutable/assets/BulkActionsBar.cmKvHzRK.css +1 -0
  606. package/dist/web/_app/immutable/assets/CalendarView.lBCvS3X5.css +1 -0
  607. package/dist/web/_app/immutable/assets/CodeMirrorEditor.D6hf2pNJ.css +1 -0
  608. package/dist/web/_app/immutable/assets/CopyField.DVGZtw4U.css +1 -0
  609. package/dist/web/_app/immutable/assets/FolderMembersPanel.kiYnDFHu.css +1 -0
  610. package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
  611. package/dist/web/_app/immutable/assets/FolderPicker.Cp46GHe2.css +1 -0
  612. package/dist/web/_app/immutable/assets/GalleryView.WBGxxUQc.css +1 -0
  613. package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
  614. package/dist/web/_app/immutable/assets/KanbanView.BOaI5KFL.css +1 -0
  615. package/dist/web/_app/immutable/assets/Link.vV0ne105.css +1 -0
  616. package/dist/web/_app/immutable/assets/Markdown.BZnsSOSf.css +1 -0
  617. package/dist/web/_app/immutable/assets/Rail.ilusFgD4.css +1 -0
  618. package/dist/web/_app/immutable/assets/SettingsDialog.D7-BO6S_.css +1 -0
  619. package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
  620. package/dist/web/_app/immutable/assets/StopFilledAlt.fNlDN65D.css +1 -0
  621. package/dist/web/_app/immutable/assets/TimelineView.xAZBJhHw.css +1 -0
  622. package/dist/web/_app/immutable/assets/WorkspaceView.C8ErUJAY.css +1 -0
  623. package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
  624. package/dist/web/_app/immutable/assets/history-summary.LpmHXasl.css +1 -0
  625. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.CvHOgSBP.woff +0 -0
  626. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.DMJ8VG8y.woff2 +0 -0
  627. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.CB9ihrfo.woff +0 -0
  628. package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.DSY6xOcd.woff2 +0 -0
  629. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CZTNEAuW.woff2 +0 -0
  630. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CsGl1sm0.woff +0 -0
  631. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CDDApCn2.woff2 +0 -0
  632. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CYLoc0-x.woff +0 -0
  633. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.BNK2_mGO.woff2 +0 -0
  634. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.DpEwFAQM.woff +0 -0
  635. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.6ng42L7E.woff2 +0 -0
  636. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.BgVn5rGT.woff +0 -0
  637. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.Cu4Hd6ag.woff +0 -0
  638. package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.CuJfVYMP.woff2 +0 -0
  639. package/dist/web/_app/immutable/assets/inline-list.cqga56xT.css +1 -0
  640. package/dist/web/_app/immutable/assets/list-columns.BgnafZ4K.css +1 -0
  641. package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
  642. package/dist/web/_app/immutable/assets/select.B90KUqR4.css +1 -0
  643. package/dist/web/_app/immutable/assets/sheet.RF9RBmml.css +1 -0
  644. package/dist/web/_app/immutable/chunks/22qYtvr82.js +1 -0
  645. package/dist/web/_app/immutable/chunks/2f1VclTm.js +1 -0
  646. package/dist/web/_app/immutable/chunks/4xgUPoGj2.js +2 -0
  647. package/dist/web/_app/immutable/chunks/5CYQk4xR.js +1 -0
  648. package/dist/web/_app/immutable/chunks/6S9WOky52.js +1 -0
  649. package/dist/web/_app/immutable/chunks/9K8VREGP.js +1 -0
  650. package/dist/web/_app/immutable/chunks/B-n5q6ku.js +1 -0
  651. package/dist/web/_app/immutable/chunks/B0p2fSEV2.js +1 -0
  652. package/dist/web/_app/immutable/chunks/B2oi87jG.js +2 -0
  653. package/dist/web/_app/immutable/chunks/B5Rb52QU.js +1 -0
  654. package/dist/web/_app/immutable/chunks/B6Lt-qaJ.js +1 -0
  655. package/dist/web/_app/immutable/chunks/B6O-q2CN.js +1 -0
  656. package/dist/web/_app/immutable/chunks/B6qeIQZz.js +2 -0
  657. package/dist/web/_app/immutable/chunks/B9KfEsQw2.js +1 -0
  658. package/dist/web/_app/immutable/chunks/BB-RSeXQ.js +1 -0
  659. package/dist/web/_app/immutable/chunks/BCQQzpbj.js +1 -0
  660. package/dist/web/_app/immutable/chunks/BGdzd-Tc.js +1 -0
  661. package/dist/web/_app/immutable/chunks/BLs1h0Rh2.js +1 -0
  662. package/dist/web/_app/immutable/chunks/BPzV_xOS2.js +1 -0
  663. package/dist/web/_app/immutable/chunks/BT2C6q8n.js +1 -0
  664. package/dist/web/_app/immutable/chunks/BUesbLq2.js +1 -0
  665. package/dist/web/_app/immutable/chunks/BUrnwOw4.js +2 -0
  666. package/dist/web/_app/immutable/chunks/BV-iCKqa.js +1 -0
  667. package/dist/web/_app/immutable/chunks/BVCJtXyc.js +1 -0
  668. package/dist/web/_app/immutable/chunks/BY9a3GSt.js +6 -0
  669. package/dist/web/_app/immutable/chunks/BZi3uKF4.js +1 -0
  670. package/dist/web/_app/immutable/chunks/BbfHGU9n2.js +1 -0
  671. package/dist/web/_app/immutable/chunks/Bbqu2-5G2.js +1 -0
  672. package/dist/web/_app/immutable/chunks/BbsX1Slr.js +3 -0
  673. package/dist/web/_app/immutable/chunks/BcwjqHaZ2.js +1 -0
  674. package/dist/web/_app/immutable/chunks/BizeEpTx.js +2 -0
  675. package/dist/web/_app/immutable/chunks/BlgjVmFM2.js +14 -0
  676. package/dist/web/_app/immutable/chunks/BocSRgv12.js +1 -0
  677. package/dist/web/_app/immutable/chunks/BojBYqc3.js +1 -0
  678. package/dist/web/_app/immutable/chunks/BpCG9m962.js +1 -0
  679. package/dist/web/_app/immutable/chunks/BqvnBg_y.js +1 -0
  680. package/dist/web/_app/immutable/chunks/BsT0J1QD.js +1 -0
  681. package/dist/web/_app/immutable/chunks/BsW72fyR2.js +1 -0
  682. package/dist/web/_app/immutable/chunks/Bti_XKwx.js +2692 -0
  683. package/dist/web/_app/immutable/chunks/Bua97Had2.js +2 -0
  684. package/dist/web/_app/immutable/chunks/BuhW5Fr0.js +689 -0
  685. package/dist/web/_app/immutable/chunks/Bx74EEyn2.js +1 -0
  686. package/dist/web/_app/immutable/chunks/BxPN0T61.js +1 -0
  687. package/dist/web/_app/immutable/chunks/Bz9lrgGs.js +1 -0
  688. package/dist/web/_app/immutable/chunks/BzaxZ6j12.js +1 -0
  689. package/dist/web/_app/immutable/chunks/C1B4xDs0.js +1 -0
  690. package/dist/web/_app/immutable/chunks/C1trcC8M.js +7 -0
  691. package/dist/web/_app/immutable/chunks/C9tvkk7Y2.js +22 -0
  692. package/dist/web/_app/immutable/chunks/CBQjdDZf.js +1 -0
  693. package/dist/web/_app/immutable/chunks/CDeazMFW2.js +2 -0
  694. package/dist/web/_app/immutable/chunks/CEahbtnP.js +1 -0
  695. package/dist/web/_app/immutable/chunks/CGjVCd0e.js +8 -0
  696. package/dist/web/_app/immutable/chunks/CICK9maP.js +1 -0
  697. package/dist/web/_app/immutable/chunks/CIoNEHQ82.js +184 -0
  698. package/dist/web/_app/immutable/chunks/CP8_U450.js +1 -0
  699. package/dist/web/_app/immutable/chunks/CQ1eQ93t2.js +6 -0
  700. package/dist/web/_app/immutable/chunks/CUFQMEBn2.js +1 -0
  701. package/dist/web/_app/immutable/chunks/CYEYDNwO2.js +1 -0
  702. package/dist/web/_app/immutable/chunks/CYyIP7kP2.js +66 -0
  703. package/dist/web/_app/immutable/chunks/CZgFaimi2.js +83 -0
  704. package/dist/web/_app/immutable/chunks/CZqvCTCv.js +1 -0
  705. package/dist/web/_app/immutable/chunks/CcI9jYBV.js +1 -0
  706. package/dist/web/_app/immutable/chunks/CcWaWbrI2.js +1 -0
  707. package/dist/web/_app/immutable/chunks/CdtzRVZK.js +1 -0
  708. package/dist/web/_app/immutable/chunks/CfYG72Hc.js +1 -0
  709. package/dist/web/_app/immutable/chunks/Ch1kmm3J2.js +1 -0
  710. package/dist/web/_app/immutable/chunks/CmSSN61R2.js +1 -0
  711. package/dist/web/_app/immutable/chunks/Cqm5wAin.js +1 -0
  712. package/dist/web/_app/immutable/chunks/CuYPXpWU.js +1 -0
  713. package/dist/web/_app/immutable/chunks/CvSEodTA.js +1 -0
  714. package/dist/web/_app/immutable/chunks/CvqqrTrj.js +1 -0
  715. package/dist/web/_app/immutable/chunks/CwAmWt6h.js +1 -0
  716. package/dist/web/_app/immutable/chunks/CwP3Oa7F.js +1 -0
  717. package/dist/web/_app/immutable/chunks/CyTluew1.js +2 -0
  718. package/dist/web/_app/immutable/chunks/CzXdOgVl2.js +7 -0
  719. package/dist/web/_app/immutable/chunks/D0IAituJ.js +1 -0
  720. package/dist/web/_app/immutable/chunks/D0W7c6Sg.js +185 -0
  721. package/dist/web/_app/immutable/chunks/D0rBhnqB2.js +1 -0
  722. package/dist/web/_app/immutable/chunks/D1-GZSN1.js +1 -0
  723. package/dist/web/_app/immutable/chunks/D1yvtriI.js +1 -0
  724. package/dist/web/_app/immutable/chunks/D25NMRpl.js +1 -0
  725. package/dist/web/_app/immutable/chunks/D8wZ2xul.js +4 -0
  726. package/dist/web/_app/immutable/chunks/DA3HEX3X.js +1 -0
  727. package/dist/web/_app/immutable/chunks/DD9wj4ca2.js +1 -0
  728. package/dist/web/_app/immutable/chunks/DJ1YeiJL2.js +1 -0
  729. package/dist/web/_app/immutable/chunks/DKFZnpVC.js +5 -0
  730. package/dist/web/_app/immutable/chunks/DKJl40hl.js +1 -0
  731. package/dist/web/_app/immutable/chunks/DPUVu0T0.js +1 -0
  732. package/dist/web/_app/immutable/chunks/DQMWa2t7.js +1 -0
  733. package/dist/web/_app/immutable/chunks/DXsFrDer2.js +1 -0
  734. package/dist/web/_app/immutable/chunks/DYc5KW3F.js +1 -0
  735. package/dist/web/_app/immutable/chunks/DZcTwXBW.js +1 -0
  736. package/dist/web/_app/immutable/chunks/DcPrzUMJ.js +1 -0
  737. package/dist/web/_app/immutable/chunks/DdPO8kRu2.js +2 -0
  738. package/dist/web/_app/immutable/chunks/DeOXyJZw2.js +1 -0
  739. package/dist/web/_app/immutable/chunks/DfufUFR1.js +2 -0
  740. package/dist/web/_app/immutable/chunks/DiQg3ing.js +1 -0
  741. package/dist/web/_app/immutable/chunks/DjIqa1_y.js +2 -0
  742. package/dist/web/_app/immutable/chunks/DkJ1dkxV2.js +1 -0
  743. package/dist/web/_app/immutable/chunks/Dl63IUnH2.js +224 -0
  744. package/dist/web/_app/immutable/chunks/DmFdD6zT.js +1 -0
  745. package/dist/web/_app/immutable/chunks/Dn3R8S-U.js +1 -0
  746. package/dist/web/_app/immutable/chunks/DpNr1GQ2.js +1 -0
  747. package/dist/web/_app/immutable/chunks/DpVNDHXz.js +2 -0
  748. package/dist/web/_app/immutable/chunks/DuxziNnw.js +1 -0
  749. package/dist/web/_app/immutable/chunks/Dv3A3Wcj.js +1 -0
  750. package/dist/web/_app/immutable/chunks/FuiJnZG0.js +1 -0
  751. package/dist/web/_app/immutable/chunks/Izkulod7.js +1 -0
  752. package/dist/web/_app/immutable/chunks/KZY6ongq2.js +2 -0
  753. package/dist/web/_app/immutable/chunks/LYL8znYR2.js +23 -0
  754. package/dist/web/_app/immutable/chunks/PhN6tXuJ2.js +1 -0
  755. package/dist/web/_app/immutable/chunks/PyLyCpuL.js +1 -0
  756. package/dist/web/_app/immutable/chunks/RK4gCWN0.js +2 -0
  757. package/dist/web/_app/immutable/chunks/VsBngTf4.js +2 -0
  758. package/dist/web/_app/immutable/chunks/XcWejFm_.js +5 -0
  759. package/dist/web/_app/immutable/chunks/al_nidE9.js +1 -0
  760. package/dist/web/_app/immutable/chunks/e50-izZO2.js +1 -0
  761. package/dist/web/_app/immutable/chunks/hG-QCarB.js +1 -0
  762. package/dist/web/_app/immutable/chunks/hStvCHkX.js +1 -0
  763. package/dist/web/_app/immutable/chunks/iJVY9p0y.js +3 -0
  764. package/dist/web/_app/immutable/chunks/kNaey6uv.js +1 -0
  765. package/dist/web/_app/immutable/chunks/pIXNe0C1.js +1 -0
  766. package/dist/web/_app/immutable/chunks/pNSRq_1B.js +2 -0
  767. package/dist/web/_app/immutable/chunks/qwr5boV8.js +1 -0
  768. package/dist/web/_app/immutable/chunks/rjjyuGhb.js +1 -0
  769. package/dist/web/_app/immutable/chunks/sg-T-FoN.js +1 -0
  770. package/dist/web/_app/immutable/chunks/uBgoVlsx.js +3 -0
  771. package/dist/web/_app/immutable/chunks/ulshNz6x.js +2 -0
  772. package/dist/web/_app/immutable/chunks/xY0c-UfG.js +3 -0
  773. package/dist/web/_app/immutable/chunks/xeNvx4Bl2.js +1 -0
  774. package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
  775. package/dist/web/_app/immutable/entry/app.pNUW-q4U.js +2 -0
  776. package/dist/web/_app/immutable/entry/start.DxGtIGG_.js +1 -0
  777. package/dist/web/_app/immutable/nodes/0.D6ZCY_R6.js +2 -0
  778. package/dist/web/_app/immutable/nodes/1.BryH3TNr.js +1 -0
  779. package/dist/web/_app/immutable/nodes/10.CMZMvR17.js +1 -0
  780. package/dist/web/_app/immutable/nodes/11.QHx_JShx.js +1 -0
  781. package/dist/web/_app/immutable/nodes/12.CiRWbb4X.js +1 -0
  782. package/dist/web/_app/immutable/nodes/13.CYrHXCA8.js +1 -0
  783. package/dist/web/_app/immutable/nodes/14.K18eIE5Z.js +1 -0
  784. package/dist/web/_app/immutable/nodes/15.DxgnZ61h.js +1 -0
  785. package/dist/web/_app/immutable/nodes/16.Dn6iuWIo.js +1 -0
  786. package/dist/web/_app/immutable/nodes/17.viwS7vTR.js +77 -0
  787. package/dist/web/_app/immutable/nodes/2.BQkQ_uUM.js +122 -0
  788. package/dist/web/_app/immutable/nodes/3.B4pqXsqq.js +6 -0
  789. package/dist/web/_app/immutable/nodes/4.CKXEgIAP.js +11 -0
  790. package/dist/web/_app/immutable/nodes/5.A2TASl4Q.js +1 -0
  791. package/dist/web/_app/immutable/nodes/6.DaIRO3SI.js +6 -0
  792. package/dist/web/_app/immutable/nodes/7.ga2UvFm-.js +1 -0
  793. package/dist/web/_app/immutable/nodes/8.BTEWT81u.js +1 -0
  794. package/dist/web/_app/immutable/nodes/9.BVxo0E0c.js +1 -0
  795. package/dist/web/_app/version.json +1 -1
  796. package/dist/web/favicon-16.png +0 -0
  797. package/dist/web/favicon-180.png +0 -0
  798. package/dist/web/favicon-32.png +0 -0
  799. package/dist/web/favicon-48.png +0 -0
  800. package/dist/web/favicon-512.png +0 -0
  801. package/dist/web/favicon.ico +0 -0
  802. package/dist/web/favicon.svg +8 -0
  803. package/dist/web/index.html +56 -21
  804. package/dist/web/studiograph-logomark.svg +29 -0
  805. package/package.json +35 -14
  806. package/dist/agent/skills/enrich-entities.md +0 -136
  807. package/dist/agent/skills/sync-configuration.md +0 -119
  808. package/dist/agent/skills/sync-setup.md +0 -82
  809. package/dist/agent/tools/message-tools.d.ts +0 -42
  810. package/dist/agent/tools/message-tools.js +0 -106
  811. package/dist/agent/tools/message-tools.js.map +0 -1
  812. package/dist/cli/commands/app.d.ts +0 -7
  813. package/dist/cli/commands/app.js +0 -268
  814. package/dist/cli/commands/app.js.map +0 -1
  815. package/dist/cli/commands/clear.d.ts +0 -5
  816. package/dist/cli/commands/clear.js +0 -36
  817. package/dist/cli/commands/clear.js.map +0 -1
  818. package/dist/cli/commands/collection.d.ts +0 -10
  819. package/dist/cli/commands/collection.js.map +0 -1
  820. package/dist/cli/commands/join.d.ts +0 -9
  821. package/dist/cli/commands/join.js +0 -255
  822. package/dist/cli/commands/join.js.map +0 -1
  823. package/dist/cli/commands/start.d.ts +0 -7
  824. package/dist/cli/commands/start.js +0 -584
  825. package/dist/cli/commands/start.js.map +0 -1
  826. package/dist/cli/commands/update.d.ts +0 -8
  827. package/dist/cli/commands/update.js +0 -155
  828. package/dist/cli/commands/update.js.map +0 -1
  829. package/dist/cli/commands/user.d.ts +0 -7
  830. package/dist/cli/commands/user.js +0 -175
  831. package/dist/cli/commands/user.js.map +0 -1
  832. package/dist/cli/scaffolding.d.ts +0 -12
  833. package/dist/cli/scaffolding.js +0 -397
  834. package/dist/cli/scaffolding.js.map +0 -1
  835. package/dist/integrations/registry.d.ts +0 -8
  836. package/dist/integrations/registry.js +0 -7
  837. package/dist/integrations/registry.js.map +0 -1
  838. package/dist/integrations/types.d.ts +0 -43
  839. package/dist/integrations/types.js +0 -5
  840. package/dist/integrations/types.js.map +0 -1
  841. package/dist/lib/lib/utils.d.ts +0 -2
  842. package/dist/lib/lib/utils.js +0 -6
  843. package/dist/lib/lib/utils.js.map +0 -1
  844. package/dist/server/chrome/chrome.css +0 -691
  845. package/dist/server/chrome/chrome.js +0 -374
  846. package/dist/server/commit-scheduler.d.ts +0 -39
  847. package/dist/server/commit-scheduler.js +0 -113
  848. package/dist/server/commit-scheduler.js.map +0 -1
  849. package/dist/server/plugin-loader.d.ts +0 -53
  850. package/dist/server/plugin-loader.js +0 -155
  851. package/dist/server/plugin-loader.js.map +0 -1
  852. package/dist/server/routes/meeting-ingest-api.d.ts +0 -14
  853. package/dist/server/routes/meeting-ingest-api.js.map +0 -1
  854. package/dist/server/routes/messages-api.d.ts +0 -15
  855. package/dist/server/routes/messages-api.js +0 -385
  856. package/dist/server/routes/messages-api.js.map +0 -1
  857. package/dist/services/batch-processor.d.ts +0 -49
  858. package/dist/services/batch-processor.js +0 -166
  859. package/dist/services/batch-processor.js.map +0 -1
  860. package/dist/services/briefing.d.ts +0 -26
  861. package/dist/services/briefing.js +0 -230
  862. package/dist/services/briefing.js.map +0 -1
  863. package/dist/services/heartbeat.d.ts +0 -28
  864. package/dist/services/heartbeat.js +0 -183
  865. package/dist/services/heartbeat.js.map +0 -1
  866. package/dist/services/image-import-service.d.ts +0 -24
  867. package/dist/services/image-import-service.js +0 -108
  868. package/dist/services/image-import-service.js.map +0 -1
  869. package/dist/services/insights.d.ts +0 -38
  870. package/dist/services/insights.js +0 -269
  871. package/dist/services/insights.js.map +0 -1
  872. package/dist/services/meeting-processor.js.map +0 -1
  873. package/dist/services/message-service.d.ts +0 -68
  874. package/dist/services/message-service.js +0 -220
  875. package/dist/services/message-service.js.map +0 -1
  876. package/dist/utils/workspace-config.d.ts +0 -8
  877. package/dist/utils/workspace-config.js +0 -22
  878. package/dist/utils/workspace-config.js.map +0 -1
  879. package/dist/web/_app/immutable/assets/0.uPSqtsC5.css +0 -1
  880. package/dist/web/_app/immutable/assets/11.2jzI3cZY.css +0 -1
  881. package/dist/web/_app/immutable/assets/12.CT4xL4K3.css +0 -1
  882. package/dist/web/_app/immutable/assets/13.BUrHkYry.css +0 -1
  883. package/dist/web/_app/immutable/assets/2.DpQWr6q6.css +0 -1
  884. package/dist/web/_app/immutable/assets/3.BxdqT7zi.css +0 -1
  885. package/dist/web/_app/immutable/assets/4.DdNqjd0T.css +0 -1
  886. package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
  887. package/dist/web/_app/immutable/assets/6.DXZr_rI_.css +0 -1
  888. package/dist/web/_app/immutable/assets/GraphView.D9ePpZez.css +0 -1
  889. package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
  890. package/dist/web/_app/immutable/assets/ViewToolbar.BWE03S64.css +0 -1
  891. package/dist/web/_app/immutable/assets/WorkspaceView.CgGDi_Zb.css +0 -1
  892. package/dist/web/_app/immutable/assets/wikilinks.CzMBkUMB.css +0 -1
  893. package/dist/web/_app/immutable/chunks/-jG4Obyh.js +0 -4
  894. package/dist/web/_app/immutable/chunks/2nrc8f_O.js +0 -1
  895. package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
  896. package/dist/web/_app/immutable/chunks/8Q3ZJIYu.js +0 -1
  897. package/dist/web/_app/immutable/chunks/B8ydT5xX.js +0 -2
  898. package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
  899. package/dist/web/_app/immutable/chunks/BEn6N5c2.js +0 -1
  900. package/dist/web/_app/immutable/chunks/BFNNbCAM.js +0 -1
  901. package/dist/web/_app/immutable/chunks/BFZZEUd5.js +0 -1
  902. package/dist/web/_app/immutable/chunks/BGk8kfOE.js +0 -2
  903. package/dist/web/_app/immutable/chunks/BIBCr278.js +0 -1
  904. package/dist/web/_app/immutable/chunks/BPCkkwqe.js +0 -1
  905. package/dist/web/_app/immutable/chunks/BhlvzGQx.js +0 -1
  906. package/dist/web/_app/immutable/chunks/BlMknQeF.js +0 -1
  907. package/dist/web/_app/immutable/chunks/BpjqrlCg.js +0 -1
  908. package/dist/web/_app/immutable/chunks/BrebtJNG.js +0 -18
  909. package/dist/web/_app/immutable/chunks/ByBZ7JIT.js +0 -1
  910. package/dist/web/_app/immutable/chunks/Bz0ZjVQE.js +0 -2
  911. package/dist/web/_app/immutable/chunks/BzJTZOK2.js +0 -1
  912. package/dist/web/_app/immutable/chunks/C0LVZhvn.js +0 -1
  913. package/dist/web/_app/immutable/chunks/C3uBrOS5.js +0 -1
  914. package/dist/web/_app/immutable/chunks/C8R1sDpW.js +0 -1
  915. package/dist/web/_app/immutable/chunks/CDRHrs0g.js +0 -1
  916. package/dist/web/_app/immutable/chunks/CN5_py1I.js +0 -1
  917. package/dist/web/_app/immutable/chunks/CPne482a.js +0 -1
  918. package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
  919. package/dist/web/_app/immutable/chunks/CWyU-seV.js +0 -1
  920. package/dist/web/_app/immutable/chunks/CX_61fY8.js +0 -5
  921. package/dist/web/_app/immutable/chunks/CYrVHOHA.js +0 -1
  922. package/dist/web/_app/immutable/chunks/ChsiIm-E.js +0 -1
  923. package/dist/web/_app/immutable/chunks/CojKppbh.js +0 -1
  924. package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
  925. package/dist/web/_app/immutable/chunks/CtYLtD7K.js +0 -1
  926. package/dist/web/_app/immutable/chunks/D-HDy5qS.js +0 -1
  927. package/dist/web/_app/immutable/chunks/D5aIYSkd.js +0 -1
  928. package/dist/web/_app/immutable/chunks/DBBXARVf.js +0 -1
  929. package/dist/web/_app/immutable/chunks/DFYOFE3o.js +0 -1
  930. package/dist/web/_app/immutable/chunks/DKaafS50.js +0 -1
  931. package/dist/web/_app/immutable/chunks/DUMOo1Pn.js +0 -1
  932. package/dist/web/_app/immutable/chunks/DWX9f6AF.js +0 -1
  933. package/dist/web/_app/immutable/chunks/DY8-EONP.js +0 -1
  934. package/dist/web/_app/immutable/chunks/DkoHPElM.js +0 -1
  935. package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
  936. package/dist/web/_app/immutable/chunks/DsnmJJEf.js +0 -1
  937. package/dist/web/_app/immutable/chunks/DujahU3W.js +0 -1
  938. package/dist/web/_app/immutable/chunks/FBn-ES5k.js +0 -1
  939. package/dist/web/_app/immutable/chunks/HQpwSOb3.js +0 -1
  940. package/dist/web/_app/immutable/chunks/KyjzlWRN.js +0 -2
  941. package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
  942. package/dist/web/_app/immutable/chunks/UwYfmrPx.js +0 -2
  943. package/dist/web/_app/immutable/chunks/W25ZVI8L.js +0 -2
  944. package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
  945. package/dist/web/_app/immutable/chunks/XjsuEnNE.js +0 -5
  946. package/dist/web/_app/immutable/chunks/ZD6ARAtb.js +0 -1
  947. package/dist/web/_app/immutable/chunks/pBTf4stg.js +0 -2
  948. package/dist/web/_app/immutable/chunks/rGIarcnp.js +0 -1
  949. package/dist/web/_app/immutable/chunks/vxEtkL8z.js +0 -1
  950. package/dist/web/_app/immutable/chunks/wDIGUaoU.js +0 -3
  951. package/dist/web/_app/immutable/entry/app.ZHiTM8WS.js +0 -2
  952. package/dist/web/_app/immutable/entry/start.C9-FfAVc.js +0 -1
  953. package/dist/web/_app/immutable/nodes/0.D92Orz8k.js +0 -2
  954. package/dist/web/_app/immutable/nodes/1.BMdyglM_.js +0 -1
  955. package/dist/web/_app/immutable/nodes/10.BilVDHSL.js +0 -1
  956. package/dist/web/_app/immutable/nodes/11.CS9E0Hic.js +0 -1
  957. package/dist/web/_app/immutable/nodes/12.D3BOxYzG.js +0 -1
  958. package/dist/web/_app/immutable/nodes/13.CClMKYtN.js +0 -1
  959. package/dist/web/_app/immutable/nodes/2.C8KKElPL.js +0 -267
  960. package/dist/web/_app/immutable/nodes/3.C5n5uiWU.js +0 -5
  961. package/dist/web/_app/immutable/nodes/4.DcGVvgiL.js +0 -11
  962. package/dist/web/_app/immutable/nodes/5.DxIjnFQO.js +0 -4
  963. package/dist/web/_app/immutable/nodes/6.lkh6kKLj.js +0 -1
  964. package/dist/web/_app/immutable/nodes/7.Bg7SbfhA.js +0 -1
  965. package/dist/web/_app/immutable/nodes/8.DcXWCNBE.js +0 -1
  966. package/dist/web/_app/immutable/nodes/9.Cefi8Jfm.js +0 -1
@@ -18,22 +18,185 @@
18
18
  import { join } from 'path';
19
19
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
20
20
  import * as lancedb from '@lancedb/lancedb';
21
+ import { embeddedAssetIds } from '../core/embeds.js';
22
+ import { isCaptionableImage } from './assets/base.js';
23
+ import { tryResolve } from '../core/secrets/read-flip.js';
21
24
  const VOYAGE_API_URL = 'https://api.voyageai.com/v1/embeddings';
22
25
  const VOYAGE_MODEL = 'voyage-3';
23
26
  const VECTOR_DIM = 1024;
24
27
  const TABLE_NAME = 'entities';
28
+ /**
29
+ * Dedicated LanceDB table for an asset's MUTABLE index state (decision A1).
30
+ *
31
+ * Why a separate table, not columns on `entities` and not asset frontmatter:
32
+ * - Frontmatter is immutable + git-committed; writing `index_status` there
33
+ * would fire one async git commit per asset and defeat the import batching.
34
+ * (The immutable `indexable` flag DOES live in frontmatter — see P3a.)
35
+ * - New columns on the shared `entities` table force a schema migration on
36
+ * every existing row. A side table is additive and touches only assets.
37
+ */
38
+ const INDEX_STATE_TABLE = 'asset_index_state';
39
+ /**
40
+ * Derivation-logic version. BUMP this when caption/extraction output changes so
41
+ * the boot sweep RE-derives every asset (Codex migration rule: a row at a stale
42
+ * version is re-derived, never treated as "done"). Legacy assets have NO row at
43
+ * all — also re-derived, never skipped.
44
+ */
45
+ export const ASSET_INDEX_VERSION = 1;
25
46
  export class VectorService {
26
47
  dbPath;
27
- voyageApiKey;
48
+ /**
49
+ * Legacy fallback key passed via constructor for tests or for early-
50
+ * boot code paths that run before the secrets store is initialized.
51
+ * Live calls prefer `tryResolve('voyage.api_key')` so values written
52
+ * to the store via the UI / CLI take effect without a restart.
53
+ */
54
+ fallbackVoyageApiKey;
28
55
  db;
29
56
  table;
57
+ /** Lazily-opened side table for mutable asset index state (A1). */
58
+ stateTable;
59
+ stateInitialized = false;
30
60
  lastIndexedPath;
31
61
  initialized = false;
62
+ // ── Single-flight guards (one in-flight init per resource) ──
63
+ // `init()` and `initStateTable()` both open the LanceDB connection and can be
64
+ // invoked concurrently (boot incremental reindex via upsert() races the
65
+ // fire-and-forget asset sweep via getAllIndexStates()). Without
66
+ // single-flighting, both would pass their boolean guard before either await
67
+ // resolved, double-connect, and double-`createTable` → "table already exists"
68
+ // / CommitConflict. Each promise is created once and awaited by all callers.
69
+ dbPromise;
70
+ initPromise;
71
+ stateInitPromise;
72
+ // ── Write serialization ──
73
+ // LanceDB uses optimistic concurrency: two `mergeInsert(...).execute()` (or
74
+ // delete) calls racing on the SAME table throw a CommitConflict and one loses.
75
+ // This singleton VectorService is shared by foreground entity writes
76
+ // (graph.ts fire-and-forget upsert/delete) AND the live asset-index drain
77
+ // (re-upsert after writing a caption sidecar). Without serialization those two
78
+ // sources can collide on the `entities` table — and the drain would record the
79
+ // loser as a terminal `failed` index state. `withWrite()` chains every mutating
80
+ // op onto a single per-instance promise so they run one at a time, in order.
81
+ writeChain = Promise.resolve();
82
+ /**
83
+ * Fired exactly once per asset, when `ensureInitialAssetIndexState` seeds a
84
+ * fresh `pending` row — i.e. an indexable IMAGE assets.db row that needs
85
+ * captioning. The asset-creation paths (graph.uploadAsset for import +
86
+ * manager/editor uploads, asset-finalize-service for presign) call
87
+ * ensureInitialAssetIndexState after writing the assets.db row, so the live
88
+ * caption drain registers here instead of being wired at each call site. It
89
+ * fires only for images and only on the first seed (a re-seed early-returns),
90
+ * so it can't loop the drain.
91
+ */
92
+ onAssetPendingCb;
93
+ /**
94
+ * Workspace-global asset ownership index (assets.db). Injected by the
95
+ * WorkspaceManager so `upsert` can resolve the captions of images an entry
96
+ * embeds (`resolveEmbeddedCaptions`) and fold them into the entry's search
97
+ * text. Optional — tests / early-boot paths run without it (no caption fold).
98
+ */
99
+ assetIndex;
100
+ // ── Operator-visible health (surfaced via /api/health/dirty) ──
101
+ // Tracked here, not at the call sites, because every fire-and-forget
102
+ // upsert/delete in graph.ts catches its own promise to avoid blocking
103
+ // writes — the operator needs a single rolled-up signal instead of
104
+ // grepping logs for `[vector] index failed`.
105
+ failureCount = 0;
106
+ inFlight = 0;
107
+ lastFailureAt = null;
108
+ lastFailure = null;
32
109
  constructor(dbPath, voyageApiKey) {
33
110
  this.dbPath = dbPath;
34
- this.voyageApiKey = voyageApiKey;
111
+ this.fallbackVoyageApiKey = voyageApiKey;
35
112
  this.lastIndexedPath = join(dbPath, 'last-indexed.json');
36
113
  }
114
+ /**
115
+ * Resolve the Voyage API key fresh on each call: store > constructor
116
+ * fallback. Lets the operator flip the key via UI / CLI without a
117
+ * server restart.
118
+ */
119
+ get voyageApiKey() {
120
+ const fromStore = tryResolve('voyage.api_key');
121
+ return fromStore ?? this.fallbackVoyageApiKey;
122
+ }
123
+ /** Begin tracking an in-flight op. Pair with `recordSuccess`/`recordFailure`. */
124
+ beginOp() { this.inFlight++; }
125
+ recordSuccess() {
126
+ if (this.inFlight > 0)
127
+ this.inFlight--;
128
+ }
129
+ recordFailure(op, entity, err) {
130
+ if (this.inFlight > 0)
131
+ this.inFlight--;
132
+ this.failureCount++;
133
+ this.lastFailureAt = new Date().toISOString();
134
+ this.lastFailure = {
135
+ op,
136
+ entity,
137
+ error: err instanceof Error ? err.message : String(err),
138
+ };
139
+ }
140
+ /**
141
+ * Snapshot for /api/health. Healthy = the last op succeeded (or none have
142
+ * run yet) AND there is no abnormal in-flight backlog. The failure count
143
+ * is informational; a single transient Voyage 503 shouldn't permanently
144
+ * mark the service unhealthy, but operators can see the trend.
145
+ */
146
+ getHealth() {
147
+ return {
148
+ healthy: this.lastFailure === null,
149
+ failureCount: this.failureCount,
150
+ inFlight: this.inFlight,
151
+ lastFailureAt: this.lastFailureAt,
152
+ lastFailure: this.lastFailure,
153
+ embeddingsEnabled: !!this.voyageApiKey,
154
+ };
155
+ }
156
+ /** Inject the workspace-global asset ownership index (assets.db). Lets
157
+ * `upsert` fold embedded-image captions into an entry's search text. */
158
+ setAssetIndex(index) {
159
+ this.assetIndex = index;
160
+ }
161
+ /**
162
+ * The captions of every immutable-keyed image an entry embeds, joined for
163
+ * folding into the entry's FTS/embedding text (asset-as-embed, decision D2).
164
+ *
165
+ * The caption + OCR text is derived once per image and stored in
166
+ * `assets.db.caption`, keyed by the immutable assetId (NOT in a sidecar or
167
+ * the body). An entry becomes findable by an embedded image's visual content
168
+ * by reading those captions back here — for the `material` body embed, the
169
+ * `reference` thumbnail, a note body image, etc. Each captioned image's text
170
+ * is read from the single assets.db row, so the same image embedded by N
171
+ * entries enriches all N without duplicating the stored caption.
172
+ *
173
+ * Forward-only (entry → the assets IT embeds) — no reverse index, no
174
+ * cross-repo ownership claim. Best-effort: returns undefined without an index
175
+ * or when nothing embedded is captioned.
176
+ */
177
+ resolveEmbeddedCaptions(entity) {
178
+ const index = this.assetIndex;
179
+ if (!index)
180
+ return undefined;
181
+ // `embeddedAssetIds` (core/embeds.ts) is the SHARED definition of "which
182
+ // assets does this entry embed" — body + string frontmatter, immutable-key
183
+ // urls only — also used by the sweep's embedder re-index, so the two never
184
+ // disagree on coverage. It applies a cheap substring pre-check, so a no-asset
185
+ // entry costs no regex.
186
+ const ids = embeddedAssetIds(entity.document?.content ?? '', entity.data);
187
+ if (ids.size === 0)
188
+ return undefined;
189
+ const captions = [];
190
+ for (const id of ids) {
191
+ try {
192
+ const caption = index.get(id)?.caption?.trim();
193
+ if (caption)
194
+ captions.push(caption);
195
+ }
196
+ catch { /* best-effort: a lookup failure must not fail the index */ }
197
+ }
198
+ return captions.length ? captions.join('\n') : undefined;
199
+ }
37
200
  /**
38
201
  * Open/create the LanceDB table and ensure the FTS index exists.
39
202
  * Call once before using the service.
@@ -41,11 +204,44 @@ export class VectorService {
41
204
  async init() {
42
205
  if (this.initialized)
43
206
  return;
44
- mkdirSync(this.dbPath, { recursive: true });
45
- this.db = await lancedb.connect(this.dbPath);
46
- const tableNames = await this.db.tableNames();
207
+ // Single-flight: concurrent callers share one in-flight init.
208
+ if (!this.initPromise)
209
+ this.initPromise = this.doInit();
210
+ await this.initPromise;
211
+ }
212
+ /**
213
+ * Run a mutating LanceDB op under the per-instance write lock so concurrent
214
+ * writers (foreground entity writes vs. the asset-index drain) can't collide
215
+ * on a shared table's optimistic-concurrency commit. Ops run strictly in the
216
+ * order `withWrite` is called; a throwing op rejects to ITS caller without
217
+ * poisoning the chain for the next writer.
218
+ */
219
+ withWrite(fn) {
220
+ const run = this.writeChain.then(fn, fn);
221
+ // Keep the chain alive regardless of this op's outcome (swallow on the
222
+ // chain copy only; the real result/throw still goes to the caller).
223
+ this.writeChain = run.then(() => undefined, () => undefined);
224
+ return run;
225
+ }
226
+ /**
227
+ * Open (once) the shared LanceDB connection. Both `init()` and
228
+ * `initStateTable()` go through this so they never race to assign `this.db`.
229
+ */
230
+ async ensureDb() {
231
+ if (this.db)
232
+ return this.db;
233
+ if (!this.dbPromise) {
234
+ mkdirSync(this.dbPath, { recursive: true });
235
+ this.dbPromise = lancedb.connect(this.dbPath);
236
+ }
237
+ this.db = await this.dbPromise;
238
+ return this.db;
239
+ }
240
+ async doInit() {
241
+ const db = await this.ensureDb();
242
+ const tableNames = await db.tableNames();
47
243
  if (tableNames.includes(TABLE_NAME)) {
48
- this.table = await this.db.openTable(TABLE_NAME);
244
+ this.table = await db.openTable(TABLE_NAME);
49
245
  }
50
246
  else {
51
247
  // Create table with a seed record (LanceDB infers schema from first batch)
@@ -58,7 +254,7 @@ export class VectorService {
58
254
  vector: new Array(VECTOR_DIM).fill(0),
59
255
  updated_at: new Date().toISOString(),
60
256
  };
61
- this.table = await this.db.createTable(TABLE_NAME, [seed]);
257
+ this.table = await db.createTable(TABLE_NAME, [seed]);
62
258
  // Create FTS index on text column
63
259
  await this.table.createIndex('text', {
64
260
  config: lancedb.Index.fts(),
@@ -68,6 +264,156 @@ export class VectorService {
68
264
  }
69
265
  this.initialized = true;
70
266
  }
267
+ // ─── Asset index state (mutable, LanceDB-only; keyed by assetId) ─────────────
268
+ /**
269
+ * Open/create the side table for asset index state. Independent of `init()`
270
+ * so state-only callers (and tests) don't pay for the entities table. Lazy
271
+ * because most workspaces never need it until the first asset is indexed.
272
+ */
273
+ async initStateTable() {
274
+ if (this.stateInitialized)
275
+ return;
276
+ // Single-flight: concurrent state readers/writers share one in-flight init,
277
+ // so two callers can't both take the createTable branch (which would throw
278
+ // "table already exists" on the loser).
279
+ if (!this.stateInitPromise)
280
+ this.stateInitPromise = this.doInitStateTable();
281
+ await this.stateInitPromise;
282
+ }
283
+ async doInitStateTable() {
284
+ const db = await this.ensureDb();
285
+ const names = await db.tableNames();
286
+ if (names.includes(INDEX_STATE_TABLE)) {
287
+ this.stateTable = await db.openTable(INDEX_STATE_TABLE);
288
+ }
289
+ else {
290
+ const seed = {
291
+ id: '__seed__', repo: '', entity_id: '', index_status: 'pending',
292
+ indexed_at: '', index_version: 0, reason: '',
293
+ };
294
+ this.stateTable = await db.createTable(INDEX_STATE_TABLE, [seed]);
295
+ await this.stateTable.delete(`id = '__seed__'`);
296
+ }
297
+ this.stateInitialized = true;
298
+ }
299
+ toState(r) {
300
+ return {
301
+ assetId: r.entity_id, // legacy column name; holds the immutable UUID
302
+ repo: r.repo,
303
+ status: r.index_status,
304
+ indexedAt: r.indexed_at,
305
+ version: r.index_version,
306
+ reason: r.reason,
307
+ };
308
+ }
309
+ /**
310
+ * Read the `text` actually indexed for one entity (the value `buildEntityText`
311
+ * produced — markdown body plus, for assets, the extracted sidecar). Null when
312
+ * no row exists. This is the searchable content of record, independent of FTS
313
+ * index freshness, so it's the deterministic way to assert "the asset's body
314
+ * reached the index" (e.g. the docx stub-upsert-race regression test).
315
+ */
316
+ async getIndexedText(repo, entityType, entityId) {
317
+ await this.init();
318
+ const id = `${repo}/${entityType}/${entityId}`.replace(/'/g, "''");
319
+ const rows = await this.table.query().where(`id = '${id}'`).limit(1).toArray();
320
+ const row = rows.find((r) => r.id !== '__seed__');
321
+ return row ? row.text : null;
322
+ }
323
+ /** Read one asset's index state, or null when no row exists (never-derived). */
324
+ async getIndexState(assetId) {
325
+ await this.initStateTable();
326
+ const id = assetId.replace(/'/g, "''");
327
+ const rows = await this.stateTable.query().where(`id = '${id}'`).limit(1).toArray();
328
+ const row = rows.find((r) => r.id !== '__seed__');
329
+ return row ? this.toState(row) : null;
330
+ }
331
+ /**
332
+ * Load every index-state row into a Map keyed by assetId. The boot sweep uses
333
+ * this to decide, per image asset, whether a row is missing (never-derived),
334
+ * stale (old version), or unfinished (pending) — without re-deriving the
335
+ * whole set (PERF1).
336
+ */
337
+ async getAllIndexStates() {
338
+ await this.initStateTable();
339
+ const rows = await this.stateTable.query().toArray();
340
+ const map = new Map();
341
+ for (const r of rows) {
342
+ if (r.id === '__seed__')
343
+ continue;
344
+ // Key by the authoritative PK `id` (== assetId for current rows), matching
345
+ // getIndexState/setIndexState. Legacy entity-keyed rows from the old
346
+ // pipeline have `id = '<repo>/<entityId>'`, which can never equal a UUID
347
+ // assetId, so they stay inert here (the sweep looks up by assetId) rather
348
+ // than being mistaken for a current row via their bare `entity_id`.
349
+ map.set(r.id, this.toState(r));
350
+ }
351
+ return map;
352
+ }
353
+ /** Upsert an asset's index state. Stamps `indexed_at` + current version unless overridden. */
354
+ async setIndexState(assetId, status, opts = {}) {
355
+ await this.initStateTable();
356
+ const record = {
357
+ id: assetId,
358
+ repo: opts.repo ?? '',
359
+ entity_id: assetId,
360
+ index_status: status,
361
+ indexed_at: opts.indexedAt ?? new Date().toISOString(),
362
+ index_version: opts.version ?? ASSET_INDEX_VERSION,
363
+ reason: opts.reason ?? '',
364
+ };
365
+ await this.withWrite(() => this.stateTable
366
+ .mergeInsert('id')
367
+ .whenMatchedUpdateAll()
368
+ .whenNotMatchedInsertAll()
369
+ .execute([record]));
370
+ }
371
+ /** Drop an asset's index-state row (e.g. when the asset is deleted). */
372
+ async deleteIndexState(assetId) {
373
+ await this.initStateTable();
374
+ const id = assetId.replace(/'/g, "''");
375
+ await this.withWrite(() => this.stateTable.delete(`id = '${id}'`));
376
+ }
377
+ /**
378
+ * Register the single sink for "a new indexable image needs captioning."
379
+ * The live caption drain (AssetIndexQueue) registers here; the chokepoint
380
+ * fires from `ensureInitialAssetIndexState`, covering every image-upload path
381
+ * at once. Replaces per-call-site enqueue wiring.
382
+ */
383
+ setOnAssetPending(cb) {
384
+ this.onAssetPendingCb = cb;
385
+ }
386
+ /**
387
+ * Seed the initial index state for a freshly-stored IMAGE asset, IF it has no
388
+ * row yet, and notify the live caption drain. Called by the asset-creation
389
+ * paths (graph.uploadAsset, asset-finalize-service) after the assets.db row
390
+ * is written — keyed by the immutable assetId, never an entity.
391
+ *
392
+ * State *transitions* (full/failed) are owned by the caption sweep; this only
393
+ * establishes the `pending` starting point + fires the drain. Only raster
394
+ * images are captioned: SVG stays transitional (sanitize-html not wired);
395
+ * documents/opaque binaries carry no caption. A re-seed (row already exists)
396
+ * early-returns so the drain can't loop. Best-effort: a state-write failure
397
+ * must not fail the upload.
398
+ */
399
+ async ensureInitialAssetIndexState(assetId, opts) {
400
+ if (!isCaptionableImage(opts.mediaType, opts.filename))
401
+ return;
402
+ try {
403
+ const existing = await this.getIndexState(assetId);
404
+ if (existing)
405
+ return;
406
+ await this.setIndexState(assetId, 'pending', { repo: opts.repo });
407
+ try {
408
+ this.onAssetPendingCb?.(assetId);
409
+ }
410
+ catch { /* non-fatal */ }
411
+ }
412
+ catch (err) {
413
+ // eslint-disable-next-line no-console
414
+ console.warn(`[vector] asset index-state seed failed for ${assetId}: ${err instanceof Error ? err.message : err}`);
415
+ }
416
+ }
71
417
  /**
72
418
  * Index or re-index a single entity.
73
419
  * Safe to call on create, update, or as part of bulk indexing.
@@ -75,7 +421,7 @@ export class VectorService {
75
421
  async upsert(repoName, entity) {
76
422
  await this.init();
77
423
  const id = `${repoName}/${entity.entityType}/${entity.id}`;
78
- const text = buildEntityText(entity);
424
+ const text = buildEntityText(entity, this.resolveEmbeddedCaptions(entity));
79
425
  const vector = this.voyageApiKey
80
426
  ? await this.generateEmbedding(text)
81
427
  : null;
@@ -89,24 +435,29 @@ export class VectorService {
89
435
  vector: vector ?? new Array(VECTOR_DIM).fill(0),
90
436
  updated_at: new Date().toISOString(),
91
437
  };
92
- await this.table
438
+ await this.withWrite(() => this.table
93
439
  .mergeInsert('id')
94
440
  .whenMatchedUpdateAll()
95
441
  .whenNotMatchedInsertAll()
96
- .execute([record]);
442
+ .execute([record]));
97
443
  }
98
444
  /**
99
445
  * Bulk upsert — used by `studiograph index`. Batches Voyage API calls.
100
446
  */
101
- async upsertMany(repoName, entities) {
447
+ async upsertMany(repoName, entities, opts = {}) {
102
448
  await this.init();
103
449
  if (entities.length === 0)
104
450
  return;
105
- const texts = entities.map(e => buildEntityText(e));
451
+ const texts = entities.map(e => buildEntityText(e, this.resolveEmbeddedCaptions(e)));
106
452
  // Batch embeddings (Voyage supports up to 128 per request)
107
453
  let vectors = new Array(entities.length).fill(null);
108
454
  if (this.voyageApiKey) {
109
- vectors = await this.generateEmbeddingsBatch(texts);
455
+ vectors = await this.generateEmbeddingsBatch(texts, opts.onProgress);
456
+ }
457
+ else {
458
+ // No embedding step — report the whole batch as "done" once so
459
+ // progress UIs that wait on at least one callback don't sit at 0%.
460
+ opts.onProgress?.(entities.length, entities.length);
110
461
  }
111
462
  const records = entities.map((entity, i) => ({
112
463
  id: `${repoName}/${entity.entityType}/${entity.id}`,
@@ -117,11 +468,11 @@ export class VectorService {
117
468
  vector: vectors[i] ?? new Array(VECTOR_DIM).fill(0),
118
469
  updated_at: new Date().toISOString(),
119
470
  }));
120
- await this.table
471
+ await this.withWrite(() => this.table
121
472
  .mergeInsert('id')
122
473
  .whenMatchedUpdateAll()
123
474
  .whenNotMatchedInsertAll()
124
- .execute(records);
475
+ .execute(records));
125
476
  }
126
477
  /**
127
478
  * Remove an entity from the index.
@@ -129,7 +480,48 @@ export class VectorService {
129
480
  async delete(repoName, entityType, entityId) {
130
481
  await this.init();
131
482
  const id = `${repoName}/${entityType}/${entityId}`;
132
- await this.table.delete(`id = '${id.replace(/'/g, "''")}'`);
483
+ await this.withWrite(() => this.table.delete(`id = '${id.replace(/'/g, "''")}'`));
484
+ // No asset index-state reap here: under asset-as-embed the caption state is
485
+ // keyed by the immutable assetId and survives deletion of any entry that
486
+ // merely embeds the asset. The state row is reaped only when the asset
487
+ // itself is deleted (graph.deleteAssetById → vectorService.deleteIndexState).
488
+ }
489
+ /**
490
+ * Remove an entity by `(repo, id)` alone, without needing its type.
491
+ *
492
+ * Used by the serve-boot incremental indexer: when git diff reports a
493
+ * deletion, the file is gone from disk so its type can't be resolved
494
+ * from frontmatter. The vector store has a discrete `entity_id` column
495
+ * so we can match on `repo + entity_id` without falling back to a LIKE
496
+ * pattern on the synthetic id.
497
+ *
498
+ * Safe across type renames: a single id that legitimately had two type
499
+ * rows (e.g. type changed mid-edit and both old + new still exist) gets
500
+ * both wiped — which is the right behavior for incremental rebuild
501
+ * since the next upsert recreates the current type's row.
502
+ */
503
+ async deleteByRepoAndId(repoName, entityId) {
504
+ await this.init();
505
+ const r = repoName.replace(/'/g, "''");
506
+ const e = entityId.replace(/'/g, "''");
507
+ await this.withWrite(() => this.table.delete(`repo = '${r}' AND entity_id = '${e}'`));
508
+ // No asset index-state reap here either — see delete(): asset state is
509
+ // assetId-keyed and decoupled from the entry's lifecycle.
510
+ }
511
+ /**
512
+ * Best-effort `deleteIndexState` for the asset-delete path: the blob/index
513
+ * delete is the authoritative op, so a failure to reap the state row must not
514
+ * turn a successful asset delete into a thrown error. Called by
515
+ * graph.deleteAssetById.
516
+ */
517
+ async deleteIndexStateSafe(assetId) {
518
+ try {
519
+ await this.deleteIndexState(assetId);
520
+ }
521
+ catch (err) {
522
+ // eslint-disable-next-line no-console
523
+ console.warn(`[vector] index-state cleanup failed for ${assetId}: ${err instanceof Error ? err.message : err}`);
524
+ }
133
525
  }
134
526
  /**
135
527
  * Search the index.
@@ -140,22 +532,35 @@ export class VectorService {
140
532
  const limit = options.limit ?? 10;
141
533
  try {
142
534
  let rows;
535
+ // Repo scoping is a PRE-filter pushed into the query, not a post-filter on
536
+ // the result page. Filtering after `.limit()` silently drops a scoped
537
+ // repo's matches whenever the global top-K is dominated by other repos —
538
+ // e.g. a `repos:['studiograph']` search returning nothing while the same
539
+ // query unscoped ranks a studiograph doc #1. `where` applies BEFORE the
540
+ // limit so the K results are already within scope.
541
+ const repoWhere = options.repos && options.repos.length > 0
542
+ ? options.repos.map(r => `repo = '${r.replace(/'/g, "''")}'`).join(' OR ')
543
+ : null;
143
544
  if (this.voyageApiKey) {
144
545
  // Tier 2: hybrid search
145
546
  const queryVector = await this.generateEmbedding(query);
146
- rows = await this.table
147
- .search(queryVector)
547
+ let q = this.table.search(queryVector);
548
+ if (repoWhere)
549
+ q = q.where(repoWhere);
550
+ rows = await q
148
551
  .limit(limit * 2) // fetch extra for re-ranking
149
552
  .toArray();
150
553
  }
151
554
  else {
152
555
  // Tier 1: FTS only
153
- rows = await this.table
154
- .search(query, 'text')
556
+ let q = this.table.search(query, 'text');
557
+ if (repoWhere)
558
+ q = q.where(repoWhere);
559
+ rows = await q
155
560
  .limit(limit)
156
561
  .toArray();
157
562
  }
158
- let results = rows
563
+ const results = rows
159
564
  .filter((r) => r.id !== '__seed__' && r.entity_id !== '')
160
565
  .map((r, i) => ({
161
566
  repoName: r.repo,
@@ -163,9 +568,6 @@ export class VectorService {
163
568
  entityId: r.entity_id,
164
569
  score: r._distance != null ? 1 / (1 + r._distance) : 1 - i * 0.01,
165
570
  }));
166
- if (options.repos && options.repos.length > 0) {
167
- results = results.filter(r => options.repos.includes(r.repoName));
168
- }
169
571
  return results.slice(0, limit);
170
572
  }
171
573
  catch {
@@ -188,9 +590,13 @@ export class VectorService {
188
590
  }
189
591
  }
190
592
  /**
191
- * Record the current time as the last index time for a repo.
593
+ * Record the last index time for a repo.
594
+ *
595
+ * Production callers omit `isoTimestamp` and the current time is used.
596
+ * Tests pass an explicit ISO timestamp so they can rewind the clock and
597
+ * assert the git-log `--since` window picks up the right commits.
192
598
  */
193
- setLastIndexedTime(repoName) {
599
+ setLastIndexedTime(repoName, isoTimestamp) {
194
600
  mkdirSync(this.dbPath, { recursive: true });
195
601
  let data = {};
196
602
  if (existsSync(this.lastIndexedPath)) {
@@ -199,7 +605,7 @@ export class VectorService {
199
605
  }
200
606
  catch { /* ignore */ }
201
607
  }
202
- data[repoName] = new Date().toISOString();
608
+ data[repoName] = isoTimestamp ?? new Date().toISOString();
203
609
  writeFileSync(this.lastIndexedPath, JSON.stringify(data, null, 2) + '\n');
204
610
  }
205
611
  /** Whether Voyage AI embeddings are enabled (Tier 2). */
@@ -211,10 +617,11 @@ export class VectorService {
211
617
  const results = await this.generateEmbeddingsBatch([text]);
212
618
  return results[0] ?? new Array(VECTOR_DIM).fill(0);
213
619
  }
214
- async generateEmbeddingsBatch(texts) {
620
+ async generateEmbeddingsBatch(texts, onProgress) {
215
621
  // Voyage supports up to 128 inputs per request
216
622
  const BATCH_SIZE = 128;
217
623
  const all = [];
624
+ const total = texts.length;
218
625
  for (let i = 0; i < texts.length; i += BATCH_SIZE) {
219
626
  const batch = texts.slice(i, i + BATCH_SIZE);
220
627
  const response = await fetch(VOYAGE_API_URL, {
@@ -231,6 +638,7 @@ export class VectorService {
231
638
  }
232
639
  const json = await response.json();
233
640
  all.push(...json.data.map(d => d.embedding));
641
+ onProgress?.(all.length, total);
234
642
  }
235
643
  return all;
236
644
  }
@@ -246,10 +654,15 @@ export class VectorService {
246
654
  export async function reindexWorkspace(workspacePath, repos, onProgress) {
247
655
  const { loadUserConfig } = await import('../core/user-config.js');
248
656
  const { BaseGraphManager } = await import('../core/graph.js');
657
+ const { AssetIndexService } = await import('./assets/asset-index-service.js');
249
658
  const { homedir } = await import('os');
250
659
  const userConfig = loadUserConfig();
251
660
  const dbPath = userConfig.vector_db_path || join(homedir(), '.studiograph', 'vector');
252
661
  const vectorService = new VectorService(dbPath, userConfig.voyage_api_key);
662
+ // Wire the assets.db handle so a cold reindex still folds embedded-image
663
+ // captions into entry search text (otherwise it would overwrite the server's
664
+ // caption-folded rows with caption-less ones).
665
+ vectorService.setAssetIndex(new AssetIndexService(workspacePath));
253
666
  await vectorService.init();
254
667
  const log = onProgress ?? (() => { });
255
668
  let total = 0;
@@ -277,13 +690,151 @@ export async function reindexWorkspace(workspacePath, repos, onProgress) {
277
690
  }
278
691
  return total;
279
692
  }
693
+ export async function incrementalReindexWorkspace(workspaceManager, repos, workspacePath, opts = {}) {
694
+ const vectorService = workspaceManager.vectorService;
695
+ if (!vectorService) {
696
+ return { total: 0, fresh: false };
697
+ }
698
+ const log = opts.log ?? (() => { });
699
+ const { execFileSync } = await import('child_process');
700
+ let total = 0;
701
+ let anyFreshRepo = false;
702
+ const staleEntities = [];
703
+ // Pre-pass: figure out the total first-time entity count so the
704
+ // progress callback has a stable denominator. Cheap — `graph.list()`
705
+ // doesn't re-read files, it returns the in-memory graph state the
706
+ // workspace manager already maintains.
707
+ let firstTimeTotal = 0;
708
+ if (opts.onFirstTimeProgress) {
709
+ for (const repo of repos) {
710
+ if (vectorService.getLastIndexedTime(repo.name))
711
+ continue;
712
+ try {
713
+ firstTimeTotal += workspaceManager.getGraph(repo.name).list().length;
714
+ }
715
+ catch {
716
+ // tolerate per-repo failure; the real loop below will log it
717
+ }
718
+ }
719
+ }
720
+ let firstTimeDone = 0;
721
+ for (const repo of repos) {
722
+ const lastIndexed = vectorService.getLastIndexedTime(repo.name);
723
+ // Per-repo first-time index. Catches three cases:
724
+ // 1. Very first `serve` boot (every repo missing a timestamp).
725
+ // 2. New folder added between serve boots (existing workspace +
726
+ // new repo with no timestamp). Pre-fix this was skipped here
727
+ // and never indexed unless the operator ran a full reindex.
728
+ // 3. Vector DB rebuilt from scratch but workspace has existing
729
+ // folders.
730
+ if (!lastIndexed) {
731
+ try {
732
+ const graph = workspaceManager.getGraph(repo.name);
733
+ const entities = graph.list();
734
+ if (entities.length > 0) {
735
+ await vectorService.upsertMany(repo.name, entities, {
736
+ onProgress: (batchDone) => {
737
+ opts.onFirstTimeProgress?.(firstTimeDone + batchDone, firstTimeTotal);
738
+ },
739
+ });
740
+ firstTimeDone += entities.length;
741
+ total += entities.length;
742
+ }
743
+ vectorService.setLastIndexedTime(repo.name);
744
+ anyFreshRepo = true;
745
+ }
746
+ catch (err) {
747
+ log(`failed to index ${repo.name}: ${err instanceof Error ? err.message : 'unknown'}`);
748
+ }
749
+ continue;
750
+ }
751
+ // Established repo — diff git log since the last index timestamp and
752
+ // collect a list of stale (repo, id) tuples to upsert / delete below.
753
+ const repoPath = join(workspacePath, repo.path);
754
+ if (!existsSync(repoPath))
755
+ continue;
756
+ try {
757
+ const output = execFileSync('git', ['log', `--since=${lastIndexed}`, '--name-status', '--format=', '--', '*.md'], { cwd: repoPath, encoding: 'utf-8', stdio: 'pipe' }).trim();
758
+ if (!output)
759
+ continue;
760
+ for (const line of output.split('\n')) {
761
+ // Accept any markdown path. Layouts in the wild:
762
+ // - flat: `entity-id.md`
763
+ // - typed: `<type>/entity-id.md`
764
+ // - nested: `folder/sub/entity-id.md`
765
+ // STU-131 normalized on flat for new entities; older typed layouts
766
+ // and arbitrary nested folders still appear in mixed repos. Entity
767
+ // type lives in frontmatter (resolved via graph.getById for
768
+ // upserts; not needed for deletes since we now match by `(repo,
769
+ // entity_id)` columns). Pre-fix this regex required exactly one
770
+ // slash with a `\w+` type segment and missed all three layouts,
771
+ // plus hyphenated types like `case-study`.
772
+ const m = line.match(/^([AMD])\s+(.+\.md)$/);
773
+ if (!m)
774
+ continue;
775
+ const [, status, path] = m;
776
+ // basename minus `.md`. Entity IDs are unique within a repo.
777
+ const id = path.split('/').pop().replace(/\.md$/, '');
778
+ if (!id)
779
+ continue;
780
+ staleEntities.push({ repoName: repo.name, entityId: id, deleted: status === 'D' });
781
+ }
782
+ }
783
+ catch (err) {
784
+ log(`failed to diff ${repo.name}: ${err instanceof Error ? err.message : 'unknown'}`);
785
+ }
786
+ }
787
+ if (staleEntities.length === 0) {
788
+ // Nothing changed via git diff. If we did first-time work above, that
789
+ // counts as a fresh run; otherwise this was a no-op incremental boot.
790
+ return { total, fresh: anyFreshRepo };
791
+ }
792
+ // Dedupe: if an entity appears multiple times (e.g. M then D), the last
793
+ // entry wins. Order matters — git log is newest-first by default, so we
794
+ // reverse before reducing to get the newest state per (repo, id).
795
+ const seen = new Map();
796
+ for (const item of staleEntities.slice().reverse()) {
797
+ seen.set(`${item.repoName}/${item.entityId}`, item);
798
+ }
799
+ for (const item of seen.values()) {
800
+ try {
801
+ if (item.deleted) {
802
+ // Delete by (repo, id) — type isn't recoverable from a deleted file.
803
+ // The new column-based matcher in vectorService handles it without
804
+ // a frontmatter lookup.
805
+ await vectorService.deleteByRepoAndId(item.repoName, item.entityId);
806
+ }
807
+ else {
808
+ const graph = workspaceManager.getGraph(item.repoName);
809
+ const entity = graph.getById(item.entityId);
810
+ await vectorService.upsert(item.repoName, entity);
811
+ total++;
812
+ }
813
+ }
814
+ catch {
815
+ // Entity may have been deleted then re-created; safe to skip.
816
+ }
817
+ }
818
+ // Stamp every repo we touched. Empty-diff repos already had a timestamp
819
+ // (we skipped the rebuild path) — re-stamping is cheap and keeps the
820
+ // "since" window tight for the next boot.
821
+ for (const repo of repos) {
822
+ vectorService.setLastIndexedTime(repo.name);
823
+ }
824
+ return { total, fresh: anyFreshRepo };
825
+ }
280
826
  // ─── Helpers ─────────────────────────────────────────────────────────────────
281
827
  /**
282
828
  * Build a text representation of an entity for FTS/embedding.
283
829
  * Combines entity type, key frontmatter fields, and markdown body.
830
+ *
831
+ * `extraText` is appended after the body — used by VectorService to
832
+ * fold PDF sidecar text into asset-entity embeddings. Kept as a plain
833
+ * string parameter (not file IO) so this stays pure and unit-testable.
834
+ *
284
835
  * Exported for testing.
285
836
  */
286
- export function buildEntityText(entity) {
837
+ export function buildEntityText(entity, extraText) {
287
838
  const parts = [];
288
839
  // Entity type and ID as context
289
840
  parts.push(`${entity.entityType}: ${entity.data.name || entity.id}`);
@@ -317,6 +868,11 @@ export function buildEntityText(entity) {
317
868
  if (plainText)
318
869
  parts.push(plainText);
319
870
  }
871
+ if (extraText) {
872
+ const trimmed = extraText.trim();
873
+ if (trimmed)
874
+ parts.push(trimmed);
875
+ }
320
876
  return parts.join('\n');
321
877
  }
322
878
  //# sourceMappingURL=vector-service.js.map