clay-server 5.1.1-beta.1 → 5.2.0-beta.10

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 (588) hide show
  1. package/lib/account-auth-policy.js +21 -0
  2. package/lib/account-auth-socket.js +30 -0
  3. package/lib/account-auth-throttle.js +44 -0
  4. package/lib/account-auth-transport.js +48 -0
  5. package/lib/account-login-page.js +28 -0
  6. package/lib/account-passkey-challenges.js +31 -0
  7. package/lib/account-passkey-page.js +89 -0
  8. package/lib/account-passkey-policy.js +39 -0
  9. package/lib/account-password-page.js +69 -0
  10. package/lib/account-passwords.js +36 -0
  11. package/lib/account-remembered.js +77 -0
  12. package/lib/account-session-page.js +51 -0
  13. package/lib/account-session-store.js +82 -0
  14. package/lib/builtin-mates.js +19 -16
  15. package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
  16. package/lib/canonical-clay-record-authority.js +15 -0
  17. package/lib/canonical-clay-scheduling-authority.js +19 -0
  18. package/lib/claude-hook-installer.js +1 -239
  19. package/lib/claude-jsonl-watcher.js +1 -204
  20. package/lib/clay-control-presentation-binding.js +96 -0
  21. package/lib/clay-control-presentation.js +128 -0
  22. package/lib/clay-control-target-projection.js +26 -0
  23. package/lib/clay-mate-chat-receipts.js +26 -0
  24. package/lib/clay-mate-chat.js +88 -0
  25. package/lib/clay-mate-knowledge-input.js +26 -0
  26. package/lib/clay-mate-knowledge.js +95 -0
  27. package/lib/clay-mate-lifecycle.js +95 -0
  28. package/lib/clay-product-control-input.js +33 -0
  29. package/lib/clay-product-control-tools.js +51 -0
  30. package/lib/clay-product-control.js +247 -0
  31. package/lib/clay-project-lifecycle.js +154 -0
  32. package/lib/clay-project-record-input.js +44 -0
  33. package/lib/clay-project-records.js +84 -0
  34. package/lib/clay-scheduling-input.js +21 -0
  35. package/lib/clay-scheduling-receipts.js +26 -0
  36. package/lib/clay-scheduling.js +119 -0
  37. package/lib/clay-screen-controls.js +104 -0
  38. package/lib/clay-skill-install.js +1 -33
  39. package/lib/clay-workspace-controls.js +84 -0
  40. package/lib/clay-workspace-input.js +17 -0
  41. package/lib/clay-workspace-receipts.js +26 -0
  42. package/lib/cli-sessions.js +1 -300
  43. package/lib/codex-defaults.js +1 -28
  44. package/lib/context-usage.js +3 -2
  45. package/lib/contextual-screen-snapshot.js +38 -0
  46. package/lib/daemon-project-access.js +11 -0
  47. package/lib/daemon-project-lifecycle-callbacks.js +15 -0
  48. package/lib/daemon-project-lifecycle.js +262 -0
  49. package/lib/daemon-projects.js +1 -1
  50. package/lib/daemon.js +80 -276
  51. package/lib/default-ai-runtime.js +4 -8
  52. package/lib/dm-digest-cursor.js +120 -0
  53. package/lib/email-mcp-server.js +1 -1
  54. package/lib/issues-service.js +29 -15
  55. package/lib/kiro-defaults.js +1 -22
  56. package/lib/knowledge-db-import-validation.js +46 -0
  57. package/lib/knowledge-db-import.js +99 -0
  58. package/lib/knowledge-db-service.js +24 -33
  59. package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
  60. package/lib/knowledge-db-storage-nedb.js +66 -0
  61. package/lib/knowledge-db-storage.js +72 -0
  62. package/lib/knowledge-db-validation.js +0 -0
  63. package/lib/knowledge-document-index.js +2 -1
  64. package/lib/knowledge-file-store.js +7 -1
  65. package/lib/knowledge-product-operations.js +46 -0
  66. package/lib/mate-avatar-catalog.js +12 -0
  67. package/lib/mate-avatar-migration.js +41 -0
  68. package/lib/mate-context-service.js +138 -0
  69. package/lib/mate-context-tools.js +21 -0
  70. package/lib/mate-creation-mcp-server.js +2 -0
  71. package/lib/mate-knowledge-canonical-access.js +10 -0
  72. package/lib/mate-knowledge-mate-bound.js +53 -0
  73. package/lib/mate-knowledge-mcp-server.js +55 -8
  74. package/lib/mate-knowledge-service.js +16 -34
  75. package/lib/mate-knowledge-text-tools.js +106 -0
  76. package/lib/mate-lifecycle-service.js +94 -0
  77. package/lib/mate-message-delivery.js +43 -0
  78. package/lib/mate-ready-creation.js +9 -1
  79. package/lib/mate-schedule-input.js +29 -0
  80. package/lib/mate-schedule-lifecycle.js +151 -0
  81. package/lib/mate-scheduling.js +103 -0
  82. package/lib/mates.js +18 -6
  83. package/lib/mcp-agent-tools.js +117 -0
  84. package/lib/mcp-connection-store.js +119 -15
  85. package/lib/mcp-import-credentials.js +31 -0
  86. package/lib/mcp-local-transport.js +13 -0
  87. package/lib/mcp-oauth.js +8 -6
  88. package/lib/mcp-proxy.js +2 -32
  89. package/lib/mcp-query-bridge.js +30 -0
  90. package/lib/mcp-remote-connections.js +74 -20
  91. package/lib/mcp-source-adapters.js +1 -0
  92. package/lib/mcp-source-context.js +1 -0
  93. package/lib/mcp-source-discovery.js +1 -0
  94. package/lib/mcp-source-plugins.js +1 -0
  95. package/lib/mcp-source-restrictions.js +1 -0
  96. package/lib/mcp-tool-policy.js +9 -0
  97. package/lib/migrate-single-user.js +3 -23
  98. package/lib/notes-checklist.js +50 -0
  99. package/lib/notes.js +49 -3
  100. package/lib/os-user-diagnostics.js +2 -4
  101. package/lib/os-users.js +24 -70
  102. package/lib/pane-pending-interactions.js +20 -0
  103. package/lib/pane-session-activation.js +114 -0
  104. package/lib/pane-session-transport.js +26 -0
  105. package/lib/project-admin-overview.js +51 -0
  106. package/lib/project-ask-user.js +8 -4
  107. package/lib/project-connection.js +14 -10
  108. package/lib/project-control-git-view.js +12 -0
  109. package/lib/project-debate.js +1 -0
  110. package/lib/project-delegated-follow-up.js +2 -1
  111. package/lib/project-directory-claim.js +65 -0
  112. package/lib/project-file-operations.js +61 -0
  113. package/lib/project-filesystem.js +15 -85
  114. package/lib/project-full-access.js +23 -2
  115. package/lib/project-http.js +7 -4
  116. package/lib/project-knowledge.js +32 -18
  117. package/lib/project-lifecycle-operations.js +98 -0
  118. package/lib/project-lifecycle-process-witness.js +32 -0
  119. package/lib/project-lifecycle-runtime.js +50 -0
  120. package/lib/project-linux-access.js +22 -0
  121. package/lib/project-logs-canonical-clay.js +27 -0
  122. package/lib/project-logs-clay-query.js +16 -0
  123. package/lib/project-logs-schema.js +4 -2
  124. package/lib/project-logs-service.js +8 -7
  125. package/lib/project-logs.js +1 -0
  126. package/lib/project-loop.js +1 -0
  127. package/lib/project-mate-chat-control.js +55 -0
  128. package/lib/project-mate-creation-proposal.js +18 -3
  129. package/lib/project-mate-interaction.js +40 -62
  130. package/lib/project-mcp.js +54 -16
  131. package/lib/project-models.js +14 -31
  132. package/lib/project-notifications.js +76 -17
  133. package/lib/project-ownership.js +77 -0
  134. package/lib/project-pair-result-delivery.js +14 -3
  135. package/lib/project-pair-usage.js +12 -13
  136. package/lib/project-pending-message-queue.js +4 -1
  137. package/lib/project-product-control.js +89 -0
  138. package/lib/project-product-session-queue.js +46 -0
  139. package/lib/project-push-access.js +28 -0
  140. package/lib/project-scheduled-message-queue.js +30 -0
  141. package/lib/project-scheduled-messages.js +67 -68
  142. package/lib/project-scheduled-task-control.js +83 -0
  143. package/lib/project-scheduled-tasks.js +13 -2
  144. package/lib/project-scheduling-access.js +10 -0
  145. package/lib/project-server-settings.js +1 -0
  146. package/lib/project-session-actions.js +65 -0
  147. package/lib/project-session-delete.js +8 -1
  148. package/lib/project-session-document.js +27 -7
  149. package/lib/project-session-github.js +63 -19
  150. package/lib/project-session-history-actions.js +167 -0
  151. package/lib/project-session-linear.js +14 -6
  152. package/lib/project-session-notes.js +7 -3
  153. package/lib/project-session-pair.js +1 -1
  154. package/lib/project-session-runtime-actions.js +64 -0
  155. package/lib/project-session-spawn.js +2 -3
  156. package/lib/project-session-vendor.js +55 -0
  157. package/lib/project-sessions.js +103 -272
  158. package/lib/project-shared-browser.js +78 -17
  159. package/lib/project-studio-presentation.js +58 -0
  160. package/lib/project-user-knowledge.js +2 -1
  161. package/lib/project-user-message.js +67 -1
  162. package/lib/project-vendor-login.js +6 -36
  163. package/lib/project-workspace-operations.js +126 -0
  164. package/lib/project-workspace-query.js +19 -2
  165. package/lib/project.js +178 -45
  166. package/lib/public/app.js +46 -0
  167. package/lib/public/appearance-bootstrap.js +16 -0
  168. package/lib/public/auth/account-login.css +98 -0
  169. package/lib/public/auth/account-login.js +104 -0
  170. package/lib/public/css/clay-tool-activity.css +51 -0
  171. package/lib/public/css/clay-workspace.css +29 -0
  172. package/lib/public/css/command-palette.css +12 -33
  173. package/lib/public/css/contextual-clay.css +240 -0
  174. package/lib/public/css/home-debate-planning.css +2 -0
  175. package/lib/public/css/home-mate-creation.css +5 -0
  176. package/lib/public/css/input.css +6 -0
  177. package/lib/public/css/mate-avatar-gallery.css +12 -0
  178. package/lib/public/css/mate-conversation.css +10 -5
  179. package/lib/public/css/messages.css +6 -2
  180. package/lib/public/css/overlays.css +4 -2
  181. package/lib/public/css/project-admin-overview.css +13 -0
  182. package/lib/public/css/session-folders.css +11 -0
  183. package/lib/public/css/session-github.css +46 -1
  184. package/lib/public/css/shared-browser.css +35 -1
  185. package/lib/public/css/sticky-notes.css +87 -1
  186. package/lib/public/css/user-settings-sessions.css +42 -0
  187. package/lib/public/index.html +28 -10
  188. package/lib/public/mate-avatars/B01.png +0 -0
  189. package/lib/public/mate-avatars/B02.png +0 -0
  190. package/lib/public/mate-avatars/B03.png +0 -0
  191. package/lib/public/mate-avatars/B04.png +0 -0
  192. package/lib/public/mate-avatars/B05.png +0 -0
  193. package/lib/public/mate-avatars/B06.png +0 -0
  194. package/lib/public/mate-avatars/B07.png +0 -0
  195. package/lib/public/mate-avatars/B08.png +0 -0
  196. package/lib/public/mate-avatars/B09.png +0 -0
  197. package/lib/public/mate-avatars/B10.png +0 -0
  198. package/lib/public/mate-avatars/B11.png +0 -0
  199. package/lib/public/mate-avatars/B12.png +0 -0
  200. package/lib/public/mate-avatars/B13.png +0 -0
  201. package/lib/public/mate-avatars/B14.png +0 -0
  202. package/lib/public/mate-avatars/B15.png +0 -0
  203. package/lib/public/mate-avatars/B16.png +0 -0
  204. package/lib/public/mate-avatars/B17.png +0 -0
  205. package/lib/public/mate-avatars/B18.png +0 -0
  206. package/lib/public/mate-avatars/B19.png +0 -0
  207. package/lib/public/mate-avatars/B20.png +0 -0
  208. package/lib/public/mate-avatars/B21.png +0 -0
  209. package/lib/public/mate-avatars/B22.png +0 -0
  210. package/lib/public/mate-avatars/B23.png +0 -0
  211. package/lib/public/mate-avatars/B24.png +0 -0
  212. package/lib/public/mate-avatars/B25.png +0 -0
  213. package/lib/public/mate-avatars/B26.png +0 -0
  214. package/lib/public/mate-avatars/B27.png +0 -0
  215. package/lib/public/mate-avatars/B28.png +0 -0
  216. package/lib/public/mate-avatars/B29.png +0 -0
  217. package/lib/public/mate-avatars/B30.png +0 -0
  218. package/lib/public/mate-avatars/B31.png +0 -0
  219. package/lib/public/mate-avatars/B32.png +0 -0
  220. package/lib/public/mate-avatars/B33.png +0 -0
  221. package/lib/public/mate-avatars/B34.png +0 -0
  222. package/lib/public/mate-avatars/B35.png +0 -0
  223. package/lib/public/mate-avatars/B36.png +0 -0
  224. package/lib/public/mate-avatars/B37.png +0 -0
  225. package/lib/public/mate-avatars/B38.png +0 -0
  226. package/lib/public/mate-avatars/B39.png +0 -0
  227. package/lib/public/mate-avatars/B40.png +0 -0
  228. package/lib/public/mate-avatars/B41.png +0 -0
  229. package/lib/public/mate-avatars/B42.png +0 -0
  230. package/lib/public/mate-avatars/B43.png +0 -0
  231. package/lib/public/mate-avatars/B44.png +0 -0
  232. package/lib/public/mate-avatars/B45.png +0 -0
  233. package/lib/public/mate-avatars/B46.png +0 -0
  234. package/lib/public/mate-avatars/B47.png +0 -0
  235. package/lib/public/mate-avatars/B48.png +0 -0
  236. package/lib/public/mate-avatars/C01.png +0 -0
  237. package/lib/public/mate-avatars/C02.png +0 -0
  238. package/lib/public/mate-avatars/C03.png +0 -0
  239. package/lib/public/mate-avatars/C04.png +0 -0
  240. package/lib/public/mate-avatars/C05.png +0 -0
  241. package/lib/public/mate-avatars/C06.png +0 -0
  242. package/lib/public/mate-avatars/C07.png +0 -0
  243. package/lib/public/mate-avatars/C08.png +0 -0
  244. package/lib/public/mate-avatars/C09.png +0 -0
  245. package/lib/public/mate-avatars/C10.png +0 -0
  246. package/lib/public/mate-avatars/C11.png +0 -0
  247. package/lib/public/mate-avatars/C12.png +0 -0
  248. package/lib/public/mate-avatars/C13.png +0 -0
  249. package/lib/public/mate-avatars/C14.png +0 -0
  250. package/lib/public/mate-avatars/C15.png +0 -0
  251. package/lib/public/mate-avatars/C16.png +0 -0
  252. package/lib/public/mate-avatars/C17.png +0 -0
  253. package/lib/public/mate-avatars/C18.png +0 -0
  254. package/lib/public/mate-avatars/C19.png +0 -0
  255. package/lib/public/mate-avatars/C20.png +0 -0
  256. package/lib/public/mate-avatars/C21.png +0 -0
  257. package/lib/public/mate-avatars/C22.png +0 -0
  258. package/lib/public/mate-avatars/C23.png +0 -0
  259. package/lib/public/mate-avatars/C24.png +0 -0
  260. package/lib/public/mate-avatars/C25.png +0 -0
  261. package/lib/public/mate-avatars/C26.png +0 -0
  262. package/lib/public/mate-avatars/C27.png +0 -0
  263. package/lib/public/mate-avatars/C28.png +0 -0
  264. package/lib/public/mate-avatars/C29.png +0 -0
  265. package/lib/public/mate-avatars/C30.png +0 -0
  266. package/lib/public/mate-avatars/C31.png +0 -0
  267. package/lib/public/mate-avatars/C32.png +0 -0
  268. package/lib/public/mate-avatars/C33.png +0 -0
  269. package/lib/public/mate-avatars/C34.png +0 -0
  270. package/lib/public/mate-avatars/C35.png +0 -0
  271. package/lib/public/mate-avatars/C36.png +0 -0
  272. package/lib/public/mate-avatars/C37.png +0 -0
  273. package/lib/public/mate-avatars/C38.png +0 -0
  274. package/lib/public/mate-avatars/C39.png +0 -0
  275. package/lib/public/mate-avatars/C40.png +0 -0
  276. package/lib/public/mate-avatars/C41.png +0 -0
  277. package/lib/public/mate-avatars/C42.png +0 -0
  278. package/lib/public/mate-avatars/C43.png +0 -0
  279. package/lib/public/mate-avatars/C44.png +0 -0
  280. package/lib/public/mate-avatars/C45.png +0 -0
  281. package/lib/public/mate-avatars/C46.png +0 -0
  282. package/lib/public/mate-avatars/C47.png +0 -0
  283. package/lib/public/mate-avatars/C48.png +0 -0
  284. package/lib/public/mate-avatars/catalog.json +482 -0
  285. package/lib/public/mate-avatars/lead-clay.png +0 -0
  286. package/lib/public/modules/account-auth-settings.js +71 -0
  287. package/lib/public/modules/account-transport-settings.js +51 -0
  288. package/lib/public/modules/admin-settings-projects.js +6 -2
  289. package/lib/public/modules/app-connection.js +11 -1
  290. package/lib/public/modules/app-favicon.js +18 -9
  291. package/lib/public/modules/app-header.js +7 -4
  292. package/lib/public/modules/app-loop-ui.js +2 -0
  293. package/lib/public/modules/app-message-router.js +22 -1
  294. package/lib/public/modules/app-messages.js +119 -17
  295. package/lib/public/modules/app-misc.js +3 -1
  296. package/lib/public/modules/app-notifications.js +11 -5
  297. package/lib/public/modules/app-panels.js +61 -123
  298. package/lib/public/modules/app-projects.js +13 -0
  299. package/lib/public/modules/app-rate-limit.js +7 -27
  300. package/lib/public/modules/app-rendering.js +4 -3
  301. package/lib/public/modules/avatar.js +15 -41
  302. package/lib/public/modules/chat-render-runtime.js +20 -0
  303. package/lib/public/modules/clay-browser-links.js +47 -0
  304. package/lib/public/modules/clay-control-activity.js +214 -0
  305. package/lib/public/modules/clay-control-copy.js +36 -0
  306. package/lib/public/modules/clay-control-detail-targets.js +44 -0
  307. package/lib/public/modules/clay-control-object-targets.js +52 -0
  308. package/lib/public/modules/clay-control-target-visibility.js +12 -0
  309. package/lib/public/modules/clay-control-targets.js +44 -0
  310. package/lib/public/modules/clay-log-links.js +23 -0
  311. package/lib/public/modules/clay-navigation-render.js +52 -0
  312. package/lib/public/modules/clay-owner-navigation.js +33 -0
  313. package/lib/public/modules/clay-session-links.js +31 -0
  314. package/lib/public/modules/clay-studio-bridge.js +20 -0
  315. package/lib/public/modules/clay-studio-document.js +67 -0
  316. package/lib/public/modules/clay-studio-render.js +146 -0
  317. package/lib/public/modules/clay-tool-activity.js +140 -0
  318. package/lib/public/modules/clay-tool-presentation.js +342 -0
  319. package/lib/public/modules/command-palette.js +162 -40
  320. package/lib/public/modules/contextual-ask-session.js +26 -0
  321. package/lib/public/modules/contextual-clay-geometry.js +155 -0
  322. package/lib/public/modules/contextual-clay-session.js +130 -0
  323. package/lib/public/modules/contextual-clay-workspace.js +169 -0
  324. package/lib/public/modules/contextual-clay.js +250 -0
  325. package/lib/public/modules/contextual-composer.js +91 -0
  326. package/lib/public/modules/contextual-mate-context.js +117 -0
  327. package/lib/public/modules/contextual-mate-hint.js +40 -0
  328. package/lib/public/modules/contextual-mate-identity.js +23 -0
  329. package/lib/public/modules/contextual-mate-sessions.js +134 -0
  330. package/lib/public/modules/contextual-search.js +137 -0
  331. package/lib/public/modules/contextual-session-citations.js +58 -0
  332. package/lib/public/modules/debate.js +1 -0
  333. package/lib/public/modules/default-ai.js +11 -3
  334. package/lib/public/modules/elicitation-form.js +5 -0
  335. package/lib/public/modules/filebrowser.js +20 -1
  336. package/lib/public/modules/generation-stop.js +8 -5
  337. package/lib/public/modules/git-panel.js +3 -1
  338. package/lib/public/modules/history-replay-batch.js +13 -1
  339. package/lib/public/modules/home-debate-live.js +2 -0
  340. package/lib/public/modules/home-debate-planning.js +7 -7
  341. package/lib/public/modules/home-mate-avatar-editor.js +127 -208
  342. package/lib/public/modules/home-mate-chat.js +8 -6
  343. package/lib/public/modules/home-mate-creation.js +73 -1
  344. package/lib/public/modules/home-mate-settings.js +19 -12
  345. package/lib/public/modules/icon-strip-tooltip.js +2 -1
  346. package/lib/public/modules/input.js +88 -10
  347. package/lib/public/modules/issues-render.js +3 -2
  348. package/lib/public/modules/knowledge-db-workbench.js +4 -4
  349. package/lib/public/modules/markdown.js +6 -34
  350. package/lib/public/modules/mate-avatar-catalog.js +97 -0
  351. package/lib/public/modules/mate-knowledge-workbench.js +1 -1
  352. package/lib/public/modules/mate-management.js +40 -7
  353. package/lib/public/modules/mcp-connection-view.js +31 -13
  354. package/lib/public/modules/mcp-discovery-view.js +31 -0
  355. package/lib/public/modules/mcp-ui.js +23 -4
  356. package/lib/public/modules/mention.js +3 -0
  357. package/lib/public/modules/message-delivery.js +20 -2
  358. package/lib/public/modules/model-picker.js +2 -0
  359. package/lib/public/modules/pane-activation.js +214 -0
  360. package/lib/public/modules/pane-binding.js +82 -0
  361. package/lib/public/modules/pane-bridge.js +7 -4
  362. package/lib/public/modules/pane-browser-bridge.js +22 -0
  363. package/lib/public/modules/pane-file-bridge.js +4 -0
  364. package/lib/public/modules/pane-issue-bridge.js +4 -1
  365. package/lib/public/modules/passkey-browser.js +69 -0
  366. package/lib/public/modules/passkey-server-settings.js +57 -0
  367. package/lib/public/modules/pending-message-queue.js +1 -0
  368. package/lib/public/modules/permission-control.js +5 -4
  369. package/lib/public/modules/personal-settings-dialog.js +7 -1
  370. package/lib/public/modules/product-review.js +26 -0
  371. package/lib/public/modules/profile.js +1 -238
  372. package/lib/public/modules/project-access-recovery.js +17 -0
  373. package/lib/public/modules/project-admin-overview.js +21 -0
  374. package/lib/public/modules/project-chat-identity.js +13 -4
  375. package/lib/public/modules/project-logs-render.js +6 -2
  376. package/lib/public/modules/project-mate-navigation.js +144 -22
  377. package/lib/public/modules/rewind.js +5 -0
  378. package/lib/public/modules/scheduled-tasks.js +2 -0
  379. package/lib/public/modules/scheduler.js +2 -0
  380. package/lib/public/modules/search-clay-chat.js +5 -440
  381. package/lib/public/modules/server-settings-controls.js +10 -0
  382. package/lib/public/modules/server-settings.js +7 -2
  383. package/lib/public/modules/session-actions.js +5 -2
  384. package/lib/public/modules/session-context-menu.js +5 -0
  385. package/lib/public/modules/session-create-form.js +10 -10
  386. package/lib/public/modules/session-folder-layout.js +1 -1
  387. package/lib/public/modules/session-folder-view-menu.js +9 -0
  388. package/lib/public/modules/session-github.js +85 -14
  389. package/lib/public/modules/session-rich-drafts.js +21 -0
  390. package/lib/public/modules/session-switch-defer.js +67 -0
  391. package/lib/public/modules/session-work-primary.js +51 -0
  392. package/lib/public/modules/settings-defaults.js +27 -28
  393. package/lib/public/modules/shared-browser-settings.js +112 -0
  394. package/lib/public/modules/shared-browser-tabs.js +13 -3
  395. package/lib/public/modules/shared-browser.js +29 -6
  396. package/lib/public/modules/sidebar-mobile.js +4 -3
  397. package/lib/public/modules/sidebar-projects.js +1 -0
  398. package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
  399. package/lib/public/modules/sidebar-sessions.js +1 -0
  400. package/lib/public/modules/split-group-restore.js +68 -0
  401. package/lib/public/modules/split-pair-ui.js +1 -0
  402. package/lib/public/modules/split-pane-reconciler.js +15 -0
  403. package/lib/public/modules/split-pane-renderer.js +87 -6
  404. package/lib/public/modules/split-session-boundary.js +1 -1
  405. package/lib/public/modules/split-view.js +60 -68
  406. package/lib/public/modules/sticky-note-markdown.js +72 -6
  407. package/lib/public/modules/sticky-notes-actions.js +30 -0
  408. package/lib/public/modules/sticky-notes-browser.js +9 -2
  409. package/lib/public/modules/sticky-notes-card.js +23 -7
  410. package/lib/public/modules/sticky-notes-checklist.js +116 -0
  411. package/lib/public/modules/sticky-notes-editor.js +108 -44
  412. package/lib/public/modules/sticky-notes-shared.js +50 -2
  413. package/lib/public/modules/sticky-notes-state.js +66 -0
  414. package/lib/public/modules/sticky-notes.js +34 -51
  415. package/lib/public/modules/stt-controller.js +4 -1
  416. package/lib/public/modules/stt-recording.js +1 -1
  417. package/lib/public/modules/stt.js +7 -2
  418. package/lib/public/modules/terminal.js +9 -0
  419. package/lib/public/modules/theme.js +8 -1
  420. package/lib/public/modules/thinking-lifecycle.js +33 -3
  421. package/lib/public/modules/thinking-view.js +23 -1
  422. package/lib/public/modules/tools.js +60 -11
  423. package/lib/public/modules/tui-grab.js +1 -2
  424. package/lib/public/modules/user-settings-account.js +14 -1
  425. package/lib/public/modules/user-settings-appearance.js +10 -3
  426. package/lib/public/modules/user-settings-editors.js +1 -1
  427. package/lib/public/modules/user-settings-layout.js +11 -2
  428. package/lib/public/modules/user-settings-preferences.js +6 -2
  429. package/lib/public/modules/user-settings-profile.js +12 -2
  430. package/lib/public/modules/user-settings-sessions.js +120 -0
  431. package/lib/public/modules/user-settings.js +6 -2
  432. package/lib/public/modules/vendor-login-browser.js +5 -3
  433. package/lib/public/modules/vendor-login.js +2 -2
  434. package/lib/public/modules/vendor-priority.js +15 -1
  435. package/lib/public/modules/wireframe-workbench.js +5 -2
  436. package/lib/public/modules/you-activity.js +3 -1
  437. package/lib/public/modules/you.js +91 -6
  438. package/lib/public/muse-avatar.svg +4 -0
  439. package/lib/public/style.css +6 -0
  440. package/lib/public/sw.js +3 -1
  441. package/lib/safe-bash-commands.js +3 -45
  442. package/lib/scheduled-task-records.js +3 -1
  443. package/lib/scheduler.js +2 -0
  444. package/lib/sdk-bridge.js +342 -401
  445. package/lib/sdk-foreground-admission.js +16 -0
  446. package/lib/sdk-mcp-descriptors.js +2 -37
  447. package/lib/sdk-message-processor.js +52 -17
  448. package/lib/sdk-quota-snapshot.js +1 -1
  449. package/lib/sdk-response-recovery.js +1 -0
  450. package/lib/sdk-worker.js +2 -677
  451. package/lib/server-account-passkeys.js +186 -0
  452. package/lib/server-account-passwords.js +127 -0
  453. package/lib/server-account-security.js +53 -0
  454. package/lib/server-admin.js +63 -16
  455. package/lib/server-appearance-settings.js +13 -1
  456. package/lib/server-auth.js +107 -79
  457. package/lib/server-contextual-clay-settings.js +40 -0
  458. package/lib/server-contextual-mate-sessions.js +70 -0
  459. package/lib/server-dm.js +2 -1
  460. package/lib/server-global-ws.js +10 -20
  461. package/lib/server-home-chat-events.js +18 -4
  462. package/lib/server-home-chat.js +22 -20
  463. package/lib/server-home-clay-entry.js +23 -4
  464. package/lib/server-home-clay-session-links.js +29 -9
  465. package/lib/server-home-mate-creation.js +1 -0
  466. package/lib/server-home-mcp-consent.js +14 -0
  467. package/lib/server-mates.js +25 -62
  468. package/lib/server-owner-ui.js +118 -0
  469. package/lib/server-path-access.js +38 -0
  470. package/lib/server-project-removal.js +22 -0
  471. package/lib/server-settings.js +8 -2
  472. package/lib/server.js +165 -43
  473. package/lib/session-config-transition.js +45 -0
  474. package/lib/session-folders.js +7 -2
  475. package/lib/session-fork-history.js +21 -0
  476. package/lib/session-github.js +9 -2
  477. package/lib/session-hygiene.js +3 -35
  478. package/lib/session-permission-mode.js +4 -3
  479. package/lib/session-skill-scope.js +11 -0
  480. package/lib/session-visibility.js +5 -2
  481. package/lib/session-work-primary.js +50 -0
  482. package/lib/sessions.js +64 -99
  483. package/lib/shared-browser-cookie-sync.js +32 -0
  484. package/lib/shared-browser-cookies.js +79 -0
  485. package/lib/shared-browser-runtime.js +25 -9
  486. package/lib/shared-browser-storage-sync.js +43 -0
  487. package/lib/shared-browser-storage.js +101 -0
  488. package/lib/shared-browser-tools.js +2 -1
  489. package/lib/shared-browser-worker.js +46 -10
  490. package/lib/terminal-manager.js +65 -6
  491. package/lib/tool-llm.js +1 -1
  492. package/lib/tui-transcript-index.js +1 -132
  493. package/lib/user-knowledge-service.js +23 -1
  494. package/lib/users-auth.js +38 -3
  495. package/lib/users-contextual-clay-preferences.js +31 -0
  496. package/lib/users-create.js +97 -0
  497. package/lib/users-permissions.js +2 -8
  498. package/lib/users-server-pin.js +37 -0
  499. package/lib/users.js +18 -84
  500. package/lib/vendor-login-browser.js +1 -11
  501. package/lib/workspace-assignment-service.js +25 -0
  502. package/lib/workspace-query-access.js +4 -1
  503. package/lib/workspace-query-mcp-server.js +1 -1
  504. package/lib/workspace-query-service.js +13 -2
  505. package/lib/ws-request.js +1 -0
  506. package/lib/ws-schema.js +18 -2
  507. package/lib/yoke/acp-agent-profiles.js +7 -5
  508. package/lib/yoke/adapters/antigravity.js +3 -14
  509. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  510. package/lib/yoke/adapters/claude.js +54 -50
  511. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  512. package/lib/yoke/adapters/codex.js +53 -111
  513. package/lib/yoke/adapters/kiro.js +3 -1
  514. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  515. package/lib/yoke/adapters/muse.js +122 -0
  516. package/lib/yoke/auth-events.js +17 -0
  517. package/lib/yoke/claude-hook-installer.js +271 -0
  518. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  519. package/lib/yoke/claude-maintenance.js +55 -0
  520. package/lib/yoke/claude-permission-patterns.js +53 -0
  521. package/lib/yoke/claude-response-recovery.js +155 -0
  522. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  523. package/lib/yoke/claude-worker-startup.js +28 -0
  524. package/lib/yoke/clay-skill-install.js +33 -0
  525. package/lib/yoke/cli-sessions.js +300 -0
  526. package/lib/yoke/codex-app-server.js +7 -12
  527. package/lib/yoke/codex-idle-recovery.js +81 -1
  528. package/lib/yoke/codex-recovery-admission.js +164 -0
  529. package/lib/yoke/configuration.js +13 -0
  530. package/lib/yoke/discovery.js +70 -0
  531. package/lib/yoke/errors.js +8 -0
  532. package/lib/yoke/host-environment.js +7 -0
  533. package/lib/yoke/index.js +9 -51
  534. package/lib/yoke/interface.js +116 -0
  535. package/lib/yoke/kiro-acp-server.js +5 -5
  536. package/lib/yoke/legacy-sessions.js +89 -0
  537. package/lib/yoke/login-protocol.js +25 -0
  538. package/lib/yoke/maintenance.js +12 -0
  539. package/lib/yoke/mcp-proxy.js +32 -0
  540. package/lib/yoke/mcp-source-adapters.js +91 -0
  541. package/lib/yoke/mcp-source-context.js +42 -0
  542. package/lib/yoke/mcp-source-discovery.js +169 -0
  543. package/lib/yoke/mcp-source-plugins.js +68 -0
  544. package/lib/yoke/mcp-source-restrictions.js +47 -0
  545. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  546. package/lib/yoke/model-preferences.js +6 -0
  547. package/lib/yoke/muse-artifacts.js +36 -0
  548. package/lib/yoke/muse-controls.js +50 -0
  549. package/lib/yoke/muse-input.js +64 -0
  550. package/lib/yoke/muse-items.js +157 -0
  551. package/lib/yoke/muse-policy.js +52 -0
  552. package/lib/yoke/muse-query.js +428 -0
  553. package/lib/yoke/muse-runtime.js +211 -0
  554. package/lib/yoke/muse-services.js +79 -0
  555. package/lib/yoke/muse-skills.js +79 -0
  556. package/lib/yoke/muse-turns.js +71 -0
  557. package/lib/yoke/options/acp.js +2 -0
  558. package/lib/yoke/options/antigravity.js +2 -0
  559. package/lib/yoke/options/claude.js +21 -0
  560. package/lib/yoke/options/codex-defaults.js +29 -0
  561. package/lib/yoke/options/codex-settings.js +21 -0
  562. package/lib/yoke/options/codex.js +6 -0
  563. package/lib/yoke/options/kiro-defaults.js +22 -0
  564. package/lib/yoke/options/kiro.js +5 -0
  565. package/lib/yoke/options/muse.js +5 -0
  566. package/lib/yoke/provider-contract.js +5 -0
  567. package/lib/yoke/providers/antigravity-executable.js +8 -0
  568. package/lib/yoke/providers/claude-executable.js +40 -0
  569. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  570. package/lib/yoke/providers/claude-process.js +97 -0
  571. package/lib/yoke/providers/claude-provision.js +75 -0
  572. package/lib/yoke/providers/codex-errors.js +8 -0
  573. package/lib/yoke/providers/muse-executable.js +17 -0
  574. package/lib/yoke/provisioning.js +6 -0
  575. package/lib/yoke/query-options.js +10 -0
  576. package/lib/yoke/response-recovery.js +41 -0
  577. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  578. package/lib/yoke/sdk-server-factory.js +7 -0
  579. package/lib/yoke/session-history.js +8 -0
  580. package/lib/yoke/session-tool-transport.js +34 -13
  581. package/lib/yoke/settings.js +23 -0
  582. package/lib/yoke/source-locations.js +4 -0
  583. package/lib/yoke/title-query.js +18 -7
  584. package/lib/yoke/tui-transcript-index.js +132 -0
  585. package/lib/yoke/usage.js +48 -0
  586. package/lib/yoke/user-input.js +13 -0
  587. package/lib/yoke/vendor-registry.js +81 -1
  588. package/package.json +11 -4
@@ -66,71 +66,54 @@ function attachAuth(ctx) {
66
66
  // --- Multi-user auth tokens (persisted to disk) ---
67
67
  var TOKENS_FILE = path.join(CONFIG_DIR, _isDevMode ? "auth-tokens-dev.json" : "auth-tokens.json");
68
68
  var MULTI_USER_COOKIE = _isDevMode ? "relay_auth_user_dev" : "relay_auth_user";
69
- var multiUserTokens = {};
70
-
71
- function loadTokens() {
72
- try {
73
- var raw = fs.readFileSync(TOKENS_FILE, "utf8");
74
- var data = JSON.parse(raw);
75
- if (data && typeof data === "object") {
76
- multiUserTokens = data;
77
- }
78
- } catch (e) {
79
- multiUserTokens = {};
80
- }
69
+ var accountPolicy = require('./account-auth-policy').attachPolicy(users);
70
+ var transport = require('./account-auth-transport').attachTransport({ users: users, tlsOptions: tlsOptions });
71
+ var sessionStore = require('./account-session-store').attachSessionStore({
72
+ file: TOKENS_FILE, managed: accountPolicy.available, clientAddress: transport.clientAddress,
73
+ });
74
+ var throttle = require('./account-auth-throttle').attachThrottle({
75
+ file: path.join(CONFIG_DIR, _isDevMode ? 'auth-attempts-dev.json' : 'auth-attempts.json'), clientAddress: transport.clientAddress,
76
+ });
77
+ function sessionToken(req) { return parseCookies(req)[MULTI_USER_COOKIE]; }
78
+ function createMultiUserSession(userId, credential, passkeyId, secure, req) {
79
+ var created = sessionStore.create(userId, credential, passkeyId, req, req && sessionToken(req));
80
+ var age = created.entry.expiresAt ? Math.max(0, Math.floor((created.entry.expiresAt - Date.now()) / 1000)) : 31536000;
81
+ var cookie = MULTI_USER_COOKIE + '=' + created.token + '; Path=/; HttpOnly; SameSite=Strict; Max-Age=' + age +
82
+ (tlsOptions || secure || req && transport.info(req).secure ? '; Secure' : '');
83
+ var rememberedCookie = rememberedAccounts.remember(userId, req);
84
+ return { token: created.token, cookie: cookie, cookies: rememberedCookie ? [cookie, rememberedCookie] : [cookie] };
81
85
  }
82
-
83
- function saveTokens() {
84
- try {
85
- fs.mkdirSync(path.dirname(TOKENS_FILE), { recursive: true });
86
- var tmpPath = TOKENS_FILE + ".tmp";
87
- fs.writeFileSync(tmpPath, JSON.stringify(multiUserTokens));
88
- fs.renameSync(tmpPath, TOKENS_FILE);
89
- } catch (e) {}
86
+ function validSessionUser(record) {
87
+ var user = record && users.findUserById(record.userId);
88
+ if (!user) return null;
89
+ if (record.passkeyId && (!require('./account-passkey-policy').configured(users.loadUsers()) ||
90
+ !(user.passkeys || []).some(function (key) { return key.id === record.passkeyId; }))) return null;
91
+ if (accountPolicy.requiresPassword(user) && (!user.passwordHash || user.mustChangePin ||
92
+ record.credentialVersion !== require('./account-session-store').digest(user.passwordHash))) return null;
93
+ return user;
90
94
  }
91
-
92
- loadTokens();
93
-
94
- function createMultiUserSession(userId) {
95
- var token = users.generateUserAuthToken(userId);
96
- multiUserTokens[token] = userId;
97
- saveTokens();
98
- var cookie = MULTI_USER_COOKIE + "=" + token + "; Path=/; HttpOnly; SameSite=Strict; Max-Age=31536000" + (tlsOptions ? "; Secure" : "");
99
- return { token: token, cookie: cookie };
100
- }
101
-
102
95
  function getMultiUserFromReq(req) {
103
- var cookies = parseCookies(req);
104
- var token = cookies[MULTI_USER_COOKIE];
105
- if (token) {
106
- var userId = multiUserTokens[token];
107
- if (userId) {
108
- var user = users.findUserById(userId);
109
- if (user) return user;
110
- }
96
+ if (accountPolicy.enabled() && !transport.allows(req, false)) return null;
97
+ var token = sessionToken(req);
98
+ var record = sessionStore.get(token, false);
99
+ var user = validSessionUser(record);
100
+ if (user) {
101
+ if (!req.claySessionPassive) sessionStore.get(token, true, req);
102
+ return user;
111
103
  }
112
- // Solo auto-login: exactly one user with no PIN => frictionless access, no
113
- // login wall. Mirrors the old single-user onramp once single-user mode is
114
- // absorbed into multi-user. Disabled the moment a PIN is set or a second
115
- // user is added (then the normal token/login flow applies).
116
- var solo = users.getSoloNoPinUser();
117
- if (solo) return solo;
118
- return null;
104
+ return users.getSoloNoPinUser() || null;
119
105
  }
120
-
121
- function isMultiUserAuthed(req) {
122
- return !!getMultiUserFromReq(req);
106
+ function touchSession(req) {
107
+ if (getMultiUserFromReq(req)) sessionStore.get(sessionToken(req), true, req);
123
108
  }
124
-
125
- function revokeUserTokens(userId) {
126
- var changed = false;
127
- for (var token in multiUserTokens) {
128
- if (multiUserTokens[token] === userId) {
129
- delete multiUserTokens[token];
130
- changed = true;
131
- }
109
+ function isMultiUserAuthed(req) { return !!getMultiUserFromReq(req); }
110
+ function revokeUserTokens(userId) { sessionStore.revokeUser(userId); }
111
+ function allowAttempt(req, res, username) {
112
+ try { throttle.consume(req, username); return true; }
113
+ catch (error) {
114
+ res.writeHead(error.status || 503, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
115
+ res.end(JSON.stringify({ error: error.message })); return false;
132
116
  }
133
- if (changed) saveTokens();
134
117
  }
135
118
 
136
119
  // --- PIN rate limiting (per-instance state) ---
@@ -163,7 +146,7 @@ function attachAuth(ctx) {
163
146
  var recovery = null;
164
147
 
165
148
  function setRecovery(urlPath, password) {
166
- recovery = { urlPath: urlPath, password: password };
149
+ recovery = { urlPath: urlPath, password: password, until: Date.now() + 15 * 60000 };
167
150
  }
168
151
 
169
152
  function clearRecovery() {
@@ -246,14 +229,11 @@ function attachAuth(ctx) {
246
229
  // --- Auth page selection ---
247
230
  var pinPage = pages.pinPageHtml();
248
231
  var adminSetupPage = pages.adminSetupPageHtml();
249
- var loginPage = pages.multiUserLoginPageHtml();
250
- var smtpLoginPage = pages.smtpLoginPageHtml();
251
232
 
252
233
  function getAuthPage() {
253
234
  if (!users.isMultiUser()) return pinPage;
254
235
  if (!users.hasAdmin()) return adminSetupPage;
255
- if (smtp.isEmailLoginEnabled()) return smtpLoginPage;
256
- return loginPage;
236
+ return require('./account-login-page').render({ password: accountPolicy.enabled(), email: !accountPolicy.enabled() && smtp.isEmailLoginEnabled() });
257
237
  }
258
238
 
259
239
  function isRequestAuthed(req) {
@@ -268,8 +248,22 @@ function attachAuth(ctx) {
268
248
  // --- Route handler ---
269
249
 
270
250
  function handleRequest(req, res, fullUrl) {
251
+ if (require('./account-login-page').handleAsset(req, res, fullUrl)) return true;
252
+ if (accountPolicy.enabled() && transport.info(req).secure && typeof res.setHeader === 'function') res.setHeader('Strict-Transport-Security', 'max-age=31536000');
253
+ if ((accountPolicy.enabled() || fullUrl === '/api/account-auth-policy' && req.method === 'PUT') && /^(?:\/auth\/(?!passkey-browser\.js)|\/api\/(?:account-auth-policy|passkey-policy|passkeys|account-sessions|account-transport|user\/pin|admin\/users|profile)|\/recover\/)/.test(fullUrl) &&
254
+ !transport.allows(req, ['GET', 'HEAD', 'OPTIONS'].indexOf(req.method) === -1)) {
255
+ res.writeHead(403, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
256
+ res.end(JSON.stringify({ error: 'Use HTTPS and the same Clay address for account requests. Reverse proxies must be explicitly configured.' })); return true;
257
+ }
258
+ if (rememberedAccounts.handleRequest(req, res, fullUrl)) return true;
259
+ if (accountSecurity.handleRequest(req, res, fullUrl)) return true;
260
+ if (accountPasskeys.handleRequest(req, res, fullUrl)) return true;
261
+ if (accountPasswords.handleRequest(req, res, fullUrl)) return true;
271
262
  // Admin password recovery
272
263
  if (recovery && fullUrl === "/recover/" + recovery.urlPath) {
264
+ if (recovery.until <= Date.now()) {
265
+ recovery = null; res.writeHead(410, { 'Content-Type': 'application/json' }); res.end('{"error":"Recovery expired. Enable a new recovery link from the server terminal."}'); return true;
266
+ }
273
267
  if (req.method === "GET") {
274
268
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
275
269
  res.end(recoveryPageHtml());
@@ -288,6 +282,8 @@ function attachAuth(ctx) {
288
282
  req.on("end", function () {
289
283
  try {
290
284
  var data = JSON.parse(body);
285
+ if (!allowAttempt(req, res, 'admin-recovery')) return;
286
+ if (!recovery || recovery.until <= Date.now()) throw new Error('Recovery expired.');
291
287
  if (data.step === "verify") {
292
288
  if (!data.password || data.password !== recovery.password) {
293
289
  recordPinFailure(ip);
@@ -315,7 +311,9 @@ function attachAuth(ctx) {
315
311
  res.end('{"error":"No admin account found"}');
316
312
  return;
317
313
  }
318
- users.updateUserPin(admin.id, data.pin);
314
+ var reset = users.updateUserPin(admin.id, data.pin);
315
+ if (!reset.ok) throw new Error('Could not reset the administrator account.');
316
+ revokeUserTokens(admin.id);
319
317
  recovery = null;
320
318
  res.writeHead(200, { "Content-Type": "application/json" });
321
319
  res.end('{"ok":true}');
@@ -334,6 +332,11 @@ function attachAuth(ctx) {
334
332
 
335
333
  // Global auth endpoint (single-user PIN)
336
334
  if (req.method === "POST" && req.url === "/auth") {
335
+ if (users.isMultiUser()) {
336
+ res.writeHead(403, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
337
+ res.end(JSON.stringify({ ok: false, error: 'Server PIN sign-in is unavailable. Sign in with your account.' }));
338
+ return true;
339
+ }
337
340
  var ip = req.socket.remoteAddress || "";
338
341
  var remaining = checkPinRateLimit(ip);
339
342
  if (remaining !== null) {
@@ -439,9 +442,9 @@ function attachAuth(ctx) {
439
442
  }
440
443
  }
441
444
  users.clearSetupCode();
442
- var session = createMultiUserSession(result.user.id);
445
+ var session = createMultiUserSession(result.user.id, null, null, false, req);
443
446
  res.writeHead(200, {
444
- "Set-Cookie": session.cookie,
447
+ "Set-Cookie": session.cookies,
445
448
  "Content-Type": "application/json",
446
449
  });
447
450
  res.end(JSON.stringify({ ok: true, user: { id: result.user.id, username: result.user.username, role: result.user.role } }));
@@ -472,6 +475,7 @@ function attachAuth(ctx) {
472
475
  req.on("end", function () {
473
476
  try {
474
477
  var data = JSON.parse(body);
478
+ if (!allowAttempt(req, res, data.username)) return;
475
479
  var user = users.authenticateUser(data.username, data.pin);
476
480
  if (!user) {
477
481
  recordPinFailure(ip);
@@ -481,11 +485,12 @@ function attachAuth(ctx) {
481
485
  return;
482
486
  }
483
487
  clearPinFailures(ip);
484
- var session = createMultiUserSession(user.id);
488
+ throttle.success(req, data.username);
489
+ var session = createMultiUserSession(user.id, null, null, false, req);
485
490
  var loginResp = { ok: true, user: { id: user.id, username: user.username, role: user.role } };
486
491
  if (user.mustChangePin) loginResp.mustChangePin = true;
487
492
  res.writeHead(200, {
488
- "Set-Cookie": session.cookie,
493
+ "Set-Cookie": session.cookies,
489
494
  "Content-Type": "application/json",
490
495
  });
491
496
  res.end(JSON.stringify(loginResp));
@@ -528,6 +533,7 @@ function attachAuth(ctx) {
528
533
  res.end('{"ok":true}');
529
534
  return;
530
535
  }
536
+ if (!allowAttempt(req, res, 'email:' + String(data.email).toLowerCase())) return;
531
537
  var result = smtp.requestOtp(data.email);
532
538
  if (result.error) {
533
539
  res.writeHead(429, { "Content-Type": "application/json" });
@@ -573,6 +579,7 @@ function attachAuth(ctx) {
573
579
  res.end('{"error":"Email and code are required"}');
574
580
  return;
575
581
  }
582
+ if (!allowAttempt(req, res, 'email:' + String(data.email).toLowerCase())) return;
576
583
  var otpResult = smtp.verifyOtp(data.email, data.code);
577
584
  if (!otpResult.valid) {
578
585
  recordPinFailure(ip);
@@ -587,9 +594,9 @@ function attachAuth(ctx) {
587
594
  return;
588
595
  }
589
596
  clearPinFailures(ip);
590
- var session = createMultiUserSession(user.id);
597
+ var session = createMultiUserSession(user.id, null, null, false, req);
591
598
  res.writeHead(200, {
592
- "Set-Cookie": session.cookie,
599
+ "Set-Cookie": session.cookies,
593
600
  "Content-Type": "application/json",
594
601
  });
595
602
  res.end(JSON.stringify({ ok: true, user: { id: user.id, username: user.username, role: user.role } }));
@@ -625,7 +632,7 @@ function attachAuth(ctx) {
625
632
  return;
626
633
  }
627
634
  var result;
628
- if (smtp.isEmailLoginEnabled() && !data.pin) {
635
+ if (smtp.isEmailLoginEnabled() && !data.pin && !accountPasswords.policy.enabled()) {
629
636
  // SMTP mode: username + email required, no PIN
630
637
  if (!data.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
631
638
  res.writeHead(400, { "Content-Type": "application/json" });
@@ -667,9 +674,9 @@ function attachAuth(ctx) {
667
674
  }
668
675
  }
669
676
  users.markInviteUsed(data.inviteCode);
670
- var session = createMultiUserSession(result.user.id);
677
+ var session = createMultiUserSession(result.user.id, null, null, false, req);
671
678
  res.writeHead(200, {
672
- "Set-Cookie": session.cookie,
679
+ "Set-Cookie": session.cookies,
673
680
  "Content-Type": "application/json",
674
681
  });
675
682
  res.end(JSON.stringify({ ok: true, user: { id: result.user.id, username: result.user.username, role: result.user.role } }));
@@ -686,17 +693,16 @@ function attachAuth(ctx) {
686
693
  if (users.isMultiUser()) {
687
694
  var cookies = parseCookies(req);
688
695
  var token = cookies[MULTI_USER_COOKIE];
689
- if (token && multiUserTokens[token]) {
690
- delete multiUserTokens[token];
691
- saveTokens();
696
+ try { sessionStore.revokeToken(token); } catch (error) {
697
+ res.writeHead(503, { 'Content-Type': 'application/json' }); res.end('{"error":"Could not persist sign-out. Please retry."}'); return true;
692
698
  }
693
699
  res.writeHead(200, {
694
- "Set-Cookie": MULTI_USER_COOKIE + "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions ? "; Secure" : ""),
700
+ "Set-Cookie": MULTI_USER_COOKIE + "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions || transport.info(req).secure ? "; Secure" : ""),
695
701
  "Content-Type": "application/json",
696
702
  });
697
703
  } else {
698
704
  res.writeHead(200, {
699
- "Set-Cookie": "relay_auth=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions ? "; Secure" : ""),
705
+ "Set-Cookie": "relay_auth=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0" + (tlsOptions || transport.info(req).secure ? "; Secure" : ""),
700
706
  "Content-Type": "application/json",
701
707
  });
702
708
  }
@@ -722,14 +728,36 @@ function attachAuth(ctx) {
722
728
  return true;
723
729
  }
724
730
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
725
- res.end(smtp.isEmailLoginEnabled() ? pages.smtpInvitePageHtml(inviteCode) : pages.invitePageHtml(inviteCode));
731
+ res.end(smtp.isEmailLoginEnabled() && !accountPasswords.policy.enabled() ? pages.smtpInvitePageHtml(inviteCode) : pages.invitePageHtml(inviteCode));
726
732
  return true;
727
733
  }
728
734
 
729
735
  return false;
730
736
  }
731
737
 
738
+ var accountPasswords = require('./server-account-passwords').attachAccountPasswords({
739
+ users: users, devMode: _isDevMode, tlsOptions: tlsOptions, parseCookies: parseCookies,
740
+ getUser: getMultiUserFromReq, createSession: createMultiUserSession, revokeSessions: revokeUserTokens,
741
+ onPolicyChanged: ctx.onAccountPolicyChanged, throttle: throttle, transport: transport,
742
+ });
743
+ var accountPasskeys = require('./server-account-passkeys').attachAccountPasskeys({
744
+ users: users, devMode: _isDevMode, parseCookies: parseCookies, http: accountPasswords.http,
745
+ getUser: getMultiUserFromReq, createSession: createMultiUserSession,
746
+ sessionToken: sessionToken, clientAddress: transport.clientAddress,
747
+ });
748
+
749
+ var rememberedAccounts = require('./account-remembered').attachRemembered({
750
+ users: users, devMode: _isDevMode, parseCookies: parseCookies, transport: transport,
751
+ file: path.join(CONFIG_DIR, _isDevMode ? 'remembered-accounts-dev.json' : 'remembered-accounts.json'), read: accountPasswords.http.read,
752
+ });
753
+
754
+ var accountSecurity = require('./server-account-security').attachAccountSecurity({
755
+ users: users, getUser: getMultiUserFromReq, sessionToken: sessionToken, sessions: sessionStore,
756
+ validSessionUser: validSessionUser, http: accountPasswords.http, transport: transport,
757
+ });
758
+
732
759
  return {
760
+ touchSession: touchSession,
733
761
  handleRequest: handleRequest,
734
762
  getMultiUserFromReq: getMultiUserFromReq,
735
763
  isRequestAuthed: isRequestAuthed,
@@ -0,0 +1,40 @@
1
+ // Authenticated personal preferences, using the shared users/config persistence.
2
+ function attachContextualClaySettings(ctx) {
3
+ function reply(res, status, data) {
4
+ res.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
5
+ res.end(JSON.stringify(data));
6
+ }
7
+ function identity(req) {
8
+ if (!ctx.isRequestAuthed(req)) return null;
9
+ return ctx.users.isMultiUser() ? ctx.getMultiUserFromReq(req) : { id: 'default' };
10
+ }
11
+ function handleRequest(req, res, url) {
12
+ if (url !== '/api/user/contextual-clay-geometry') return false;
13
+ var user = identity(req);
14
+ if (!user) { reply(res, 401, { error: 'Sign in to manage popover preferences.' }); return true; }
15
+ if (req.method === 'GET') {
16
+ try { reply(res, 200, { geometry: ctx.users.getContextualClayGeometry(user.id) }); }
17
+ catch (error) { reply(res, 500, { error: 'Could not read popover preference.' }); }
18
+ return true;
19
+ }
20
+ if (req.method !== 'PUT') { reply(res, 405, { error: 'Method not allowed.' }); return true; }
21
+ if (req.headers['x-clay-settings'] !== '1' || (req.headers['sec-fetch-site'] && ['same-origin', 'none'].indexOf(req.headers['sec-fetch-site']) < 0)) {
22
+ reply(res, 403, { error: 'Save preferences from Clay.' }); return true;
23
+ }
24
+ var body = ''; var tooLarge = false;
25
+ req.setEncoding('utf8');
26
+ req.on('data', function (chunk) { body += chunk; if (body.length > 1024 && !tooLarge) { tooLarge = true; reply(res, 413, { error: 'Request too large.' }); } });
27
+ req.on('end', function () {
28
+ if (tooLarge) return;
29
+ var live = identity(req);
30
+ if (!live || live.id !== user.id) { reply(res, 401, { error: 'Sign in again.' }); return; }
31
+ try {
32
+ var result = ctx.users.setContextualClayGeometry(live.id, JSON.parse(body));
33
+ reply(res, result.error ? 400 : 200, result);
34
+ } catch (error) { reply(res, 400, { error: 'Could not save popover preference.' }); }
35
+ });
36
+ return true;
37
+ }
38
+ return { handleRequest: handleRequest };
39
+ }
40
+ module.exports = { attachContextualClaySettings: attachContextualClaySettings };
@@ -0,0 +1,70 @@
1
+ // Presentation-only session operations share Home's authoritative permissions,
2
+ // model policy, saved-session projection and session manager. No transcript tap.
3
+ function attachContextualMateSessions(ctx) {
4
+ var receipts = new Map();
5
+ var lifetime = 30 * 60 * 1000;
6
+ function stamp(mate) { return JSON.stringify([mate.id, mate.createdBy || null, mate.createdAt || null, mate.builtinKey || null]); }
7
+ function live(ws, userId, msg, original) {
8
+ if (!ctx.isActorLive(ws, userId)) throw new Error('Your account is no longer available.');
9
+ var found = ctx.findMateProject(userId, msg.mateId, true);
10
+ if (!found || found.mate.archived || found.mate.lifecycleDeletion || found.mate.createdBy && found.mate.createdBy !== userId || stamp(found.mate) !== msg.mateStamp) throw new Error('This Mate is no longer available.');
11
+ var status = found.ctx.getStatus();
12
+ if (!status || !status.isMate || status.mateId !== found.mate.id || userId && status.projectOwnerId !== userId) throw new Error('This private Mate workspace is unavailable.');
13
+ found.contextualManager = found.ctx.getSessionManager();
14
+ found.contextualRevision = JSON.stringify([status.path, status.projectOwnerId, status.mateId, stamp(found.mate)]);
15
+ if (original && (found.ctx !== original.ctx || found.contextualRevision !== original.contextualRevision || found.contextualManager !== original.contextualManager)) throw new Error('This Mate conversation changed.');
16
+ return found;
17
+ }
18
+ function reply(ws, msg, data) { ctx.sendMessage(ws, Object.assign({ type: 'contextual_mate_sessions_result', requestId: msg.requestId, mateId: msg.mateId, mateStamp: msg.mateStamp }, data)); }
19
+ async function perform(ws, userId, msg) {
20
+ try {
21
+ if (typeof msg.requestId !== 'string' || !/^mate-conversations-[a-z0-9-]{36}$/.test(msg.requestId)) throw new Error('Invalid conversation request.');
22
+ var found = live(ws, userId, msg), manager = found.ctx.getSessionManager();
23
+ if (!manager) throw new Error('Conversation history is unavailable.');
24
+ if (msg.type === 'home_mate_sessions_list') {
25
+ var list = ctx.listHomeSessions(found, userId);
26
+ reply(ws, msg, { ok: true, sessions: list.slice(0, 500), truncated: list.length > 500 }); return;
27
+ }
28
+ var session;
29
+ if (msg.type === 'home_mate_session_open') {
30
+ session = ctx.resolveHomeSession(found, userId, msg.sessionId);
31
+ if (!session || typeof msg.sessionOriginId !== 'string' || msg.sessionOriginId !== session.sessionOriginId) throw new Error('This conversation is no longer available.');
32
+ } else {
33
+ var now = Date.now();
34
+ receipts.forEach(function (entry, key) { if (now - entry.at > lifetime) receipts.delete(key); });
35
+ var key = JSON.stringify([userId, msg.mateId, msg.requestId]);
36
+ var receipt = receipts.get(key);
37
+ manager.sessions.forEach(function (candidate) { if (candidate.contextualCreationRequestId === msg.requestId && ctx.ownsSession(candidate, userId)) session = candidate; });
38
+ if (session && session.contextualCreationMateStamp !== msg.mateStamp) throw new Error('This request belongs to a replaced Mate.');
39
+ if (receipt && (!session || receipt.origin !== session.sessionOriginId || receipt.stamp !== msg.mateStamp)) throw new Error('The previously created conversation is no longer available.');
40
+ if (!session && msg.lookupOnly) throw new Error('Creation was not confirmed. Start a new chat explicitly if you still want one.');
41
+ if (!session) {
42
+ if (receipts.size >= 1024) throw new Error('Please try starting a conversation later.');
43
+ var resolved = await ctx.homeModels.resolveMateModel(ws, found, userId);
44
+ found = live(ws, userId, msg, found);
45
+ // Recheck after model resolution: concurrent retries select one exact session.
46
+ manager.sessions.forEach(function (candidate) { if (candidate.contextualCreationRequestId === msg.requestId && ctx.ownsSession(candidate, userId)) session = candidate; });
47
+ receipt = receipts.get(key);
48
+ if (receipt && (!session || receipt.origin !== session.sessionOriginId || receipt.stamp !== msg.mateStamp)) throw new Error('The previously created conversation is no longer available.');
49
+ if (session && session.contextualCreationMateStamp !== msg.mateStamp) throw new Error('This request belongs to a replaced Mate.');
50
+ if (!session) {
51
+ if (receipts.size >= 1024) throw new Error('Please try starting a conversation later.');
52
+ session = manager.createSessionRaw({ ownerId: userId, vendor: resolved.vendor, model: resolved.model, effort: resolved.effort || null });
53
+ session.contextualCreationRequestId = msg.requestId;
54
+ session.contextualCreationMateStamp = msg.mateStamp;
55
+ manager.saveSessionFile(session);
56
+ }
57
+ }
58
+ if (!ctx.ownsSession(session, userId)) throw new Error('This conversation is no longer available.');
59
+ receipts.set(key, { at: now, origin: session.sessionOriginId, stamp: msg.mateStamp });
60
+ }
61
+ live(ws, userId, msg, found);
62
+ reply(ws, msg, { ok: true, sessionId: session.localId, sessionOriginId: session.sessionOriginId });
63
+ } catch (error) { reply(ws, msg, { ok: false, error: error.message || 'Conversation unavailable.' }); }
64
+ }
65
+ return { handle: function (ws, userId, msg) {
66
+ if (msg.presentation !== 'contextual' || !/^home_mate_(sessions_list|session_open|new_session)$/.test(msg.type)) return false;
67
+ perform(ws, userId, msg); return true;
68
+ } };
69
+ }
70
+ module.exports = { attachContextualMateSessions: attachContextualMateSessions };
package/lib/server-dm.js CHANGED
@@ -49,7 +49,7 @@ function attachDm(ctx) {
49
49
  var mateCtx2 = mates.buildMateCtx(userId);
50
50
  if (mates.isMate(mateCtx2, msg.targetUserId)) {
51
51
  var mate = mates.getMate(mateCtx2, msg.targetUserId);
52
- if (!mate) return true;
52
+ if (!mate || mate.lifecycleDeletion) return true;
53
53
  // Ensure mate project is registered (survives server restarts)
54
54
  var mateSlug2 = "mate-" + mate.id;
55
55
  if (!projects.has(mateSlug2)) {
@@ -69,6 +69,7 @@ function attachDm(ctx) {
69
69
  id: mate.id,
70
70
  displayName: mp.displayName || mate.name || "New Mate",
71
71
  username: mate.id,
72
+ avatarCatalogId: mp.avatarCatalogId || "",
72
73
  avatarStyle: mp.avatarStyle || "imprint",
73
74
  avatarSeed: mp.avatarSeed || mate.id,
74
75
  avatarColor: mp.avatarColor || "#5857fc",
@@ -63,14 +63,6 @@ function attachGlobalWs(opts) {
63
63
  if (msg.type === "browse_dir") {
64
64
  var rawPath = (msg.path || "").replace(/^~/, config.REAL_HOME);
65
65
  var absTarget = path.resolve(rawPath);
66
- // Multi-user mode: non-admins can only browse their home directory.
67
- if (osUsers && ws._clayUser && ws._clayUser.role !== "admin") {
68
- var browseHome = ws._clayUser.linuxUser ? "/home/" + ws._clayUser.linuxUser : null;
69
- if (!browseHome || (absTarget !== browseHome && (absTarget + "/").indexOf(browseHome + "/") !== 0)) {
70
- sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: [], error: "Access restricted to your home directory" });
71
- return;
72
- }
73
- }
74
66
  var parentDir, prefix;
75
67
  try {
76
68
  var stat = fs.statSync(absTarget);
@@ -87,12 +79,17 @@ function attachGlobalWs(opts) {
87
79
  parentDir = path.dirname(absTarget);
88
80
  prefix = path.basename(absTarget).toLowerCase();
89
81
  }
82
+ if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, parentDir)) {
83
+ sendTo(ws, { type: "browse_dir_result", entries: [], error: "Directory access is not permitted" });
84
+ return;
85
+ }
90
86
  try {
91
87
  var dirItems = fs.readdirSync(parentDir, { withFileTypes: true });
92
88
  var dirEntries = [];
93
89
  for (var di = 0; di < dirItems.length; di++) {
94
90
  var d = dirItems[di];
95
91
  if (!d.isDirectory()) continue;
92
+ if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, path.join(parentDir, d.name))) continue;
96
93
  if (d.name.charAt(0) === ".") continue;
97
94
  if (IGNORED_DIRS.has(d.name)) continue;
98
95
  if (prefix && !d.name.toLowerCase().startsWith(prefix)) continue;
@@ -110,16 +107,9 @@ function attachGlobalWs(opts) {
110
107
  if (msg.type === "add_project") {
111
108
  var addPath = (msg.path || "").replace(/^~/, config.REAL_HOME);
112
109
  var addAbs = path.resolve(addPath);
113
- if (osUsers && ws._clayUser && ws._clayUser.role !== "admin") {
114
- if (!ws._clayUser.linuxUser) {
115
- sendTo(ws, { type: "add_project_result", ok: false, error: "No Linux user assigned" });
116
- return;
117
- }
118
- var userHome = "/home/" + ws._clayUser.linuxUser;
119
- if (addAbs !== userHome && (addAbs + "/").indexOf(userHome + "/") !== 0) {
120
- sendTo(ws, { type: "add_project_result", ok: false, error: "Path not allowed. You can only add directories under " + userHome });
121
- return;
122
- }
110
+ if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, addAbs)) {
111
+ sendTo(ws, { type: "add_project_result", ok: false, error: "Directory access is not permitted" });
112
+ return;
123
113
  }
124
114
  try {
125
115
  var addStat = fs.statSync(addAbs);
@@ -133,7 +123,7 @@ function attachGlobalWs(opts) {
133
123
  }
134
124
  if (typeof onAddProject === "function") {
135
125
  var result = onAddProject(addAbs, ws._clayUser);
136
- sendTo(ws, { type: "add_project_result", ok: result.ok, slug: result.slug, error: result.error, existing: result.existing });
126
+ sendTo(ws, Object.assign({}, result, { type: "add_project_result" }));
137
127
  } else {
138
128
  sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
139
129
  }
@@ -159,7 +149,7 @@ function attachGlobalWs(opts) {
159
149
  }
160
150
  if (typeof onCreateProject === "function") {
161
151
  var createResult = onCreateProject(createName, ws._clayUser);
162
- sendTo(ws, { type: "add_project_result", ok: createResult.ok, slug: createResult.slug, error: createResult.error });
152
+ sendTo(ws, Object.assign({}, createResult, { type: "add_project_result" }));
163
153
  } else {
164
154
  sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
165
155
  }
@@ -3,7 +3,7 @@
3
3
  function homeDebateQuestions(input) {
4
4
  var source = input && Array.isArray(input.questions) && input.questions[0] ? input.questions[0] : null;
5
5
  if (!source) return [];
6
- var question = { header: source.header || "", question: source.question || "", multiSelect: false, options: [] };
6
+ var question = { header: source.header || "", question: source.question || "", multiSelect: false, allowOther: source.allowOther !== false, options: [] };
7
7
  var options = Array.isArray(source.options) ? source.options.slice(0, 6) : [];
8
8
  for (var i = 0; i < options.length; i++) question.options.push({ label: options[i].label || "Option", description: options[i].description || "" });
9
9
  return [question];
@@ -36,6 +36,7 @@ function findDebateTurn(messages, event) {
36
36
  function debateIdentity(source, fallback) {
37
37
  var prior = fallback || {};
38
38
  return {
39
+ avatarCatalogId: source.avatarCatalogId || prior.avatarCatalogId || "",
39
40
  avatarStyle: source.avatarStyle || prior.avatarStyle || "imprint",
40
41
  avatarSeed: source.avatarSeed || prior.avatarSeed || source.mateId || "mate",
41
42
  avatarColor: source.avatarColor || prior.avatarColor || "",
@@ -112,7 +113,7 @@ function applyAssignmentHistoryEvent(messages, event) {
112
113
  messages.push({ role: "assignment", assignment: assignment });
113
114
  }
114
115
 
115
- function historyToHomeChat(history, debateSetupMode, mateCreationMode) {
116
+ function historyToHomeChat(history, debateSetupMode, mateCreationMode, pendingAskUser) {
116
117
  var messages = [];
117
118
  var pending = "";
118
119
  var interviewMode = debateSetupMode === true || mateCreationMode === true;
@@ -124,6 +125,12 @@ function historyToHomeChat(history, debateSetupMode, mateCreationMode) {
124
125
  for (var i = 0; i < history.length; i++) {
125
126
  var event = history[i];
126
127
  if (!event) continue;
128
+ if (event.type === 'tool_executing' && event.name === 'AskUserQuestion' && ['mcp-import', 'mate-schedule', 'mcp_fallback', 'product-control'].indexOf(event.source) >= 0) {
129
+ flushAssistant();
130
+ var activeConsent = pendingAskUser === undefined || !!(pendingAskUser && pendingAskUser[event.id]);
131
+ messages.push({ role: 'question', flow: event.source === 'mcp-import' ? 'mcp_import' : 'mate_question', toolId: event.id, questions: homeDebateQuestions(event.input), status: activeConsent ? 'pending' : 'expired', error: activeConsent ? '' : 'This question is no longer active. Ask for a new review.' });
132
+ continue;
133
+ }
127
134
  if (event.type === "project_assignment_proposal" || event.type === "project_assignment_status") {
128
135
  flushAssistant();
129
136
  applyAssignmentHistoryEvent(messages, event);
@@ -185,7 +192,7 @@ function historyToHomeChat(history, debateSetupMode, mateCreationMode) {
185
192
  } else if (interviewMode && event.type === "tool_executing" && event.name === "AskUserQuestion" && event.id && event.input) {
186
193
  flushAssistant();
187
194
  messages.push({ role: "question", flow: mateCreationMode === true ? "mate_creation" : "debate", toolId: event.id, questions: homeDebateQuestions(event.input), status: "pending", error: "" });
188
- } else if ((event.type === "ask_user_answered" || event.type === "home_debate_question_expired" || event.type === "home_mate_creation_question_expired") && event.toolId) {
195
+ } else if ((event.type === "ask_user_answered" || event.type === "home_debate_question_expired" || event.type === "home_mate_creation_question_expired" || event.type === "mcp_import_consent_expired" || event.type === "mate_schedule_question_expired") && event.toolId) {
189
196
  for (var k = messages.length - 1; k >= 0; k--) {
190
197
  if (messages[k].role === "question" && messages[k].toolId === event.toolId) {
191
198
  messages[k].status = event.type === "ask_user_answered" ? "answered" : "expired";
@@ -273,7 +280,7 @@ function transformEvent(event, mateId, session, requestId, stableSessionId) {
273
280
  }
274
281
  if (session && session.homeDebatePlanning === true && HOME_DEBATE_EVENT_TYPES[event.type]) {
275
282
  var live = { type: "home_debate_event", eventType: event.type };
276
- var fields = ["turnId", "decisionId", "decision", "toolName", "command", "commandTruncated", "topic", "format", "moderatorId", "moderatorName", "panelists", "mateName", "role", "round", "activity", "delta", "text", "reason", "action", "avatarStyle", "avatarSeed", "avatarColor", "avatarCustom"];
283
+ var fields = ["turnId", "decisionId", "decision", "toolName", "command", "commandTruncated", "topic", "format", "moderatorId", "moderatorName", "panelists", "mateName", "role", "round", "activity", "delta", "text", "reason", "action", "avatarCatalogId", "avatarStyle", "avatarSeed", "avatarColor", "avatarCustom"];
277
284
  for (var fi = 0; fi < fields.length; fi++) if (Object.prototype.hasOwnProperty.call(event, fields[fi])) live[fields[fi]] = event[fields[fi]];
278
285
  if (event.mateId) live.speakerMateId = event.mateId;
279
286
  return Object.assign(live, metadata);
@@ -298,6 +305,13 @@ function transformEvent(event, mateId, session, requestId, stableSessionId) {
298
305
  if (event.type === "debate_proposal_resolved" && event.proposalId) return Object.assign({ type: "home_debate_proposal_resolved", proposalId: event.proposalId, action: event.action || "cancel", error: event.error || "" }, metadata);
299
306
  if (session && session.mateCreationMode === true && event.type === "mate_creation_proposal" && event.proposal) return Object.assign({ type: "home_mate_creation_proposal", proposal: event.proposal }, metadata);
300
307
  if (session && session.mateCreationMode === true && event.type === "mate_creation_proposal_resolved" && event.proposalId) return Object.assign({ type: "home_mate_creation_proposal_resolved", proposalId: event.proposalId, action: event.action || "cancel", createdMateId: event.mateId || null, mateName: event.mateName || null, error: event.error || "" }, metadata);
308
+ if (!(session && (session.debateSetupMode === true || session.mateCreationMode === true)) && event.type === 'tool_executing' && event.name === 'AskUserQuestion' && ['mate-schedule', 'mcp_fallback', 'product-control'].indexOf(event.source) >= 0) return Object.assign({ type: 'home_mate_question', toolId: event.id, questions: homeDebateQuestions(event.input) }, metadata);
309
+ if (session && session.debateSetupMode !== true && session.mateCreationMode !== true && event.type === 'ask_user_answered' && event.toolId && (session.history || []).some(function (item) { return item.id === event.toolId && ['mate-schedule', 'mcp_fallback', 'product-control'].indexOf(item.source) >= 0; })) return Object.assign({ type: 'home_mate_question_resolved', toolId: event.toolId, status: 'answered', answers: event.answers }, metadata);
310
+ if (event.type === 'tool_executing' && event.name === 'AskUserQuestion' && event.source === 'mcp-import') return Object.assign({ type: 'home_mcp_import_question', toolId: event.id, questions: homeDebateQuestions(event.input) }, metadata);
311
+ if (event.type === 'product_control_question_expired') return Object.assign({ type: 'home_mate_question_resolved', toolId: event.toolId, status: 'expired', error: event.error }, metadata);
312
+ if (event.type === 'mate_schedule_question_expired') return Object.assign({ type: 'home_mate_question_resolved', toolId: event.toolId, status: 'expired', error: event.error }, metadata);
313
+ if (event.type === 'mcp_import_consent_expired') return Object.assign({ type: 'home_mcp_import_question_resolved', toolId: event.toolId, status: 'expired', error: event.error }, metadata);
314
+ if (session && event.type === 'ask_user_answered' && event.toolId && (session.history || []).some(function (item) { return item.id === event.toolId && item.source === 'mcp-import'; })) return Object.assign({ type: 'home_mcp_import_question_resolved', toolId: event.toolId, status: 'answered', answers: event.answers }, metadata);
301
315
  if (session && session.debateSetupMode === true && event.type === "tool_executing" && event.name === "AskUserQuestion" && event.id && event.input) {
302
316
  return Object.assign({ type: "home_debate_question", toolId: event.id, questions: homeDebateQuestions(event.input) }, metadata);
303
317
  }