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
@@ -6,7 +6,346 @@
6
6
  *
7
7
  * Single agent instance per server process (single-user v1).
8
8
  */
9
- export async function registerChatRoutes(fastify, agent, memoryService) {
9
+ import { validateArtifactBundle } from '../../core/artifact-bundle.js';
10
+ import { parseFollowups } from '../../agent/followups.js';
11
+ import * as access from '../../services/access-control.js';
12
+ import { reqGitUser } from './graph-api-access.js';
13
+ import { hashArtifactBody } from '../../agent/tools/artifact-tools.js';
14
+ import { log } from '../../utils/log.js';
15
+ import { addInferenceUsage, createCloudInferenceBillingClient, createInferenceUsageSummary, isStudiographCreditsMode, } from '../../services/cloud-inference-billing.js';
16
+ import { reserveCloudInference, settleCloudInference, releaseCloudInference, } from '../cloud-billing-flow.js';
17
+ import { prepareCreatePayload } from '../../services/entity-mutations.js';
18
+ import { resolveImageRefs, resolveDocContext, isValidAttachmentTurn, composeAttachmentMessageText, attachmentPlaceholder, normalizeAttachmentRef, } from '../../services/scratch-attachment-service.js';
19
+ /**
20
+ * A per-turn "today is …" context line so the agent always knows the current
21
+ * date and stops misfiling entries to the wrong day. Prefers the client's local
22
+ * date (correct timezone) and falls back to the server's UTC date for callers
23
+ * that don't send one. The label is sanitized (single line, length-capped)
24
+ * since it's free text from the request.
25
+ */
26
+ export function buildDatePrefix(clientDate, clientDateLabel) {
27
+ const iso = clientDate && /^\d{4}-\d{2}-\d{2}$/.test(clientDate)
28
+ ? clientDate
29
+ : new Date().toISOString().slice(0, 10);
30
+ const label = clientDateLabel
31
+ ? clientDateLabel.replace(/[\r\n]+/g, ' ').trim().slice(0, 64) || iso
32
+ : iso;
33
+ return (`[Today is ${label} (${iso}).]\n\n` +
34
+ `Interpret relative dates ("today", "tomorrow", "yesterday", weekday names) ` +
35
+ `against this. When setting a date field, default to ${iso} (YYYY-MM-DD) ` +
36
+ `unless the user gives another date.\n\n`);
37
+ }
38
+ /** Cap on how many unresolved comments we fold into an entry's chat context.
39
+ * Keeps the prefix bounded on heavily-commented entries; the agent can still
40
+ * call list_entities/get_related for the full set. */
41
+ const MAX_CONTEXT_COMMENTS = 25;
42
+ function slugifyArtifactId(value) {
43
+ const slug = value
44
+ .toLowerCase()
45
+ .replace(/[^a-z0-9]+/g, '-')
46
+ .replace(/^-+|-+$/g, '')
47
+ .slice(0, 80);
48
+ return slug || 'artifact';
49
+ }
50
+ function parseEntityContext(context) {
51
+ if (!context || context.startsWith('folder:'))
52
+ return null;
53
+ const [repo, entityType, entityId] = context.split('/');
54
+ if (!repo || !entityType || !entityId)
55
+ return null;
56
+ return { repo, entityType, entityId };
57
+ }
58
+ function parseArtifactSelectionContext(parts) {
59
+ const marker = parts.slice(3).find((part) => part.startsWith('artifact-selection:'));
60
+ if (!marker)
61
+ return null;
62
+ const raw = marker.slice('artifact-selection:'.length);
63
+ try {
64
+ return decodeURIComponent(raw).slice(0, 1600);
65
+ }
66
+ catch {
67
+ return raw.slice(0, 1600);
68
+ }
69
+ }
70
+ function repoFromContext(context, user, agent, authService) {
71
+ const workspaceManager = agent.getWorkspaceManager();
72
+ if (context?.startsWith('folder:')) {
73
+ const repo = context.slice('folder:'.length);
74
+ return access.canWriteRepo(user, repo, workspaceManager, authService) ? repo : null;
75
+ }
76
+ const entityContext = parseEntityContext(context);
77
+ if (entityContext && access.canWriteRepo(user, entityContext.repo, workspaceManager, authService)) {
78
+ return entityContext.repo;
79
+ }
80
+ if (user) {
81
+ const personal = workspaceManager.getUserPersonalRepo(user.id);
82
+ if (personal && access.canWriteRepo(user, personal.name, workspaceManager, authService)) {
83
+ return personal.name;
84
+ }
85
+ }
86
+ return access.getAccessibleRepos(user, workspaceManager, authService)
87
+ .find((repo) => access.canWriteRepo(user, repo.name, workspaceManager, authService))
88
+ ?.name ?? null;
89
+ }
90
+ function resolveArtifactToolTarget(target, user, agent, authService) {
91
+ if (!target?.entityId)
92
+ return null;
93
+ const workspaceManager = agent.getWorkspaceManager();
94
+ if (target.repo) {
95
+ if (!access.canWriteRepo(user, target.repo, workspaceManager, authService)) {
96
+ throw new Error(`No write access to artifact folder: ${target.repo}`);
97
+ }
98
+ const graph = workspaceManager.getGraph(target.repo);
99
+ if (!graph)
100
+ throw new Error(`Folder not found: ${target.repo}`);
101
+ graph.get('artifact', target.entityId);
102
+ return { repo: target.repo, entityId: target.entityId };
103
+ }
104
+ const matches = [];
105
+ for (const repo of access.getAccessibleRepos(user, workspaceManager, authService)) {
106
+ if (!access.canWriteRepo(user, repo.name, workspaceManager, authService))
107
+ continue;
108
+ const graph = workspaceManager.getGraph(repo.name);
109
+ if (!graph)
110
+ continue;
111
+ try {
112
+ graph.get('artifact', target.entityId);
113
+ matches.push({ repo: repo.name, entityId: target.entityId });
114
+ }
115
+ catch {
116
+ // Not in this folder.
117
+ }
118
+ }
119
+ if (matches.length === 1)
120
+ return matches[0];
121
+ if (matches.length > 1) {
122
+ throw new Error(`Artifact target ${target.entityId} exists in multiple folders. Pass target.repo.`);
123
+ }
124
+ throw new Error(`Artifact target not found: ${target.entityId}`);
125
+ }
126
+ /** True when a bundle's entry document has no real content (the new-entry
127
+ * template ships a blank entrypoint). Mirrors the canvas's empty-artifact check. */
128
+ function bundleEntrypointBlank(bundle) {
129
+ const entry = bundle.files?.[bundle.entrypoint];
130
+ return typeof entry === 'string' && entry.trim().length === 0;
131
+ }
132
+ /** True when a stored artifact body parses to a bundle with a blank entrypoint.
133
+ * Unparseable bodies are treated as non-blank (conservative — the stale guard
134
+ * still applies rather than letting an unread overwrite through). */
135
+ function artifactBodyIsBlank(body) {
136
+ try {
137
+ const parsed = validateArtifactBundle(JSON.parse(body));
138
+ return parsed.ok && !!parsed.bundle && bundleEntrypointBlank(parsed.bundle);
139
+ }
140
+ catch {
141
+ return false;
142
+ }
143
+ }
144
+ export async function persistArtifactFromChat(params) {
145
+ const { bundle, context, target, user, agent, authService, gitUser, options } = params;
146
+ const validation = validateArtifactBundle(bundle);
147
+ if (!validation.ok || !validation.bundle) {
148
+ throw new Error(`Invalid artifact bundle: ${validation.errors.join('; ')}`);
149
+ }
150
+ const validBundle = validation.bundle;
151
+ const workspaceManager = agent.getWorkspaceManager();
152
+ const body = `${JSON.stringify(validBundle, null, 2)}\n`;
153
+ const entityContext = parseEntityContext(context);
154
+ const actor = gitUser ?? { id: 'agent', name: 'Studiograph Agent', email: 'agent@studiograph.local' };
155
+ const createData = {
156
+ name: validBundle.title,
157
+ kind: validBundle.kind,
158
+ status: 'draft',
159
+ viewport_width: validBundle.viewport.width,
160
+ viewport_height: validBundle.viewport.height,
161
+ viewport_mode: validBundle.viewport.mode,
162
+ };
163
+ const updateData = {
164
+ name: validBundle.title,
165
+ kind: validBundle.kind,
166
+ viewport_width: validBundle.viewport.width,
167
+ viewport_height: validBundle.viewport.height,
168
+ viewport_mode: validBundle.viewport.mode,
169
+ };
170
+ const explicitTarget = resolveArtifactToolTarget(target, user, agent, authService);
171
+ const updateTarget = explicitTarget
172
+ ?? (entityContext?.entityType === 'artifact'
173
+ ? { repo: entityContext.repo, entityId: entityContext.entityId }
174
+ : null);
175
+ if (updateTarget) {
176
+ if (!access.canWriteRepo(user, updateTarget.repo, workspaceManager, authService)) {
177
+ throw new Error(`No write access to artifact folder: ${updateTarget.repo}`);
178
+ }
179
+ const graph = workspaceManager.getGraph(updateTarget.repo);
180
+ if (!graph)
181
+ throw new Error(`Folder not found: ${updateTarget.repo}`);
182
+ // Stale-write + destructive-shrink guard. Only protects an artifact that
183
+ // already has real content — a fresh/empty canvas (new-entry template) can
184
+ // be filled freely without a prior read. Prefer the live editor body, so
185
+ // the hash matches what read_artifact returned.
186
+ let currentBody = null;
187
+ try {
188
+ const existing = graph.get('artifact', updateTarget.entityId);
189
+ currentBody = graph.getLiveBody('artifact', updateTarget.entityId) ?? existing.document.content;
190
+ }
191
+ catch {
192
+ currentBody = null; // artifact doesn't exist yet → nothing to protect
193
+ }
194
+ if (currentBody && !artifactBodyIsBlank(currentBody)) {
195
+ if (!options?.baseHash) {
196
+ throw new Error('This artifact already has content — call read_artifact first and pass its hash as baseHash before updating, so you do not overwrite the current source.');
197
+ }
198
+ if (options.baseHash !== hashArtifactBody(currentBody)) {
199
+ throw new Error('Artifact changed since you read it (baseHash mismatch). Call read_artifact again, re-apply your change to the current source, then retry.');
200
+ }
201
+ if (!options.replace && bundleEntrypointBlank(validBundle)) {
202
+ throw new Error('Refusing to blank a non-empty artifact. Include the full content, or pass replace: true to intentionally clear it.');
203
+ }
204
+ }
205
+ await graph.update({
206
+ entityType: 'artifact',
207
+ entityId: updateTarget.entityId,
208
+ data: updateData,
209
+ content: body,
210
+ commitMessage: `Update artifact/${updateTarget.entityId} from agent`,
211
+ user: actor,
212
+ source: 'server-write',
213
+ });
214
+ return { repo: updateTarget.repo, entityType: 'artifact', entityId: updateTarget.entityId, action: 'updated' };
215
+ }
216
+ const repo = repoFromContext(context, user, agent, authService);
217
+ if (!repo)
218
+ throw new Error('No writable folder is available for the artifact.');
219
+ const graph = workspaceManager.getGraph(repo);
220
+ if (!graph)
221
+ throw new Error(`Folder not found: ${repo}`);
222
+ const baseId = slugifyArtifactId(validBundle.artifactId || validBundle.title);
223
+ let entityId = baseId;
224
+ let foundAvailableId = false;
225
+ for (let i = 2; i < 1000; i++) {
226
+ try {
227
+ graph.get('artifact', entityId);
228
+ entityId = `${baseId}-${i}`;
229
+ }
230
+ catch {
231
+ foundAvailableId = true;
232
+ break;
233
+ }
234
+ }
235
+ if (!foundAvailableId) {
236
+ entityId = `${baseId}-${Date.now().toString(36)}`;
237
+ }
238
+ await graph.create(prepareCreatePayload({
239
+ entityType: 'artifact',
240
+ entityId,
241
+ data: createData,
242
+ content: body,
243
+ commitMessage: `Create artifact/${entityId} from agent`,
244
+ }, actor));
245
+ return { repo, entityType: 'artifact', entityId, action: 'created' };
246
+ }
247
+ /**
248
+ * Render an entry's open (unresolved, non-deleted) comments as a compact,
249
+ * newest-first block so the agent sees user feedback on the entry it's chatting
250
+ * about without having to call a tool. Each line carries the author, the text
251
+ * the comment is pinned to (anchor_quote), and the body. Returns '' when there
252
+ * are no open comments (or no service), so the caller can append unconditionally.
253
+ */
254
+ export function formatEntryComments(commentService, repo, entryType, entryId) {
255
+ if (!commentService)
256
+ return '';
257
+ let comments;
258
+ try {
259
+ comments = commentService.list({ repo, entryType, entryId, resolved: false });
260
+ }
261
+ catch {
262
+ return '';
263
+ }
264
+ if (comments.length === 0)
265
+ return '';
266
+ // list() returns oldest-first (ORDER BY thread_id, created_at); show the most
267
+ // recent feedback first and cap the count.
268
+ const ordered = [...comments]
269
+ .sort((a, b) => b.createdAt.localeCompare(a.createdAt))
270
+ .slice(0, MAX_CONTEXT_COMMENTS);
271
+ const lines = ordered.map(c => {
272
+ const anchor = c.anchorQuote ? ` (on "${c.anchorQuote}")` : '';
273
+ const body = c.body.replace(/\s+/g, ' ').trim();
274
+ return `- ${c.authorDisplayName}${anchor}: ${body}`;
275
+ });
276
+ const more = comments.length > ordered.length
277
+ ? `\n(${comments.length - ordered.length} more unresolved — use get_related to see all)`
278
+ : '';
279
+ return (`\nUnresolved comments on this entry (newest first) — treat these as user ` +
280
+ `feedback to address:\n${lines.join('\n')}${more}\n`);
281
+ }
282
+ export function buildChatContextPrefix(context, user, agent, authService, commentService) {
283
+ if (!context)
284
+ return '';
285
+ const workspaceManager = agent.getWorkspaceManager();
286
+ if (context.startsWith('folder:')) {
287
+ const repo = context.slice('folder:'.length);
288
+ if (!access.hasRepoAccess(user, repo, workspaceManager, authService))
289
+ return '';
290
+ return `[Currently viewing folder: ${repo}]\n\nScope your help to this folder unless the user asks otherwise. Use list_entities or search_entities with repoNames: ["${repo}"] to explore its contents.\n\n`;
291
+ }
292
+ const parts = context.split('/');
293
+ if (parts.length < 3) {
294
+ return `[Currently viewing: ${context}]\n\n`;
295
+ }
296
+ const [repo, type, id] = parts;
297
+ const selectedArtifactTarget = parseArtifactSelectionContext(parts);
298
+ if (!access.hasRepoAccess(user, repo, workspaceManager, authService))
299
+ return '';
300
+ try {
301
+ const graph = workspaceManager.getGraph(repo);
302
+ if (graph) {
303
+ const entity = graph.get(type, id);
304
+ const fm = entity.data ?? {};
305
+ const entityContent = entity.document?.content ?? '';
306
+ const fmLines = Object.entries(fm)
307
+ .filter(([k]) => !['entity_type', 'entity_id', 'created_at', 'updated_at', 'created_by', 'updated_by'].includes(k))
308
+ .map(([k, v]) => `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)
309
+ .join('\n');
310
+ const commentsBlock = formatEntryComments(commentService, repo, type, id);
311
+ const isArtifact = type === 'artifact';
312
+ // For artifacts, the body IS the full ArtifactBundle JSON (all HTML/CSS/JS
313
+ // inlined). Re-sending it every turn overflows the model on larger
314
+ // artifacts, so inject a compact header instead and have the agent pull
315
+ // the source on demand via read_artifact. Use the live editor body so the
316
+ // hash matches what read_artifact / the write guard see.
317
+ let contentSection;
318
+ if (isArtifact) {
319
+ const liveBody = graph.getLiveBody('artifact', id) ?? entityContent;
320
+ let fileCount = 0;
321
+ try {
322
+ const parsed = JSON.parse(liveBody);
323
+ if (parsed?.files && typeof parsed.files === 'object')
324
+ fileCount = Object.keys(parsed.files).length;
325
+ }
326
+ catch { /* malformed body — header still useful */ }
327
+ contentSection = `Artifact source: ${fileCount} file(s), ${liveBody.length} bytes, hash ${hashArtifactBody(liveBody)}. The full source is omitted here to keep context small — call read_artifact to get the current ArtifactBundle before editing.`;
328
+ }
329
+ else {
330
+ contentSection = `Entity content:\n${entityContent}`;
331
+ }
332
+ const artifactInstruction = isArtifact
333
+ ? `\nThis entry is an Artifact Canvas. To revise it, call read_artifact to get the current bundle and its hash, modify the full bundle, then call create_artifact with that bundle and the hash as baseHash (the bundle replaces the canvas). To fill an empty canvas from scratch, call create_artifact directly.\n`
334
+ : '';
335
+ const selectionInstruction = selectedArtifactTarget
336
+ ? `\nSelected artifact target: ${selectedArtifactTarget}\nIf the user refers to "this", "the selected element", "this slide", or a similar scoped target, treat this selected artifact target as the intended area to modify.\n`
337
+ : '';
338
+ return `[Currently viewing entry: ${repo}/${type}/${id}]\n\nEntity frontmatter:\n${fmLines}\n\n${contentSection}\n${commentsBlock}${artifactInstruction}${selectionInstruction}\nAnswer questions about THIS entity. Use the information above.\n\n`;
339
+ }
340
+ }
341
+ catch {
342
+ return `[Currently viewing entry: ${repo}/${type}/${id}]\n\n`;
343
+ }
344
+ return '';
345
+ }
346
+ export async function registerChatRoutes(fastify, agent, wsHub, authService, memoryService, commentService, chatSessionService) {
347
+ const cloudBilling = createCloudInferenceBillingClient();
348
+ const creditsGatewayMode = isStudiographCreditsMode();
10
349
  // POST /api/chat — send message, get full response
11
350
  fastify.post('/api/chat', async (req, reply) => {
12
351
  const { message } = req.body;
@@ -15,20 +354,76 @@ export async function registerChatRoutes(fastify, agent, memoryService) {
15
354
  }
16
355
  try {
17
356
  const user = req.user ?? null;
18
- const response = await agent.chatInSession('default', message, { user });
19
- return reply.send(response);
357
+ const sessionId = user ? `user:${user.id}:default` : 'default';
358
+ let billingReservation = null;
359
+ try {
360
+ billingReservation = creditsGatewayMode
361
+ ? null
362
+ : await reserveCloudInference(cloudBilling, agent, 'Hosted Studiograph chat inference.');
363
+ const response = await agent.chatInSession(sessionId, message, { user, userId: user?.id });
364
+ await settleCloudInference(cloudBilling, billingReservation, response.usage);
365
+ billingReservation = null;
366
+ return reply.send({ content: response.content, toolCalls: response.toolCalls });
367
+ }
368
+ catch (err) {
369
+ await releaseCloudInference(cloudBilling, billingReservation, 'Inference request failed before billing settlement.');
370
+ throw err;
371
+ }
20
372
  }
21
373
  catch (err) {
22
374
  fastify.log.error(err, 'Agent chat error');
23
375
  return reply.status(500).send({ error: err.message || 'Agent error' });
24
376
  }
25
377
  });
26
- // POST /api/chat/streamSSE stream of agent events
27
- fastify.post('/api/chat/stream', async (req, reply) => {
28
- const { message, context, sessionId, history } = req.body;
378
+ // POST /api/chat/titlename a conversation from its opening exchange.
379
+ // Called by the client after the first assistant reply lands; the returned
380
+ // title replaces the truncated first-message title shown on the launcher.
381
+ // Best-effort: returns { title: null } when titling isn't possible (gateway
382
+ // mode, no key, empty result) so the client just keeps its fallback.
383
+ fastify.post('/api/chat/title', async (req, reply) => {
384
+ const message = req.body?.message;
385
+ const assistantReply = req.body?.reply ?? '';
29
386
  if (!message || typeof message !== 'string' || !message.trim()) {
30
387
  return reply.status(400).send({ error: 'message is required' });
31
388
  }
389
+ try {
390
+ let billingReservation = null;
391
+ try {
392
+ billingReservation = creditsGatewayMode
393
+ ? null
394
+ : await reserveCloudInference(cloudBilling, agent, 'Studiograph conversation title.');
395
+ const result = await agent.generateConversationTitle(message, assistantReply);
396
+ await settleCloudInference(cloudBilling, billingReservation, result?.usage);
397
+ billingReservation = null;
398
+ return reply.send({ title: result?.title ?? null });
399
+ }
400
+ catch (err) {
401
+ await releaseCloudInference(cloudBilling, billingReservation, 'Title request failed before billing settlement.');
402
+ throw err;
403
+ }
404
+ }
405
+ catch (err) {
406
+ fastify.log.error(err, 'Title generation error');
407
+ // Non-fatal — the client keeps its fallback title.
408
+ return reply.send({ title: null });
409
+ }
410
+ });
411
+ // POST /api/chat/stream — SSE stream of agent events
412
+ fastify.post('/api/chat/stream', async (req, reply) => {
413
+ const { message, context, sessionId, attachments, images, history, clientDate, clientDateLabel } = req.body;
414
+ // Unify the generic `attachments` field with the legacy `images` field
415
+ // (D10) so old clients keep working. The current turn's refs cover both
416
+ // images (→ vision) and docs (→ injected text).
417
+ const currentRefs = [
418
+ ...(Array.isArray(attachments) ? attachments : []),
419
+ ...(Array.isArray(images) ? images : []),
420
+ ];
421
+ // #5: a turn is valid with text OR at least one attachment (image/doc-only
422
+ // sends are allowed); empty-everything is still rejected.
423
+ if (!isValidAttachmentTurn(message, currentRefs.length)) {
424
+ return reply.status(400).send({ error: 'message or attachments required' });
425
+ }
426
+ const messageText = typeof message === 'string' ? message : '';
32
427
  const user = req.user ?? null;
33
428
  const resolvedSessionId = sessionId
34
429
  ? (user ? `user:${user.id}:${sessionId}` : sessionId)
@@ -54,11 +449,216 @@ export async function registerChatRoutes(fastify, agent, memoryService) {
54
449
  // Detect client disconnect
55
450
  reply.raw.on('close', () => { streamDead = true; });
56
451
  reply.raw.on('error', () => { streamDead = true; });
452
+ // Internal-agent identity for activity + entity_change tagging. The web
453
+ // agent runs inside a user session, so the label reads as "<user>'s
454
+ // agent" — distinguishable in the sidebar from external MCP integrations
455
+ // which carry their token name (e.g. "Christian's Cursor").
456
+ const agentLabel = user?.displayName ? `${user.displayName}'s agent` : 'Agent';
457
+ const agentIdentity = {
458
+ kind: 'internal',
459
+ label: agentLabel,
460
+ userId: user?.id != null ? String(user.id) : undefined,
461
+ };
462
+ // Turn-scoped activity tracking. A single chat turn can fan out across
463
+ // multiple folders and intersperse tool calls with LLM "thinking" gaps.
464
+ // We want one continuous chip per touched folder for the whole turn —
465
+ // not a flicker per tool call. So:
466
+ // 1. The first `enter` for a repo broadcasts and adds the repo to a
467
+ // turn-local set; subsequent enters refresh it (server-side
468
+ // throttle drops sub-second repeats).
469
+ // 2. Per-tool `leave` events are suppressed — the chip is "pinned"
470
+ // until the turn ends.
471
+ // 3. A 2s heartbeat keeps the chip alive across multi-second LLM
472
+ // thinking gaps that would otherwise time out the client's
473
+ // MIN_VISIBLE floor.
474
+ // 4. The finally block below fires the actual `leave` for every
475
+ // touched folder when the turn completes (success, error, or
476
+ // client disconnect).
477
+ const activeRepos = new Set();
478
+ let activityHeartbeat = null;
479
+ function ensureActivityHeartbeat() {
480
+ if (activityHeartbeat)
481
+ return;
482
+ activityHeartbeat = setInterval(() => {
483
+ for (const repo of activeRepos) {
484
+ wsHub.handleAgentActivity('heartbeat', repo, agentIdentity);
485
+ }
486
+ }, 2_000);
487
+ }
488
+ function stopActivityHeartbeat() {
489
+ if (activityHeartbeat) {
490
+ clearInterval(activityHeartbeat);
491
+ activityHeartbeat = null;
492
+ }
493
+ }
494
+ let billingReservation = null;
57
495
  try {
496
+ billingReservation = creditsGatewayMode
497
+ ? null
498
+ : await reserveCloudInference(cloudBilling, agent, 'Hosted Studiograph streaming chat inference.');
499
+ let artifactCount = 0;
500
+ const gitUser = reqGitUser(req);
501
+ const entityContext = parseEntityContext(context);
502
+ const currentArtifactTarget = entityContext?.entityType === 'artifact'
503
+ ? { repo: entityContext.repo, entityId: entityContext.entityId }
504
+ : null;
505
+ // Resolve composer attachments. The client sends durable REFS, never
506
+ // bytes; we resolve from the asset/scratch ROW (A1) and re-authorize
507
+ // every call. Two transports, by type:
508
+ // - images → vision blocks (current turn only — prior images are held by
509
+ // the warm agent-pool, or re-attached on demand by the user, D7).
510
+ // - docs → injected TEXT, replayed EVERY turn from the session's prior
511
+ // user messages + the current turn (D7), so they survive reload and
512
+ // stay in context late in long chats. Doc text is already extracted +
513
+ // stored, so replay is just a row read (no re-parse).
514
+ // Denied/deleted/over-cap refs degrade to `[file: name]` notes, not errors.
515
+ let imageBlocks = [];
516
+ let imagePlaceholders = [];
517
+ let docContext = '';
518
+ let docPlaceholders = [];
519
+ // Doc refs replayed from history (prior user messages) — re-authorized in
520
+ // the resolver, so a revoked/deleted file silently drops.
521
+ const historyRefs = (user && sessionId && chatSessionService)
522
+ ? chatSessionService.getSessionAttachmentRefs(user.id, sessionId)
523
+ .map(normalizeAttachmentRef)
524
+ .filter((r) => r !== null)
525
+ : [];
526
+ if (currentRefs.length > 0 || historyRefs.length > 0) {
527
+ const attWsm = agent.getWorkspaceManager();
528
+ const attIndex = attWsm.getAssetIndex?.();
529
+ // The scratch blob store is workspace-global — reach it via any graph.
530
+ const scratchGraph = (() => {
531
+ for (const cfg of attWsm.getAllRepoConfigs()) {
532
+ try {
533
+ const g = attWsm.getGraph(cfg.name);
534
+ if (g.getAssetService?.())
535
+ return g;
536
+ }
537
+ catch { /* next */ }
538
+ }
539
+ return null;
540
+ })();
541
+ const deps = {
542
+ getAssetRow: (id) => attIndex?.get(id) ?? null,
543
+ canAccessRepo: (repo) => access.hasRepoAccess(user ?? undefined, repo, attWsm, authService),
544
+ downloadAsset: (repo, id, filename) => attWsm.getGraph(repo).downloadAssetById(id, filename),
545
+ getScratchRow: (sid, fid) => chatSessionService?.getScratchFile(sid, fid) ?? null,
546
+ downloadScratch: (blobKey) => {
547
+ const svc = scratchGraph?.getAssetService?.();
548
+ if (!svc)
549
+ throw new Error('scratch backend unavailable');
550
+ return svc.download(blobKey);
551
+ },
552
+ currentUserId: user?.id,
553
+ };
554
+ // Images — current turn only. Gated on vision: a text-only model can't
555
+ // see pixels, so degrade every image ref to a text note.
556
+ if (currentRefs.length > 0) {
557
+ if (agent.supportsVision()) {
558
+ ({ blocks: imageBlocks, placeholders: imagePlaceholders } = await resolveImageRefs(currentRefs, deps));
559
+ }
560
+ else {
561
+ // Only IMAGE refs are "can't show" here — docs still go in as text
562
+ // via docContext below, so they must not also get a dropped note.
563
+ // Library `asset` refs are always images; a `scratch` ref's kind
564
+ // lives on its row, so look it up (cheap, rare text-only path).
565
+ imagePlaceholders = currentRefs
566
+ .filter((r) => r.kind === 'asset' || deps.getScratchRow(r.sessionId, r.fileId)?.kind === 'image')
567
+ .map((r) => attachmentPlaceholder(r.filename));
568
+ }
569
+ }
570
+ // Docs — current turn FIRST so a freshly-attached doc wins the file/char
571
+ // budget over older replayed history; deduped in the resolver. Not
572
+ // vision-gated (text works on any model). Synchronous (stored text).
573
+ ({ docContext, placeholders: docPlaceholders } = resolveDocContext([...currentRefs, ...historyRefs], deps));
574
+ }
575
+ const attachmentPlaceholders = [...imagePlaceholders, ...docPlaceholders];
58
576
  const response = await agent.getPool().withAgent(resolvedSessionId, {
59
577
  user,
578
+ // Raw client session id (what scratch images are keyed by) so
579
+ // session-scoped tools target THIS conversation, not other chats.
580
+ clientSessionId: sessionId,
581
+ currentArtifactTarget,
60
582
  onHighlight: (ids) => sendEvent({ type: 'highlight', entityIds: ids }),
61
- onMutation: (m) => sendEvent({ type: 'mutation', action: m.action, repo: m.repo, entityType: m.entityType, entityId: m.entityId }),
583
+ onArtifact: async (bundle, target, writeOptions) => {
584
+ const location = await persistArtifactFromChat({
585
+ bundle,
586
+ context,
587
+ target,
588
+ user,
589
+ agent,
590
+ authService,
591
+ gitUser,
592
+ options: writeOptions,
593
+ });
594
+ artifactCount++;
595
+ sendEvent({ type: 'artifact', artifact: bundle, ...location });
596
+ sendEvent({
597
+ type: 'mutation',
598
+ action: location.action,
599
+ repo: location.repo,
600
+ entityType: location.entityType,
601
+ entityId: location.entityId,
602
+ });
603
+ wsHub.broadcast({
604
+ type: 'entity_change',
605
+ action: location.action,
606
+ repo: location.repo,
607
+ entityType: location.entityType,
608
+ entityId: location.entityId,
609
+ actor: user?.displayName ?? 'Agent',
610
+ source: 'api',
611
+ agent: agentIdentity,
612
+ timestamp: new Date().toISOString(),
613
+ });
614
+ return location;
615
+ },
616
+ onMutation: (m) => {
617
+ // Stream the event to the requesting user's chat (existing behavior).
618
+ sendEvent({ type: 'mutation', action: m.action, repo: m.repo, entityType: m.entityType, entityId: m.entityId });
619
+ // Broadcast to all connected workspace clients so OTHER users
620
+ // see live updates from this user's agent. Without this, the
621
+ // web agent's mutations are invisible to peers until they
622
+ // reload — MCP mutations already broadcast via src/mcp/tools.ts.
623
+ wsHub.broadcast({
624
+ type: 'entity_change',
625
+ action: m.action,
626
+ repo: m.repo,
627
+ entityType: m.entityType,
628
+ entityId: m.entityId,
629
+ actor: user?.displayName ?? 'Agent',
630
+ source: 'api',
631
+ agent: agentIdentity,
632
+ timestamp: new Date().toISOString(),
633
+ });
634
+ // Asset-only change (e.g. saving a chat image to the library):
635
+ // also emit repo_sync so asset views refresh — they don't track
636
+ // entity_change (free-standing assets aren't entities).
637
+ if (m.repoSync) {
638
+ wsHub.broadcast({
639
+ type: 'repo_sync',
640
+ repo: m.repo,
641
+ actor: user?.displayName ?? 'Agent',
642
+ source: 'api',
643
+ agent: agentIdentity,
644
+ timestamp: new Date().toISOString(),
645
+ });
646
+ }
647
+ },
648
+ onAgentActivity: (action, repo) => {
649
+ if (action === 'enter') {
650
+ activeRepos.add(repo);
651
+ wsHub.handleAgentActivity('enter', repo, agentIdentity);
652
+ ensureActivityHeartbeat();
653
+ }
654
+ // Per-tool `leave` is intentionally suppressed — the finally
655
+ // block at turn end fires a single `leave` per repo. `heartbeat`
656
+ // doesn't currently fire from tool wrappers, but if it did,
657
+ // pass through.
658
+ if (action === 'heartbeat' && activeRepos.has(repo)) {
659
+ wsHub.handleAgentActivity('heartbeat', repo, agentIdentity);
660
+ }
661
+ },
62
662
  }, async (rawAgent) => {
63
663
  // Subscribe to agent events for streaming
64
664
  let hasContent = false;
@@ -86,82 +686,127 @@ export async function registerChatRoutes(fastify, agent, memoryService) {
86
686
  }
87
687
  }
88
688
  });
89
- // Build context
90
- let contextPrefix = '';
91
- if (context) {
92
- const parts = context.split('/');
93
- if (parts.length >= 3) {
94
- const [repo, type, id] = parts;
95
- try {
96
- const graph = agent.getWorkspaceManager().getGraph(repo);
97
- if (graph) {
98
- const entity = graph.get(type, id);
99
- const fm = entity.data ?? {};
100
- const entityContent = entity.document?.content ?? '';
101
- const fmLines = Object.entries(fm)
102
- .filter(([k]) => !['entity_type', 'entity_id', 'created_at', 'updated_at', 'created_by', 'updated_by'].includes(k))
103
- .map(([k, v]) => `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)
104
- .join('\n');
105
- contextPrefix = `[Currently viewing: ${context}]\n\nEntity frontmatter:\n${fmLines}\n\nEntity content:\n${entityContent}\n\nAnswer questions about THIS entity. Use the information above.\n\n`;
106
- }
107
- }
108
- catch {
109
- contextPrefix = `[Currently viewing: ${context}]\n\n`;
110
- }
111
- }
112
- else {
113
- contextPrefix = `[Currently viewing: ${context}]\n\n`;
114
- }
115
- }
689
+ // Build scope-aware context prefix only after folder access passes.
690
+ const contextPrefix = buildChatContextPrefix(context, user ?? undefined, agent, authService, commentService);
116
691
  const userPrefix = user ? `[Current user: ${user.displayName} (${user.email}, ${user.role})]\n\n` : '';
117
- const fullMessage = userPrefix + contextPrefix + message;
692
+ const datePrefix = buildDatePrefix(clientDate, clientDateLabel);
693
+ // #5: image/doc-only send → a minimal prompt so the agent looks at
694
+ // the attachment. Dropped-file notes (placeholders) ride along as text.
695
+ const hasAttachmentContent = imageBlocks.length > 0 || docContext.length > 0;
696
+ const userText = composeAttachmentMessageText(messageText, hasAttachmentContent, attachmentPlaceholders);
697
+ // Doc context (D12-wrapped, capped) goes BEFORE the user's text so the
698
+ // question can reference "the attached file"; the wrapper marks it as
699
+ // data, not instructions.
700
+ const docBlock = docContext ? `${docContext}\n\n` : '';
701
+ const fullMessage = userPrefix + datePrefix + contextPrefix + docBlock + userText;
118
702
  // Send message and await response
119
703
  const result = await new Promise((resolve, reject) => {
120
704
  let content = '';
705
+ let assistantMessageCount = 0;
706
+ let toolCallCount = 0;
707
+ const blockTypeCounts = {};
708
+ let lastStopReason;
709
+ let lastErrorMessage;
710
+ const usage = createInferenceUsageSummary();
121
711
  const endSub = rawAgent.subscribe((event) => {
122
712
  if (event.type === 'message_end' && event.message?.role === 'assistant') {
123
- content = event.message.content
124
- .filter((b) => b.type === 'text')
125
- .map((b) => b.text)
126
- .join('');
713
+ addInferenceUsage(usage, event.message.usage);
714
+ assistantMessageCount++;
715
+ const blocks = event.message.content ?? [];
716
+ for (const b of blocks) {
717
+ blockTypeCounts[b.type] = (blockTypeCounts[b.type] ?? 0) + 1;
718
+ }
719
+ const textBlocks = blocks.filter((b) => b.type === 'text');
720
+ const toolBlocks = blocks.filter((b) => b.type === 'toolCall');
721
+ toolCallCount += toolBlocks.length;
722
+ if (event.message.stopReason)
723
+ lastStopReason = event.message.stopReason;
724
+ if (event.message.errorMessage)
725
+ lastErrorMessage = event.message.errorMessage;
726
+ // Keep the LAST non-empty text seen, so a follow-up assistant
727
+ // turn that has only tool calls doesn't wipe out the text that
728
+ // was produced earlier in the same prompt run.
729
+ const turnText = textBlocks.map((b) => b.text).join('');
730
+ if (turnText.length > 0)
731
+ content = turnText;
127
732
  }
128
733
  else if (event.type === 'agent_end') {
129
734
  endSub();
130
- resolve({ content });
735
+ if (!content) {
736
+ log.warn(`[chat/stream] agent produced no text ` +
737
+ `(assistantMessages=${assistantMessageCount}, toolCalls=${toolCallCount}, ` +
738
+ `blockTypes=${JSON.stringify(blockTypeCounts)}, ` +
739
+ `stopReason=${lastStopReason ?? 'n/a'}, ` +
740
+ `errorMessage=${JSON.stringify(lastErrorMessage ?? null)}, ` +
741
+ `sessionId=${resolvedSessionId}) prompt="${messageText.slice(0, 80)}"`);
742
+ }
743
+ resolve({ content, usage });
131
744
  }
132
745
  });
133
- rawAgent.prompt(fullMessage).catch((err) => { endSub(); reject(err); });
746
+ rawAgent.prompt(fullMessage, imageBlocks.length ? imageBlocks : undefined)
747
+ .catch((err) => { endSub(); reject(err); });
134
748
  });
135
749
  unsubscribe();
136
750
  return result;
137
751
  }, { userId: user?.id, fallbackHistory: history });
752
+ await settleCloudInference(cloudBilling, billingReservation, response.usage);
753
+ billingReservation = null;
138
754
  // Write brief entry to today's daily memory
139
755
  if (memoryService && response.content) {
140
756
  try {
141
- const snippet = `User: ${message.slice(0, 100)}${message.length > 100 ? '…' : ''}\nAgent: ${response.content.slice(0, 200)}${response.content.length > 200 ? '…' : ''}`;
757
+ const snippet = `User: ${messageText.slice(0, 100)}${messageText.length > 100 ? '…' : ''}\nAgent: ${response.content.slice(0, 200)}${response.content.length > 200 ? '…' : ''}`;
142
758
  memoryService.saveSessionSummary(snippet, { source: 'web-chat', sessionId }, user?.id);
143
759
  }
144
760
  catch { /* non-fatal */ }
145
761
  }
146
- // Parse follow-up suggestions from response
147
- const followupRe = /<!--\s*followups:\s*(\[.*?\])\s*-->\s*$/s;
148
- const followupMatch = response.content.match(followupRe);
149
- let suggestions;
150
- let cleanContent = response.content;
151
- if (followupMatch) {
152
- try {
153
- suggestions = JSON.parse(followupMatch[1]);
154
- cleanContent = response.content.slice(0, followupMatch.index).trimEnd();
155
- }
156
- catch { /* malformed — ignore */ }
762
+ // Parse follow-up suggestions from response (shared with CLI transport)
763
+ const { content: parsedContent, suggestions } = parseFollowups(response.content);
764
+ let cleanContent = parsedContent;
765
+ // If the agent finished with no text AND no tool call, surface that
766
+ // explicitly so the UI doesn't look frozen. Users reported "silent
767
+ // failures" that were actually legitimately-empty assistant turns.
768
+ // The `fallback: true` flag lets the client decide what to do \u2014
769
+ // typed prompts render the message, system-initiated silent prompts
770
+ // (auto-greet) drop the placeholder so users don't see a confusing
771
+ // "Could you try rephrasing?" they didn't trigger.
772
+ let fallback = false;
773
+ if (!cleanContent.trim() && artifactCount === 0 && !streamDead) {
774
+ cleanContent = '_I didn\u2019t have a response for that. Could you try rephrasing?_';
775
+ fallback = true;
157
776
  }
158
- sendEvent({ type: 'done', message: cleanContent, suggestions });
777
+ sendEvent({ type: 'done', message: cleanContent, suggestions, fallback });
159
778
  }
160
779
  catch (err) {
780
+ await releaseCloudInference(cloudBilling, billingReservation, 'Inference request failed before billing settlement.');
781
+ // Log to stderr so silent agent failures show up in server logs —
782
+ // the SSE error event goes to the client but was invisible to ops.
783
+ log.error('[chat/stream] agent error:', err?.stack || err?.message || err);
161
784
  sendEvent({ type: 'error', message: err.message || 'Agent error' });
162
785
  }
786
+ finally {
787
+ // End-of-turn agent activity cleanup. Fires for every folder the
788
+ // agent touched during this turn — including paths through the
789
+ // catch branch above, so a crashed/aborted turn still releases
790
+ // its chips instead of relying on the 90s server TTL.
791
+ stopActivityHeartbeat();
792
+ for (const repo of activeRepos) {
793
+ wsHub.handleAgentActivity('leave', repo, agentIdentity);
794
+ }
795
+ activeRepos.clear();
796
+ }
163
797
  reply.raw.end();
164
798
  });
799
+ // GET /api/chat/capabilities — composer feature gating (vision attach).
800
+ fastify.get('/api/chat/capabilities', async (_req, reply) => {
801
+ try {
802
+ return { vision: agent.supportsVision() };
803
+ }
804
+ catch {
805
+ // Conservative default — hide/disable the affordance rather than offer a
806
+ // vision attach the model can't honor.
807
+ return reply.send({ vision: false });
808
+ }
809
+ });
165
810
  // POST /api/chat/abort — abort the current agent run
166
811
  fastify.post('/api/chat/abort', async (_req, reply) => {
167
812
  try {