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
@@ -31,7 +31,7 @@ function attachHomeChat(deps) {
31
31
  }
32
32
  if (!mateId && allMates[i].builtinKey === "clay") mate = allMates[i];
33
33
  }
34
- if (!mate) return null;
34
+ if (!mate || mate.lifecycleDeletion) return null;
35
35
  var slug = "mate-" + mate.id;
36
36
  if (!projects.has(slug)) {
37
37
  if (!ensureRegistered) return null;
@@ -123,6 +123,7 @@ function attachHomeChat(deps) {
123
123
  model: sessionString(session.model, 240),
124
124
  createdAt: createdAt,
125
125
  lastActivity: lastActivity,
126
+ sessionOriginId: session.sessionOriginId || null,
126
127
  isProcessing: !!session.isProcessing,
127
128
  sessionRole: hierarchy[session.localId].role,
128
129
  parentSessionId: hierarchy[session.localId].parentSessionId == null ? null : sessionReference(sessionManager.sessions.get(hierarchy[session.localId].parentSessionId)),
@@ -184,6 +185,12 @@ function attachHomeChat(deps) {
184
185
  }
185
186
  });
186
187
  if (!unsubscribe) return;
188
+ var unregisterConsent = null;
189
+ if (openedSession && typeof found.ctx.registerMcpConsentViewer === 'function') {
190
+ try { unregisterConsent = found.ctx.registerMcpConsentViewer(ws, openedSession); } catch (error) {}
191
+ }
192
+ var unsubscribeEvents = unsubscribe;
193
+ unsubscribe = function () { if (unregisterConsent) unregisterConsent(); unsubscribeEvents(); };
187
194
  ws[tapKey] = {
188
195
  unsubscribe: unsubscribe,
189
196
  sessionId: sessionId,
@@ -222,6 +229,7 @@ function attachHomeChat(deps) {
222
229
  var homeDebates = attachHomeDebates({ mates: mates, findMateProject: findMateProject, ownsSession: ownsSession, sessionReference: sessionReference, sendMessage: sendMessage });
223
230
  var homeClaySessionLinks = attachHomeClaySessionLinks({
224
231
  projects: projects,
232
+ findMateProject: findMateProject, ownsSession: ownsSession, isActorLive: isActorLive,
225
233
  workspaceQueryService: deps.workspaceQueryService,
226
234
  projectLogsService: deps.projectLogsService,
227
235
  sendMessage: sendMessage,
@@ -238,7 +246,7 @@ function attachHomeChat(deps) {
238
246
  requestId: requestId || null,
239
247
  model: session.model || null,
240
248
  vendor: session.vendor || null,
241
- messages: historyToHomeChat(session.history || [], session.debateSetupMode === true, session.mateCreationMode === true),
249
+ messages: historyToHomeChat(session.history || [], session.debateSetupMode === true, session.mateCreationMode === true, session.pendingAskUser),
242
250
  isProcessing: session.isProcessing === true,
243
251
  };
244
252
  if (session.homeClayEntryMode === "search") {
@@ -293,7 +301,10 @@ function attachHomeChat(deps) {
293
301
  homeModels: homeModels, isActorLive: isActorLive, persistActiveSession: persistActiveSession,
294
302
  });
295
303
  var homeMateCreation = attachHomeMateCreation({ findMateProject: findMateProject, resolveHomeSession: resolveHomeSession, sessionReference: sessionReference, setupTap: setupTap, sendHistory: sendHistory, sendSessionList: sendSessionList, sendError: sendError, sendModelError: sendModelError, homeModels: homeModels, isActorLive: isActorLive, persistActiveSession: persistActiveSession });
296
- var homeClayEntry = attachHomeClayEntry({ findMateProject: findMateProject, ownsSession: ownsSession, sessionReference: sessionReference, setupSearchTap: setupSearchTap, sendHistory: sendHistory, sendSessionList: sendSessionList, sendError: sendError, sendModelError: sendModelError, homeModels: homeModels, isActorLive: isActorLive });
304
+ var homeMcpConsent = require('./server-home-mcp-consent').attachHomeMcpConsent({ findMateProject: findMateProject, resolveHomeSession: resolveHomeSession, messageTap: messageTap, isActorLive: isActorLive, sendError: sendError });
305
+ var homeClayEntry = attachHomeClayEntry({ findMateProject: findMateProject, ownsSession: ownsSession, sessionReference: sessionReference, setupSearchTap: setupSearchTap, sendHistory: sendHistory, sendSessionList: sendSessionList, sendError: sendError, sendModelError: sendModelError, sendMessage: sendMessage, homeModels: homeModels, isActorLive: isActorLive });
306
+
307
+ var contextualSessions = require('./server-contextual-mate-sessions').attachContextualMateSessions({ findMateProject: findMateProject, ownsSession: ownsSession, resolveHomeSession: resolveHomeSession, listHomeSessions: listHomeSessions, isActorLive: isActorLive, homeModels: homeModels, sendMessage: sendMessage });
297
308
 
298
309
  async function openExactSession(ws, found, userId, selected, msg) {
299
310
  await ensureSessionModel(ws, found, userId, selected, null);
@@ -397,20 +408,8 @@ function attachHomeChat(deps) {
397
408
  historyError.sessionId = sessionReference(activeSession);
398
409
  throw historyError;
399
410
  }
400
- sessionManager.sendAndRecord(activeSession, { type: "user_message", text: text });
401
411
  try {
402
- if (!activeSession.isProcessing) {
403
- activeSession.isProcessing = true;
404
- activeSession.sentToolResults = {};
405
- if (typeof options.onRecorded === "function") options.onRecorded(activeSession);
406
- if (!activeSession.queryInstance && (!activeSession.worker || activeSession.messageQueue !== "worker")) {
407
- sdk.startQuery(activeSession, options.queryText || text, null, null);
408
- } else {
409
- sdk.pushMessage(activeSession, options.queryText || text, null);
410
- }
411
- } else {
412
- sdk.pushMessage(activeSession, options.queryText || text, null);
413
- }
412
+ await require('./mate-message-delivery').deliver({ sm: sessionManager, sdk: sdk }, activeSession, text, options);
414
413
  } catch (error) {
415
414
  error.sessionId = sessionReference(activeSession);
416
415
  throw error;
@@ -418,7 +417,7 @@ function attachHomeChat(deps) {
418
417
  return sessionReferenceValue;
419
418
  }
420
419
 
421
- function handleMessage(ws, msg) {
420
+ function handleMessage(ws, msg, routedProjectSlug) {
422
421
  if (!msg || typeof msg.type !== "string") return false;
423
422
  if (msg.type === "home_mate_stop" || msg.type === "home_mate_permission_response") {
424
423
  var controlUserId = ws._clayUser ? ws._clayUser.id : null;
@@ -449,10 +448,12 @@ function attachHomeChat(deps) {
449
448
  }
450
449
  return true;
451
450
  }
452
- if (msg.type !== "issue_reference_resolve" && msg.type !== "home_debates_list" && msg.type !== "home_clay_ask" && msg.type !== "home_clay_session_resolve" && msg.type !== "home_clay_log_resolve" && msg.type !== "home_mate_present" && msg.type !== "home_mate_open" && msg.type !== "home_mate_sessions_list" && msg.type !== "home_mate_session_open" && msg.type !== "home_mate_send" && msg.type !== "home_mate_new_session" && msg.type !== "home_mate_debate_plan" && msg.type !== "home_debate_proposal_response" && msg.type !== "home_debate_question_response" && msg.type !== "home_debate_control" && msg.type !== "home_mate_creation_plan" && msg.type !== "home_mate_creation_question_response" && msg.type !== "home_mate_creation_proposal_response" && msg.type !== "home_mate_close" && msg.type !== "home_mate_memory_list" && msg.type !== "home_mate_knowledge_list" && msg.type !== "home_mate_models_get" && msg.type !== "home_mate_model_set") {
451
+ if (msg.type !== "issue_reference_resolve" && msg.type !== "home_debates_list" && msg.type !== "home_clay_ask" && msg.type !== "home_clay_session_resolve" && msg.type !== "home_clay_log_resolve" && msg.type !== "home_mate_present" && msg.type !== "home_mate_open" && msg.type !== "home_mate_sessions_list" && msg.type !== "home_mate_session_open" && msg.type !== "home_mate_send" && msg.type !== "home_mate_new_session" && msg.type !== "home_mate_debate_plan" && msg.type !== "home_debate_proposal_response" && msg.type !== "home_mcp_import_response" && msg.type !== "home_mate_question_response" && msg.type !== "home_debate_question_response" && msg.type !== "home_debate_control" && msg.type !== "home_mate_creation_plan" && msg.type !== "home_mate_creation_question_response" && msg.type !== "home_mate_creation_proposal_response" && msg.type !== "home_mate_close" && msg.type !== "home_mate_memory_list" && msg.type !== "home_mate_knowledge_list" && msg.type !== "home_mate_models_get" && msg.type !== "home_mate_model_set") {
453
452
  return false;
454
453
  }
455
454
 
455
+ if (contextualSessions.handle(ws, ws._clayUser ? ws._clayUser.id : null, msg)) return true;
456
+
456
457
  if (msg.type === "home_mate_present") {
457
458
  ws._homeChatPresented = msg.visible === true;
458
459
  return true;
@@ -474,11 +475,12 @@ function attachHomeChat(deps) {
474
475
  return true;
475
476
  }
476
477
 
478
+ if (msg.type === "home_mcp_import_response" || msg.type === "home_mate_question_response") { homeMcpConsent.respond(ws, userId, msg); return true; }
477
479
  if (msg.type === "issue_reference_resolve") { resolveIssueLink(ws, msg); return true; }
478
480
  if (homeDebates.handle(ws, userId, msg)) return true;
479
481
  if (msg.type === "home_clay_ask") { homeClayEntry.start(ws, userId, msg); return true; }
480
- if (msg.type === "home_clay_session_resolve") { homeClaySessionLinks.resolve(ws, msg); return true; }
481
- if (msg.type === "home_clay_log_resolve") { homeClaySessionLinks.resolveLog(ws, msg); return true; }
482
+ if (msg.type === "home_clay_session_resolve") { homeClaySessionLinks.resolve(ws, msg, routedProjectSlug); return true; }
483
+ if (msg.type === "home_clay_log_resolve") { homeClaySessionLinks.resolveLog(ws, msg, routedProjectSlug); return true; }
482
484
 
483
485
  if (msg.type === "home_mate_debate_plan") {
484
486
  homeDebate.start(ws, userId, msg);
@@ -15,10 +15,12 @@ function attachHomeClayEntry(ctx) {
15
15
  }
16
16
 
17
17
  async function start(ws, userId, msg) {
18
+ var contextual = msg.presentation === 'contextual';
18
19
  var text = typeof msg.text === "string" ? msg.text.replace(/[\u0000-\u001f\u007f]/g, " ").trim().slice(0, 12000) : "";
19
20
  var requestId = typeof msg.requestId === "string" ? msg.requestId.slice(0, 240) : null;
21
+ if (ctx.isActorLive && !ctx.isActorLive(ws, userId)) { ctx.sendError(ws, null, 'Your account is no longer available.', requestId, null, 'actor_unavailable'); return; }
20
22
  var found = ctx.findMateProject(userId, null, true);
21
- if (!found || found.mate.builtinKey !== "clay") {
23
+ if (!found || found.mate.builtinKey !== "clay" || found.mate.archived || ctx.isActorLive && !ctx.isActorLive(ws, userId)) {
22
24
  ctx.sendError(ws, null, "Clay is not available.", requestId, null, "mate_unavailable");
23
25
  return;
24
26
  }
@@ -27,26 +29,43 @@ function attachHomeClayEntry(ctx) {
27
29
  return;
28
30
  }
29
31
  var manager = found.ctx.getSessionManager();
32
+ var mateStamp = JSON.stringify([found.mate.id, found.mate.createdAt || null, found.mate.createdBy || null]);
30
33
  if (!manager || typeof manager.sendAndRecord !== "function") {
31
34
  ctx.sendError(ws, found.mate.id, "Conversation history is unavailable.", requestId, null, "session_unavailable");
32
35
  return;
33
36
  }
34
37
  var existing = findExisting(manager, userId, requestId);
35
38
  if (existing) {
39
+ if (contextual) {
40
+ if (existing.homeClayEntryMode !== 'contextual' || existing.homeClayEntryText !== text || msg.sessionOriginId && msg.sessionOriginId !== existing.sessionOriginId) { ctx.sendError(ws, found.mate.id, 'This request belongs to a different conversation.', requestId, null, 'request_mismatch'); return; }
41
+ ctx.sendMessage(ws, { type: 'home_clay_contextual_session', requestId: requestId, mateId: found.mate.id, sessionId: existing.localId, sessionOriginId: existing.sessionOriginId }); return;
42
+ }
36
43
  ctx.setupSearchTap(ws, found, existing.localId, requestId);
37
44
  ctx.sendHistory(ws, found, existing, requestId);
38
45
  ctx.sendSessionList(ws, found, userId);
39
46
  return;
40
47
  }
48
+ if (contextual && msg.sessionOriginId) { ctx.sendError(ws, found.mate.id, 'This new conversation is no longer available. Start a new Ask.', requestId, null, 'session_unavailable'); return; }
41
49
  var session = null;
42
50
  try {
43
51
  var resolved = await ctx.homeModels.resolveMateModel(ws, found, userId);
44
52
  if (ctx.isActorLive && !ctx.isActorLive(ws, userId)) throw new Error("Your account is no longer available.");
45
53
  var liveFound = ctx.findMateProject(userId, null, true);
46
- if (!liveFound || liveFound.ctx !== found.ctx || !liveFound.mate || liveFound.mate.builtinKey !== "clay") throw new Error("Clay is no longer available.");
47
- session = manager.createSession({ ownerId: userId, vendor: resolved.vendor, model: resolved.model, effort: resolved.effort || null }, null);
54
+ if (!liveFound || liveFound.ctx !== found.ctx || !liveFound.mate || liveFound.ctx.getSessionManager() !== manager || liveFound.mate.builtinKey !== "clay" || JSON.stringify([liveFound.mate.id, liveFound.mate.createdAt || null, liveFound.mate.createdBy || null]) !== mateStamp || liveFound.mate.archived) throw new Error("Clay is no longer available.");
55
+ // Another request may have completed while model resolution was awaiting.
56
+ if (findExisting(manager, userId, requestId)) return start(ws, userId, msg);
57
+ var options = { ownerId: userId, vendor: resolved.vendor, model: resolved.model, effort: resolved.effort || null };
58
+ // Background creation must not switch any existing pane/native writer.
59
+ session = contextual ? manager.createSessionRaw(options) : manager.createSession(options, null);
48
60
  session.homeClayEntryRequestId = requestId;
49
- session.homeClayEntryMode = "search";
61
+ session.homeClayEntryMode = contextual ? 'contextual' : 'search';
62
+ if (contextual) {
63
+ session.homeClayEntryText = text;
64
+ session.title = text.slice(0, 80);
65
+ manager.saveSessionFile(session);
66
+ ctx.sendMessage(ws, { type: 'home_clay_contextual_session', requestId: requestId, mateId: found.mate.id, sessionId: session.localId, sessionOriginId: session.sessionOriginId });
67
+ return;
68
+ }
50
69
  manager.sendAndRecord(session, { type: "user_message", text: text });
51
70
  session.isProcessing = true;
52
71
  session.sentToolResults = {};
@@ -2,23 +2,43 @@
2
2
  // owner-bound source session.
3
3
 
4
4
  function attachHomeClaySessionLinks(ctx) {
5
- function source(ws, msg) {
5
+ function source(ws, msg, routedProjectSlug) {
6
+ if (Object.prototype.hasOwnProperty.call(msg, "contextualSource")) {
7
+ var hint = msg.contextualSource, userId = ws && ws._clayUser && ws._clayUser.id;
8
+ if (!hint || typeof hint.mateId !== "string" || !Number.isSafeInteger(hint.sessionId) || typeof hint.sessionOriginId !== "string" || typeof hint.mateStamp !== "string" || !ctx.isActorLive || !ctx.isActorLive(ws, userId)) return {};
9
+ var found = ctx.findMateProject && ctx.findMateProject(userId, hint.mateId, false);
10
+ if (!found || found.mate.archived || found.mate.lifecycleDeletion || found.mate.createdBy && found.mate.createdBy !== userId) return {};
11
+ var stamp = JSON.stringify([found.mate.id, found.mate.createdBy || null, found.mate.createdAt || null, found.mate.builtinKey || null]);
12
+ if (stamp !== hint.mateStamp || ctx.projects.get(found.slug) !== found.ctx) return {};
13
+ var manager = found.ctx.getSessionManager && found.ctx.getSessionManager();
14
+ var session = manager && manager.sessions.get(hint.sessionId);
15
+ if (!ctx.ownsSession(session, userId) || session.sessionOriginId !== hint.sessionOriginId) return {};
16
+ return { tap: { mateSlug: found.slug, mateId: found.mate.id, sessionId: hint.sessionId }, project: found.ctx, session: session };
17
+ }
6
18
  var tap = msg.surface === "search" ? ws._searchClayTap : ws._homeChatTap;
19
+ if (!tap && routedProjectSlug) {
20
+ var routedProject = ctx.projects.get(routedProjectSlug);
21
+ var routedManager = routedProject && routedProject.getSessionManager ? routedProject.getSessionManager() : null;
22
+ var routedSession = routedManager && ws._clayActiveSession ? routedManager.sessions.get(ws._clayActiveSession) : null;
23
+ return { tap: { mateSlug: routedProjectSlug, sessionId: ws._clayActiveSession }, project: routedProject, session: routedSession };
24
+ }
7
25
  var sourceProject = tap && tap.mateSlug ? ctx.projects.get(tap.mateSlug) : null;
8
26
  var sourceManager = sourceProject && sourceProject.getSessionManager ? sourceProject.getSessionManager() : null;
9
27
  var sourceSession = sourceManager && tap ? sourceManager.sessions.get(tap.sessionId) : null;
10
28
  return { tap: tap, project: sourceProject, session: sourceSession };
11
29
  }
12
30
 
13
- function resolve(ws, msg) {
14
- var selected = source(ws, msg);
15
- var bound = ctx.workspaceQueryService && selected.session
16
- ? ctx.workspaceQueryService.bindProjectSession({ projectSlug: selected.tap.mateSlug, session: selected.session })
17
- : null;
31
+ function resolve(ws, msg, routedProjectSlug) {
32
+ var selected = source(ws, msg, routedProjectSlug);
18
33
  var payload = { type: "home_clay_session_target", requestId: msg.requestId || null, sessionRef: msg.sessionRef || null, status: "error" };
19
34
  try {
35
+ var binding = selected.session ? { projectSlug: selected.tap.mateSlug, session: selected.session } : null;
36
+ if (binding && ws && ws._clayUser) binding.viewerId = ws._clayUser.id;
37
+ var bound = ctx.workspaceQueryService && binding
38
+ ? ctx.workspaceQueryService.bindProjectSession(binding)
39
+ : null;
20
40
  if (!bound) throw new Error("The source conversation is no longer available.");
21
- payload.target = bound.resolveSessionNavigation({ sessionRef: msg.sessionRef });
41
+ payload.target = bound.resolveSessionNavigation({ sessionRef: msg.sessionRef, entryIndex: msg.entryIndex });
22
42
  payload.status = "ready";
23
43
  } catch (error) {
24
44
  payload.error = error.message || "Session not available.";
@@ -26,8 +46,8 @@ function attachHomeClaySessionLinks(ctx) {
26
46
  ctx.sendMessage(ws, payload);
27
47
  }
28
48
 
29
- function resolveLog(ws, msg) {
30
- var selected = source(ws, msg);
49
+ function resolveLog(ws, msg, routedProjectSlug) {
50
+ var selected = source(ws, msg, routedProjectSlug);
31
51
  var status = selected.project && selected.project.getStatus ? selected.project.getStatus() : null;
32
52
  var bound = ctx.projectLogsService && selected.session && status
33
53
  ? ctx.projectLogsService.bindMate({
@@ -18,6 +18,7 @@ var INITIATION_PROMPT = [
18
18
  "Before the user answers again, your first and only action must be the next most useful AskUserQuestion. Before presenting it, do not use Bash, Read, Glob, Grep, workspace history, general knowledge, or any other inspection tool, and do not add a preface.",
19
19
  "When that tool returns the user's answer, continue the interview normally. Inspect only bounded context that is directly relevant to what the user supplied, and do not bulk-read knowledge files.",
20
20
  "Then explore the working relationship, recurring activities and context, communication preferences, autonomy, boundaries, and escalation behavior. Use grounded choices only when helpful. Every three to five exchanges, briefly summarize what you understand inside the next question and let the user correct it.",
21
+ "If the user explicitly asks the future Mate to send a scheduled message, collect the message and exact local date/time, timezone, and repetition only through one focused structured question at a time. Treat it as optional schedule intent: never create or register a job during this interview; include it only in propose_mate after reviewing it with the user.",
21
22
  "Choose the Mate's name last. Do not write files and do not create or update a Mate directly.",
22
23
  "When the identity is complete, end only by calling propose_mate with a concise public bio, structured preferences, and a complete first-person identityMarkdown. Do not emit a normal assistant preface or conclusion.",
23
24
  ].join("\n");
@@ -0,0 +1,14 @@
1
+ // Home transcript responses retain the project's server-owned consent request.
2
+ function attachHomeMcpConsent(ctx) {
3
+ function respond(ws, userId, msg) {
4
+ var found = ctx.findMateProject(userId, msg.mateId || null, false);
5
+ var session = found && ctx.resolveHomeSession(found, userId, msg.sessionId);
6
+ var tap = ctx.messageTap(ws, msg), pending = session && session.pendingAskUser && session.pendingAskUser[msg.toolId];
7
+ if (!ctx.isActorLive(ws, userId) || !found || !session || !tap || tap.mateSlug !== found.slug || tap.sessionId !== session.localId || (tap.requestId || null) !== (msg.requestId || null) || !pending || !pending.request || ['mcp-import', 'mate-schedule', 'mcp_fallback', 'product-control'].indexOf(pending.request.source) < 0) {
8
+ ctx.sendError(ws, found && found.mate.id, 'This owner question is unavailable or expired.', msg.requestId || null, msg.sessionId || null, 'question_expired', { toolId: msg.toolId }); return;
9
+ }
10
+ if (!found.ctx.handleHomeAskUserResponse({ type: 'ask_user_response', toolId: msg.toolId, answers: msg.answers || {} }, session, ws)) ctx.sendError(ws, found.mate.id, 'This question could not be submitted.', msg.requestId || null, msg.sessionId, 'question_refused', { toolId: msg.toolId });
11
+ }
12
+ return { respond: respond };
13
+ }
14
+ module.exports = { attachHomeMcpConsent: attachHomeMcpConsent };
@@ -74,12 +74,26 @@ function attachMates(ctx) {
74
74
  var mateSlug = "mate-" + mate.id;
75
75
  var mateName = (mate.profile && mate.profile.displayName) || mate.name || "Mate";
76
76
  var registered = false;
77
+ var boundScheduleJob = null;
77
78
  var favorites;
78
79
  try {
79
80
  registered = addProject(mateDir, mateSlug, mateName, null, mate.createdBy || effectiveUserId, null, { isMate: true, mateDisplayName: mateName }) !== false;
80
81
  if (!registered) throw new Error("The Mate project could not be registered.");
82
+ var intent = mate.seedData && mate.seedData.scheduleIntent;
83
+ if (intent && intent.message && intent.scheduleRule) {
84
+ var targetProject = projects.get(mateSlug);
85
+ var targetManager = targetProject && targetProject.getSessionManager();
86
+ if (!targetProject || !targetManager || typeof targetProject.bindMateSchedule !== "function") throw new Error("The Mate schedule could not be bound to the new Mate.");
87
+ var targetSession = targetManager.createSessionRaw({ ownerId: users.isMultiUser() ? effectiveUserId : null, vendor: mate.vendor, model: mate.model });
88
+ boundScheduleJob = targetProject.bindMateSchedule(targetSession, intent, "creation-" + mate.id);
89
+ if (!boundScheduleJob) throw new Error("The Mate schedule could not be persisted.");
90
+ mates.updateMate(mateCtx, mate.id, { seedData: Object.assign({}, mate.seedData, { scheduleIntent: null }) });
91
+ }
81
92
  favorites = users.addDmFavorite(effectiveUserId, mate.id);
82
93
  } catch (error) {
94
+ if (targetSession && targetSession.mateSchedules && targetProject && typeof targetProject.cancelMateSchedule === "function") {
95
+ try { targetSession.mateSchedules.forEach(function (record) { targetProject.cancelMateSchedule(targetSession, record); }); } catch (cancelError) {}
96
+ }
83
97
  if (registered) try { removeProject(mateSlug); } catch (removeError) {}
84
98
  try { mates.deleteMate(mateCtx, mate.id); } catch (deleteError) {}
85
99
  throw error;
@@ -97,6 +111,10 @@ function attachMates(ctx) {
97
111
  return mate;
98
112
  }
99
113
 
114
+ var lifecycle = require("./mate-lifecycle-service").attachMateLifecycleService({
115
+ users: users, mates: mates, projects: projects, removeProject: removeProject, refresh: refreshTeamSections,
116
+ });
117
+
100
118
  // --- Mate message handlers ---
101
119
 
102
120
  function handleMessage(ws, msg) {
@@ -168,7 +186,7 @@ function attachMates(ctx) {
168
186
  for (var mi = 0; mi < mateList.length; mi++) {
169
187
  var m = mateList[mi];
170
188
  var mSlug = "mate-" + m.id;
171
- if (!projects.has(mSlug)) {
189
+ if (!m.lifecycleDeletion && !projects.has(mSlug)) {
172
190
  var mDir = mates.getMateDir(mateCtx5, m.id);
173
191
  fs.mkdirSync(mDir, { recursive: true });
174
192
  var mName = (m.profile && m.profile.displayName) || m.name || "New Mate";
@@ -200,45 +218,9 @@ function attachMates(ctx) {
200
218
 
201
219
  if (msg.type === "mate_delete") {
202
220
  if (!msg.mateId) return true;
203
- var mateCtx6 = mates.buildMateCtx(userId);
204
- // Track deleted built-in mate key so it doesn't auto-recreate
205
- var mateToDelete = mates.getMate(mateCtx6, msg.mateId);
206
- if (mateToDelete && mateToDelete.builtinKey) {
207
- users.addDeletedBuiltinKey(userId, mateToDelete.builtinKey);
208
- }
209
- var result = mates.deleteMate(mateCtx6, msg.mateId);
210
- if (result.error) {
211
- ws.send(JSON.stringify({ type: "mate_error", error: result.error }));
212
- } else {
213
- removeProject("mate-" + msg.mateId);
214
- // Build updated available builtins list
215
- var builtinDefs3 = require("./builtin-mates");
216
- var missingKeys3 = mates.getMissingBuiltinKeys(mateCtx6);
217
- var availableBuiltins3 = [];
218
- for (var abk3 = 0; abk3 < missingKeys3.length; abk3++) {
219
- var bDef3 = builtinDefs3.getBuiltinByKey(missingKeys3[abk3]);
220
- if (bDef3) {
221
- availableBuiltins3.push({
222
- key: bDef3.key,
223
- displayName: bDef3.displayName,
224
- bio: bDef3.bio,
225
- avatarCustom: bDef3.avatarCustom || "",
226
- avatarStyle: bDef3.avatarStyle || "imprint",
227
- avatarColor: bDef3.avatarColor || "",
228
- });
229
- }
230
- }
231
- ws.send(JSON.stringify({ type: "mate_deleted", mateId: msg.mateId, availableBuiltins: availableBuiltins3 }));
232
- // Broadcast to all clients so strips update
233
- projects.forEach(function (pCtx) {
234
- pCtx.forEachClient(function (otherWs) {
235
- if (otherWs === ws) return;
236
- if (users.isMultiUser() && (!otherWs._clayUser || otherWs._clayUser.id !== userId)) return;
237
- if (otherWs.readyState !== 1) return;
238
- otherWs.send(JSON.stringify({ type: "mate_deleted", mateId: msg.mateId, availableBuiltins: availableBuiltins3 }));
239
- });
240
- });
241
- }
221
+ lifecycle.remove(userId, msg.mateId, null, ws).then(function () {}, function (error) {
222
+ ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, error: error.message }));
223
+ });
242
224
  return true;
243
225
  }
244
226
 
@@ -303,28 +285,8 @@ function attachMates(ctx) {
303
285
  ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, error: "Use the Mate model selector to change this setting." }));
304
286
  return true;
305
287
  }
306
- var mateCtx7 = mates.buildMateCtx(userId);
307
- var updated = mates.updateMate(mateCtx7, msg.mateId, msg.updates);
308
- if (updated && updated.error) {
309
- ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, requestId: msg.requestId, error: updated.error }));
310
- return true;
311
- }
312
- if (updated) {
313
- ws.send(JSON.stringify({ type: "mate_updated", mate: updated, requestId: msg.requestId }));
314
- // Broadcast update
315
- projects.forEach(function (pCtx) {
316
- pCtx.forEachClient(function (otherWs) {
317
- if (otherWs === ws) return;
318
- if (users.isMultiUser() && (!otherWs._clayUser || otherWs._clayUser.id !== userId)) return;
319
- if (otherWs.readyState !== 1) return;
320
- otherWs.send(JSON.stringify({ type: "mate_updated", mate: updated }));
321
- });
322
- });
323
- // Re-enforce team sections across all mate projects so roster stays current
324
- refreshTeamSections(mateCtx7);
325
- } else {
326
- ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, requestId: msg.requestId, error: "Mate not found" }));
327
- }
288
+ try { lifecycle.update(userId, msg.mateId, msg.updates, ws, msg.requestId); }
289
+ catch (error) { ws.send(JSON.stringify({ type: "mate_error", mateId: msg.mateId, requestId: msg.requestId, error: error.message })); }
328
290
  return true;
329
291
  }
330
292
 
@@ -333,6 +295,7 @@ function attachMates(ctx) {
333
295
 
334
296
  return {
335
297
  handleMessage: handleMessage,
298
+ lifecycle: lifecycle,
336
299
  scheduleRegistryRefresh: scheduleRegistryRefresh,
337
300
  createReadyMateFromInterview: createReadyMateFromInterview,
338
301
  };
@@ -0,0 +1,118 @@
1
+ var crypto = require('crypto');
2
+ // Only authenticated application sockets enumerated by the server are targets.
3
+ function attachOwnerUi(ctx) {
4
+ var identities = new WeakMap(), capabilities = new WeakMap(), deliveries = new Map();
5
+ var activityOrder = 0;
6
+ function activity(owner, slug, sessionId, mateId, selected, source, validateSource, navigationTarget) {
7
+ var order = ++activityOrder;
8
+ var viewers = selected ? [check(owner, selected)] : sockets(owner).filter(function (viewer) {
9
+ var tap = viewer.ws._homeChatTap;
10
+ return viewer.slug === slug && viewer.sessionId === sessionId || tap && tap.mateSlug === slug && tap.sessionId === sessionId;
11
+ });
12
+ function send(message, receiptViewer) {
13
+ viewers.forEach(function (viewer) {
14
+ try {
15
+ if (receiptViewer && viewer.ws !== receiptViewer || !alive(viewer.ws, owner)) return;
16
+ if (message.phase !== 'clear' && validateSource) validateSource();
17
+ var live = inspect(owner, viewer.ref), tap = live.ws._homeChatTap;
18
+ if (message.phase !== 'clear' && (selected ? (live.slug !== viewer.slug || live.sessionId !== viewer.sessionId) && !(message.phase === 'rendered' && navigationTarget && live.slug === navigationTarget.projectSlug && live.sessionId === navigationTarget.sessionId) : !(live.slug === slug && live.sessionId === sessionId || tap && tap.mateSlug === slug && tap.sessionId === sessionId))) return;
19
+ live.ws.send(JSON.stringify(Object.assign({ type: 'clay_control_activity', ownerId: owner, mateId: mateId,
20
+ sourceSlug: slug, sourceSessionId: sessionId, order: order, recipientViewerRef: live.ref }, source, message)));
21
+ } catch (error) { /* Presentation cannot alter the authoritative effect. */ }
22
+ });
23
+ }
24
+ return { send: send, clear: function (id, sequence) { send({ version: 1, id: id, sequence: sequence, phase: 'clear' }); } };
25
+ }
26
+ function alive(ws, owner) {
27
+ return ws && ws.readyState === 1 && (!ws._clayAuthCheck || ws._clayAuthCheck()) &&
28
+ (ctx.isMultiUser() ? !!owner && ws._clayUser && ws._clayUser.id === owner && !!ctx.findUser(owner) : !ws._clayUser);
29
+ }
30
+ function sockets(owner) {
31
+ var all = new Map();
32
+ ctx.forEachClient(function (ws, slug) {
33
+ if (!alive(ws, owner) || all.has(ws)) return;
34
+ if (!identities.has(ws)) identities.set(ws, 'viewer:' + crypto.randomUUID());
35
+ all.set(ws, { ws: ws, ref: identities.get(ws), slug: slug || null, sessionId: ws._clayActiveSession || null,
36
+ supported: capabilities.get(ws) === 1 && !ws._clayPane });
37
+ });
38
+ return Array.from(all.values());
39
+ }
40
+ function get(owner, ref) { return sockets(owner).find(function (item) { return item.ref === ref; }); }
41
+ function inspect(owner, ref) {
42
+ var viewer = get(owner, ref);
43
+ if (!viewer) throw new Error('The exact owner UI connection is absent or revoked.');
44
+ return viewer;
45
+ }
46
+ function check(owner, original) {
47
+ var live = inspect(owner, original.ref);
48
+ if (live.ws !== original.ws || live.slug !== original.slug || live.sessionId !== original.sessionId || live.supported !== original.supported) throw new Error('The selected viewer context changed. Inspect again.');
49
+ return live;
50
+ }
51
+ function deliver(owner, original, target, revalidate, activity) {
52
+ revalidate(); var viewer = check(owner, original);
53
+ if (!viewer.supported) return { status: 'unsupported', delivered: false, acknowledged: false, visible: 'unknown' };
54
+ if (deliveries.size >= 100) {
55
+ deliveries.forEach(function (item, key) { if (Date.now() - item.created > 300000) deliveries.delete(key); });
56
+ if (deliveries.size >= 100) throw new Error('UI delivery capacity is full; wait for earlier attempts to expire.');
57
+ }
58
+ var id = 'navigation:' + crypto.randomUUID();
59
+ var renderToken = crypto.randomUUID();
60
+ var record = { owner: owner, viewer: viewer, target: target, revalidate: revalidate, activity: activity, created: Date.now(), claimed: false, renderToken: renderToken, renderClosed: false,
61
+ result: { status: 'delivered', deliveryId: id, delivered: false, acknowledged: false, visible: 'unknown' } };
62
+ deliveries.set(id, record);
63
+ record.renderTimer = setTimeout(function () {
64
+ if (record.renderClosed) return;
65
+ record.renderClosed = true; record.result.renderStatus = 'unknown';
66
+ if (record.activity) record.activity.navigation('unknown');
67
+ }, ctx.renderTimeoutMs || 5000); record.renderTimer.unref();
68
+ try {
69
+ viewer.ws.send(JSON.stringify({ type: 'clay_navigation_offer', deliveryId: id }));
70
+ if (!alive(viewer.ws, owner)) throw new Error('Viewer authorization or connection ended during delivery.');
71
+ record.result.delivered = true;
72
+ } catch (error) { record.result.status = 'failed'; record.result.error = error.message; record.result.retrySafe = false; }
73
+ return Object.assign({}, record.result);
74
+ }
75
+ function read(owner, id) {
76
+ var record = deliveries.get(id);
77
+ if (!record || record.owner !== owner) throw new Error('No delivery exists for this owner.');
78
+ if (Date.now() - record.created > 300000) { deliveries.delete(id); throw new Error('The five-minute navigation receipt expired. Inspect the current view before any new reviewed request.'); }
79
+ record.revalidate();
80
+ return Object.assign({}, record.result);
81
+ }
82
+ function handleMessage(ws, msg) {
83
+ if (['clay_ui_ready', 'clay_navigation_claim', 'clay_navigation_ack', 'clay_navigation_rendered'].indexOf(msg.type) < 0) return false;
84
+ var owner = ctx.isMultiUser() ? ws._clayUser && ws._clayUser.id : null;
85
+ if (!sockets(owner).some(function (item) { return item.ws === ws; })) return true;
86
+ if (msg.type === 'clay_ui_ready') {
87
+ if (msg.version === 1) { capabilities.set(ws, 1); ws.send(JSON.stringify({ type: 'clay_control_viewer', viewerRef: identities.get(ws) })); }
88
+ return true;
89
+ }
90
+ var record = deliveries.get(msg.deliveryId);
91
+ if (!record || record.viewer.ws !== ws || record.owner !== owner || Date.now() - record.created > 30000) return true;
92
+ try {
93
+ record.revalidate();
94
+ if (msg.type === 'clay_navigation_rendered') {
95
+ if (!record.renderClosed && Date.now() > record.created + (ctx.renderTimeoutMs || 5000)) { record.renderClosed = true; clearTimeout(record.renderTimer); record.result.renderStatus = 'unknown'; if (record.activity) record.activity.navigation('unknown'); }
96
+ if (record.renderClosed || !record.claimed || !record.result.acknowledged || record.result.clientStatus !== 'accepted' || msg.renderToken !== record.renderToken) return true;
97
+ var current = inspect(owner, record.viewer.ref);
98
+ if (current.ws !== ws || msg.sessionOriginId !== record.target.sessionOriginId || !record.target.sessionOriginId || msg.projectSlug !== record.target.projectSlug || msg.sessionId !== record.target.sessionId || msg.surface !== 'conversation' || msg.entryIndex !== record.target.entryIndex || current.slug !== record.target.projectSlug || current.sessionId !== record.target.sessionId) throw new Error('Rendered target or authenticated viewer changed.');
99
+ record.renderClosed = true; clearTimeout(record.renderTimer);
100
+ record.result.renderStatus = msg.visible === true ? 'rendered' : 'unknown'; record.result.visible = msg.visible === true ? true : 'unknown';
101
+ if (record.activity) record.activity.navigation(msg.visible === true ? 'rendered' : 'unknown');
102
+ } else if (msg.type === 'clay_navigation_claim') {
103
+ if (record.claimed) return true;
104
+ check(owner, record.viewer); record.claimed = true;
105
+ ws.send(JSON.stringify({ type: 'clay_navigation_apply', deliveryId: msg.deliveryId, target: record.target, renderToken: record.renderToken, renderDeadline: record.created + (ctx.renderTimeoutMs || 5000) }));
106
+ } else if (record.claimed && !record.result.acknowledged && ['accepted', 'refused', 'failed'].indexOf(msg.status) >= 0) {
107
+ record.result.acknowledged = true;
108
+ // Accepted only confirms invocation of the existing navigator, never rendering.
109
+ record.result.clientStatus = msg.status;
110
+ if (msg.status !== 'accepted') { record.renderClosed = true; clearTimeout(record.renderTimer); }
111
+ if (record.activity) record.activity.navigation(msg.status === 'accepted' ? 'acknowledged' : msg.status === 'refused' ? 'cancelled' : 'failed');
112
+ }
113
+ } catch (error) { record.renderClosed = true; clearTimeout(record.renderTimer); record.result.visible = 'unknown'; record.result.status = 'failed'; record.result.error = error.message; record.result.retrySafe = false; if (record.activity) record.activity.cancel(); }
114
+ return true;
115
+ }
116
+ return { list: sockets, inspect: inspect, check: check, deliver: deliver, read: read, handleMessage: handleMessage, activity: activity };
117
+ }
118
+ module.exports = { attachOwnerUi: attachOwnerUi };
@@ -0,0 +1,38 @@
1
+ // Directory pickers and project registration must not become content-access
2
+ // bypasses through another spelling, symlink or nested directory.
3
+ var fs = require("fs");
4
+ var path = require("path");
5
+ function inside(root, target) {
6
+ var relative = path.relative(root, target);
7
+ return relative !== ".." && relative.indexOf(".." + path.sep) !== 0 && !path.isAbsolute(relative);
8
+ }
9
+ function attachPathAccess(ctx) {
10
+ return function (userId, requested) {
11
+ if (!ctx.users.isMultiUser()) return true;
12
+ var user = userId && ctx.users.findUserById(userId);
13
+ if (!user) return false;
14
+ var target;
15
+ try { target = fs.realpathSync(requested); } catch (error) { return false; }
16
+ var allowed = false;
17
+ var denied = false;
18
+ ctx.projects.forEach(function (project, slug) {
19
+ var status = project.getStatus();
20
+ var root;
21
+ try { root = fs.realpathSync(status.path); } catch (error) { return; }
22
+ if (inside(root, target) || inside(target, root)) {
23
+ if (!ctx.canAccess(userId, slug)) denied = true;
24
+ else if (inside(root, target)) allowed = true;
25
+ }
26
+ });
27
+ if (denied) return false;
28
+ if (ctx.osUsers) {
29
+ if (!user.linuxUser) return false;
30
+ try {
31
+ var identity = ctx.resolveIdentity(user.linuxUser);
32
+ return inside(fs.realpathSync(identity.home), target);
33
+ } catch (error) { return false; }
34
+ }
35
+ return allowed || ctx.users.getAllUsers().length === 1;
36
+ };
37
+ }
38
+ module.exports = { attachPathAccess: attachPathAccess };
@@ -0,0 +1,22 @@
1
+ // Shared runtime removal used by the server callback and lifecycle controls.
2
+ function removeProjectRuntime(projects, slug, awaitCompletion, registryRefresh) {
3
+ var project = projects.get(slug);
4
+ if (!project) return false;
5
+ var wasMate = project.getStatus().isMate;
6
+ var shutdownResult = project.destroy();
7
+ if (!awaitCompletion) projects.delete(slug);
8
+ if (shutdownResult && typeof shutdownResult.catch === 'function') {
9
+ shutdownResult.catch(function (error) {
10
+ console.error('[server] Project destroy failed for ' + slug + ':', error && error.message ? error.message : error);
11
+ });
12
+ }
13
+ if (!wasMate && registryRefresh) registryRefresh();
14
+ if (awaitCompletion) return Promise.resolve(shutdownResult).then(function (result) {
15
+ if (result !== true) throw new Error('Project runtime shutdown did not complete successfully: ' + slug);
16
+ if (projects.get(slug) !== project) throw new Error('Project runtime was replaced during shutdown: ' + slug);
17
+ projects.delete(slug);
18
+ return true;
19
+ });
20
+ return true;
21
+ }
22
+ module.exports = { removeProjectRuntime: removeProjectRuntime };
@@ -12,11 +12,13 @@ function attachSettings(ctx) {
12
12
  var CONFIG_DIR = ctx.CONFIG_DIR;
13
13
 
14
14
  var profilePath = path.join(CONFIG_DIR, "profile.json");
15
+ var contextualClaySettings = require('./server-contextual-clay-settings').attachContextualClaySettings(ctx);
15
16
  var appearanceSettings = require('./server-appearance-settings').attachAppearanceSettings(ctx);
16
17
  var notificationSettings = require('./server-notification-settings').attachNotificationSettings(ctx);
17
18
  var experimentalSettings = attachExperimentalSettings(ctx);
18
19
 
19
20
  function handleRequest(req, res, fullUrl) {
21
+ if (contextualClaySettings.handleRequest(req, res, fullUrl)) return true;
20
22
  if (appearanceSettings.handleRequest(req, res, fullUrl)) return true;
21
23
  if (notificationSettings.handleRequest(req, res, fullUrl)) return true;
22
24
  if (experimentalSettings.handleRequest(req, res, fullUrl)) return true;
@@ -56,6 +58,7 @@ function attachSettings(ctx) {
56
58
  profile.userId = mu.id;
57
59
  profile.role = mu.role;
58
60
  profile.pinEnabled = !!mu.pinHash;
61
+ profile.passwordEnabled = !!mu.passwordHash;
59
62
  profile.autoContinueOnRateLimit = !!mu.autoContinueOnRateLimit;
60
63
  profile.chatLayout = mu.chatLayout || "channel";
61
64
  profile.projectMateFilterMode = users.getProjectMateFilterMode(mu.id);
@@ -395,7 +398,7 @@ function attachSettings(ctx) {
395
398
  res.end('{"error":"Current PIN is required"}');
396
399
  return;
397
400
  }
398
- if (mu.pinHash !== users.hashPin(data.currentPin)) {
401
+ if (!users.verifyPin(data.currentPin, mu.pinHash, mu)) {
399
402
  res.writeHead(400, { "Content-Type": "application/json" });
400
403
  res.end('{"error":"Current PIN is incorrect"}');
401
404
  return;
@@ -754,7 +757,10 @@ function attachSettings(ctx) {
754
757
  return false;
755
758
  }
756
759
 
757
- return { handleRequest: handleRequest };
760
+ return {
761
+ handleRequest: handleRequest,
762
+ getInitialAppearance: appearanceSettings.getInitialAppearance
763
+ };
758
764
  }
759
765
 
760
766
  module.exports = { attachSettings: attachSettings };