clay-server 5.2.0-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 (552) hide show
  1. package/lib/account-auth-socket.js +1 -0
  2. package/lib/builtin-mates.js +19 -16
  3. package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
  4. package/lib/canonical-clay-record-authority.js +15 -0
  5. package/lib/canonical-clay-scheduling-authority.js +19 -0
  6. package/lib/claude-hook-installer.js +1 -239
  7. package/lib/claude-jsonl-watcher.js +1 -204
  8. package/lib/clay-control-presentation-binding.js +96 -0
  9. package/lib/clay-control-presentation.js +128 -0
  10. package/lib/clay-control-target-projection.js +26 -0
  11. package/lib/clay-mate-chat-receipts.js +26 -0
  12. package/lib/clay-mate-chat.js +88 -0
  13. package/lib/clay-mate-knowledge-input.js +26 -0
  14. package/lib/clay-mate-knowledge.js +95 -0
  15. package/lib/clay-mate-lifecycle.js +95 -0
  16. package/lib/clay-product-control-input.js +33 -0
  17. package/lib/clay-product-control-tools.js +51 -0
  18. package/lib/clay-product-control.js +247 -0
  19. package/lib/clay-project-lifecycle.js +154 -0
  20. package/lib/clay-project-record-input.js +44 -0
  21. package/lib/clay-project-records.js +84 -0
  22. package/lib/clay-scheduling-input.js +21 -0
  23. package/lib/clay-scheduling-receipts.js +26 -0
  24. package/lib/clay-scheduling.js +119 -0
  25. package/lib/clay-screen-controls.js +104 -0
  26. package/lib/clay-skill-install.js +1 -33
  27. package/lib/clay-workspace-controls.js +84 -0
  28. package/lib/clay-workspace-input.js +17 -0
  29. package/lib/clay-workspace-receipts.js +26 -0
  30. package/lib/cli-sessions.js +1 -300
  31. package/lib/codex-defaults.js +1 -28
  32. package/lib/context-usage.js +3 -2
  33. package/lib/contextual-screen-snapshot.js +38 -0
  34. package/lib/daemon-project-access.js +11 -0
  35. package/lib/daemon-project-lifecycle-callbacks.js +15 -0
  36. package/lib/daemon-project-lifecycle.js +262 -0
  37. package/lib/daemon-projects.js +1 -1
  38. package/lib/daemon.js +78 -276
  39. package/lib/default-ai-runtime.js +4 -8
  40. package/lib/dm-digest-cursor.js +120 -0
  41. package/lib/email-mcp-server.js +1 -1
  42. package/lib/issues-service.js +29 -15
  43. package/lib/kiro-defaults.js +1 -22
  44. package/lib/knowledge-db-import-validation.js +46 -0
  45. package/lib/knowledge-db-import.js +99 -0
  46. package/lib/knowledge-db-service.js +24 -33
  47. package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
  48. package/lib/knowledge-db-storage-nedb.js +66 -0
  49. package/lib/knowledge-db-storage.js +72 -0
  50. package/lib/knowledge-db-validation.js +0 -0
  51. package/lib/knowledge-document-index.js +2 -1
  52. package/lib/knowledge-file-store.js +7 -1
  53. package/lib/knowledge-product-operations.js +46 -0
  54. package/lib/mate-avatar-catalog.js +12 -0
  55. package/lib/mate-avatar-migration.js +41 -0
  56. package/lib/mate-context-service.js +138 -0
  57. package/lib/mate-context-tools.js +21 -0
  58. package/lib/mate-creation-mcp-server.js +2 -0
  59. package/lib/mate-knowledge-canonical-access.js +10 -0
  60. package/lib/mate-knowledge-mate-bound.js +53 -0
  61. package/lib/mate-knowledge-mcp-server.js +55 -8
  62. package/lib/mate-knowledge-service.js +16 -34
  63. package/lib/mate-knowledge-text-tools.js +106 -0
  64. package/lib/mate-lifecycle-service.js +94 -0
  65. package/lib/mate-message-delivery.js +43 -0
  66. package/lib/mate-ready-creation.js +9 -1
  67. package/lib/mate-schedule-input.js +29 -0
  68. package/lib/mate-schedule-lifecycle.js +151 -0
  69. package/lib/mate-scheduling.js +103 -0
  70. package/lib/mates.js +18 -6
  71. package/lib/mcp-agent-tools.js +117 -0
  72. package/lib/mcp-connection-store.js +119 -15
  73. package/lib/mcp-import-credentials.js +31 -0
  74. package/lib/mcp-local-transport.js +13 -0
  75. package/lib/mcp-oauth.js +8 -6
  76. package/lib/mcp-proxy.js +2 -32
  77. package/lib/mcp-query-bridge.js +30 -0
  78. package/lib/mcp-remote-connections.js +74 -20
  79. package/lib/mcp-source-adapters.js +1 -0
  80. package/lib/mcp-source-context.js +1 -0
  81. package/lib/mcp-source-discovery.js +1 -0
  82. package/lib/mcp-source-plugins.js +1 -0
  83. package/lib/mcp-source-restrictions.js +1 -0
  84. package/lib/mcp-tool-policy.js +9 -0
  85. package/lib/notes-checklist.js +50 -0
  86. package/lib/notes.js +49 -3
  87. package/lib/os-user-diagnostics.js +2 -4
  88. package/lib/os-users.js +24 -70
  89. package/lib/pane-pending-interactions.js +20 -0
  90. package/lib/pane-session-activation.js +114 -0
  91. package/lib/pane-session-transport.js +26 -0
  92. package/lib/project-admin-overview.js +51 -0
  93. package/lib/project-ask-user.js +8 -4
  94. package/lib/project-connection.js +14 -10
  95. package/lib/project-control-git-view.js +12 -0
  96. package/lib/project-debate.js +1 -0
  97. package/lib/project-delegated-follow-up.js +2 -1
  98. package/lib/project-directory-claim.js +65 -0
  99. package/lib/project-file-operations.js +61 -0
  100. package/lib/project-filesystem.js +15 -85
  101. package/lib/project-full-access.js +23 -2
  102. package/lib/project-http.js +7 -4
  103. package/lib/project-knowledge.js +32 -18
  104. package/lib/project-lifecycle-operations.js +98 -0
  105. package/lib/project-lifecycle-process-witness.js +32 -0
  106. package/lib/project-lifecycle-runtime.js +50 -0
  107. package/lib/project-linux-access.js +22 -0
  108. package/lib/project-logs-canonical-clay.js +27 -0
  109. package/lib/project-logs-clay-query.js +16 -0
  110. package/lib/project-logs-schema.js +4 -2
  111. package/lib/project-logs-service.js +8 -7
  112. package/lib/project-logs.js +1 -0
  113. package/lib/project-loop.js +1 -0
  114. package/lib/project-mate-chat-control.js +55 -0
  115. package/lib/project-mate-creation-proposal.js +18 -3
  116. package/lib/project-mate-interaction.js +40 -62
  117. package/lib/project-mcp.js +54 -16
  118. package/lib/project-models.js +14 -31
  119. package/lib/project-notifications.js +76 -17
  120. package/lib/project-ownership.js +77 -0
  121. package/lib/project-pair-result-delivery.js +14 -3
  122. package/lib/project-pair-usage.js +12 -13
  123. package/lib/project-pending-message-queue.js +4 -1
  124. package/lib/project-product-control.js +89 -0
  125. package/lib/project-product-session-queue.js +46 -0
  126. package/lib/project-push-access.js +28 -0
  127. package/lib/project-scheduled-message-queue.js +30 -0
  128. package/lib/project-scheduled-messages.js +67 -68
  129. package/lib/project-scheduled-task-control.js +83 -0
  130. package/lib/project-scheduled-tasks.js +13 -2
  131. package/lib/project-scheduling-access.js +10 -0
  132. package/lib/project-session-actions.js +65 -0
  133. package/lib/project-session-delete.js +8 -1
  134. package/lib/project-session-document.js +27 -7
  135. package/lib/project-session-github.js +63 -19
  136. package/lib/project-session-history-actions.js +167 -0
  137. package/lib/project-session-linear.js +14 -6
  138. package/lib/project-session-notes.js +7 -3
  139. package/lib/project-session-pair.js +1 -1
  140. package/lib/project-session-runtime-actions.js +64 -0
  141. package/lib/project-session-spawn.js +2 -3
  142. package/lib/project-session-vendor.js +55 -0
  143. package/lib/project-sessions.js +103 -272
  144. package/lib/project-shared-browser.js +78 -17
  145. package/lib/project-studio-presentation.js +58 -0
  146. package/lib/project-user-message.js +67 -1
  147. package/lib/project-vendor-login.js +6 -36
  148. package/lib/project-workspace-operations.js +126 -0
  149. package/lib/project-workspace-query.js +19 -2
  150. package/lib/project.js +178 -45
  151. package/lib/public/app.js +46 -0
  152. package/lib/public/appearance-bootstrap.js +16 -0
  153. package/lib/public/css/clay-tool-activity.css +51 -0
  154. package/lib/public/css/clay-workspace.css +29 -0
  155. package/lib/public/css/command-palette.css +12 -33
  156. package/lib/public/css/contextual-clay.css +240 -0
  157. package/lib/public/css/home-debate-planning.css +2 -0
  158. package/lib/public/css/home-mate-creation.css +5 -0
  159. package/lib/public/css/input.css +6 -0
  160. package/lib/public/css/mate-avatar-gallery.css +12 -0
  161. package/lib/public/css/mate-conversation.css +10 -5
  162. package/lib/public/css/messages.css +6 -2
  163. package/lib/public/css/overlays.css +4 -2
  164. package/lib/public/css/project-admin-overview.css +13 -0
  165. package/lib/public/css/session-folders.css +11 -0
  166. package/lib/public/css/session-github.css +46 -1
  167. package/lib/public/css/shared-browser.css +35 -1
  168. package/lib/public/css/sticky-notes.css +87 -1
  169. package/lib/public/index.html +11 -5
  170. package/lib/public/mate-avatars/B01.png +0 -0
  171. package/lib/public/mate-avatars/B02.png +0 -0
  172. package/lib/public/mate-avatars/B03.png +0 -0
  173. package/lib/public/mate-avatars/B04.png +0 -0
  174. package/lib/public/mate-avatars/B05.png +0 -0
  175. package/lib/public/mate-avatars/B06.png +0 -0
  176. package/lib/public/mate-avatars/B07.png +0 -0
  177. package/lib/public/mate-avatars/B08.png +0 -0
  178. package/lib/public/mate-avatars/B09.png +0 -0
  179. package/lib/public/mate-avatars/B10.png +0 -0
  180. package/lib/public/mate-avatars/B11.png +0 -0
  181. package/lib/public/mate-avatars/B12.png +0 -0
  182. package/lib/public/mate-avatars/B13.png +0 -0
  183. package/lib/public/mate-avatars/B14.png +0 -0
  184. package/lib/public/mate-avatars/B15.png +0 -0
  185. package/lib/public/mate-avatars/B16.png +0 -0
  186. package/lib/public/mate-avatars/B17.png +0 -0
  187. package/lib/public/mate-avatars/B18.png +0 -0
  188. package/lib/public/mate-avatars/B19.png +0 -0
  189. package/lib/public/mate-avatars/B20.png +0 -0
  190. package/lib/public/mate-avatars/B21.png +0 -0
  191. package/lib/public/mate-avatars/B22.png +0 -0
  192. package/lib/public/mate-avatars/B23.png +0 -0
  193. package/lib/public/mate-avatars/B24.png +0 -0
  194. package/lib/public/mate-avatars/B25.png +0 -0
  195. package/lib/public/mate-avatars/B26.png +0 -0
  196. package/lib/public/mate-avatars/B27.png +0 -0
  197. package/lib/public/mate-avatars/B28.png +0 -0
  198. package/lib/public/mate-avatars/B29.png +0 -0
  199. package/lib/public/mate-avatars/B30.png +0 -0
  200. package/lib/public/mate-avatars/B31.png +0 -0
  201. package/lib/public/mate-avatars/B32.png +0 -0
  202. package/lib/public/mate-avatars/B33.png +0 -0
  203. package/lib/public/mate-avatars/B34.png +0 -0
  204. package/lib/public/mate-avatars/B35.png +0 -0
  205. package/lib/public/mate-avatars/B36.png +0 -0
  206. package/lib/public/mate-avatars/B37.png +0 -0
  207. package/lib/public/mate-avatars/B38.png +0 -0
  208. package/lib/public/mate-avatars/B39.png +0 -0
  209. package/lib/public/mate-avatars/B40.png +0 -0
  210. package/lib/public/mate-avatars/B41.png +0 -0
  211. package/lib/public/mate-avatars/B42.png +0 -0
  212. package/lib/public/mate-avatars/B43.png +0 -0
  213. package/lib/public/mate-avatars/B44.png +0 -0
  214. package/lib/public/mate-avatars/B45.png +0 -0
  215. package/lib/public/mate-avatars/B46.png +0 -0
  216. package/lib/public/mate-avatars/B47.png +0 -0
  217. package/lib/public/mate-avatars/B48.png +0 -0
  218. package/lib/public/mate-avatars/C01.png +0 -0
  219. package/lib/public/mate-avatars/C02.png +0 -0
  220. package/lib/public/mate-avatars/C03.png +0 -0
  221. package/lib/public/mate-avatars/C04.png +0 -0
  222. package/lib/public/mate-avatars/C05.png +0 -0
  223. package/lib/public/mate-avatars/C06.png +0 -0
  224. package/lib/public/mate-avatars/C07.png +0 -0
  225. package/lib/public/mate-avatars/C08.png +0 -0
  226. package/lib/public/mate-avatars/C09.png +0 -0
  227. package/lib/public/mate-avatars/C10.png +0 -0
  228. package/lib/public/mate-avatars/C11.png +0 -0
  229. package/lib/public/mate-avatars/C12.png +0 -0
  230. package/lib/public/mate-avatars/C13.png +0 -0
  231. package/lib/public/mate-avatars/C14.png +0 -0
  232. package/lib/public/mate-avatars/C15.png +0 -0
  233. package/lib/public/mate-avatars/C16.png +0 -0
  234. package/lib/public/mate-avatars/C17.png +0 -0
  235. package/lib/public/mate-avatars/C18.png +0 -0
  236. package/lib/public/mate-avatars/C19.png +0 -0
  237. package/lib/public/mate-avatars/C20.png +0 -0
  238. package/lib/public/mate-avatars/C21.png +0 -0
  239. package/lib/public/mate-avatars/C22.png +0 -0
  240. package/lib/public/mate-avatars/C23.png +0 -0
  241. package/lib/public/mate-avatars/C24.png +0 -0
  242. package/lib/public/mate-avatars/C25.png +0 -0
  243. package/lib/public/mate-avatars/C26.png +0 -0
  244. package/lib/public/mate-avatars/C27.png +0 -0
  245. package/lib/public/mate-avatars/C28.png +0 -0
  246. package/lib/public/mate-avatars/C29.png +0 -0
  247. package/lib/public/mate-avatars/C30.png +0 -0
  248. package/lib/public/mate-avatars/C31.png +0 -0
  249. package/lib/public/mate-avatars/C32.png +0 -0
  250. package/lib/public/mate-avatars/C33.png +0 -0
  251. package/lib/public/mate-avatars/C34.png +0 -0
  252. package/lib/public/mate-avatars/C35.png +0 -0
  253. package/lib/public/mate-avatars/C36.png +0 -0
  254. package/lib/public/mate-avatars/C37.png +0 -0
  255. package/lib/public/mate-avatars/C38.png +0 -0
  256. package/lib/public/mate-avatars/C39.png +0 -0
  257. package/lib/public/mate-avatars/C40.png +0 -0
  258. package/lib/public/mate-avatars/C41.png +0 -0
  259. package/lib/public/mate-avatars/C42.png +0 -0
  260. package/lib/public/mate-avatars/C43.png +0 -0
  261. package/lib/public/mate-avatars/C44.png +0 -0
  262. package/lib/public/mate-avatars/C45.png +0 -0
  263. package/lib/public/mate-avatars/C46.png +0 -0
  264. package/lib/public/mate-avatars/C47.png +0 -0
  265. package/lib/public/mate-avatars/C48.png +0 -0
  266. package/lib/public/mate-avatars/catalog.json +482 -0
  267. package/lib/public/mate-avatars/lead-clay.png +0 -0
  268. package/lib/public/modules/admin-settings-projects.js +6 -2
  269. package/lib/public/modules/app-connection.js +11 -1
  270. package/lib/public/modules/app-favicon.js +18 -9
  271. package/lib/public/modules/app-header.js +7 -4
  272. package/lib/public/modules/app-loop-ui.js +2 -0
  273. package/lib/public/modules/app-message-router.js +22 -1
  274. package/lib/public/modules/app-messages.js +115 -17
  275. package/lib/public/modules/app-misc.js +3 -1
  276. package/lib/public/modules/app-notifications.js +11 -5
  277. package/lib/public/modules/app-panels.js +61 -123
  278. package/lib/public/modules/app-projects.js +13 -0
  279. package/lib/public/modules/app-rate-limit.js +7 -27
  280. package/lib/public/modules/app-rendering.js +4 -3
  281. package/lib/public/modules/avatar.js +15 -41
  282. package/lib/public/modules/chat-render-runtime.js +20 -0
  283. package/lib/public/modules/clay-browser-links.js +47 -0
  284. package/lib/public/modules/clay-control-activity.js +214 -0
  285. package/lib/public/modules/clay-control-copy.js +36 -0
  286. package/lib/public/modules/clay-control-detail-targets.js +44 -0
  287. package/lib/public/modules/clay-control-object-targets.js +52 -0
  288. package/lib/public/modules/clay-control-target-visibility.js +12 -0
  289. package/lib/public/modules/clay-control-targets.js +44 -0
  290. package/lib/public/modules/clay-log-links.js +23 -0
  291. package/lib/public/modules/clay-navigation-render.js +52 -0
  292. package/lib/public/modules/clay-owner-navigation.js +33 -0
  293. package/lib/public/modules/clay-session-links.js +31 -0
  294. package/lib/public/modules/clay-studio-bridge.js +20 -0
  295. package/lib/public/modules/clay-studio-document.js +67 -0
  296. package/lib/public/modules/clay-studio-render.js +146 -0
  297. package/lib/public/modules/clay-tool-activity.js +140 -0
  298. package/lib/public/modules/clay-tool-presentation.js +342 -0
  299. package/lib/public/modules/command-palette.js +162 -40
  300. package/lib/public/modules/contextual-ask-session.js +26 -0
  301. package/lib/public/modules/contextual-clay-geometry.js +155 -0
  302. package/lib/public/modules/contextual-clay-session.js +130 -0
  303. package/lib/public/modules/contextual-clay-workspace.js +169 -0
  304. package/lib/public/modules/contextual-clay.js +250 -0
  305. package/lib/public/modules/contextual-composer.js +91 -0
  306. package/lib/public/modules/contextual-mate-context.js +117 -0
  307. package/lib/public/modules/contextual-mate-hint.js +40 -0
  308. package/lib/public/modules/contextual-mate-identity.js +23 -0
  309. package/lib/public/modules/contextual-mate-sessions.js +134 -0
  310. package/lib/public/modules/contextual-search.js +137 -0
  311. package/lib/public/modules/contextual-session-citations.js +58 -0
  312. package/lib/public/modules/debate.js +1 -0
  313. package/lib/public/modules/default-ai.js +11 -3
  314. package/lib/public/modules/elicitation-form.js +5 -0
  315. package/lib/public/modules/filebrowser.js +20 -1
  316. package/lib/public/modules/generation-stop.js +8 -5
  317. package/lib/public/modules/git-panel.js +3 -1
  318. package/lib/public/modules/history-replay-batch.js +13 -1
  319. package/lib/public/modules/home-debate-live.js +2 -0
  320. package/lib/public/modules/home-debate-planning.js +7 -7
  321. package/lib/public/modules/home-mate-avatar-editor.js +127 -208
  322. package/lib/public/modules/home-mate-chat.js +8 -6
  323. package/lib/public/modules/home-mate-creation.js +73 -1
  324. package/lib/public/modules/home-mate-settings.js +19 -12
  325. package/lib/public/modules/icon-strip-tooltip.js +2 -1
  326. package/lib/public/modules/input.js +88 -10
  327. package/lib/public/modules/issues-render.js +3 -2
  328. package/lib/public/modules/knowledge-db-workbench.js +4 -4
  329. package/lib/public/modules/markdown.js +6 -34
  330. package/lib/public/modules/mate-avatar-catalog.js +97 -0
  331. package/lib/public/modules/mate-knowledge-workbench.js +1 -1
  332. package/lib/public/modules/mate-management.js +40 -7
  333. package/lib/public/modules/mcp-connection-view.js +31 -13
  334. package/lib/public/modules/mcp-discovery-view.js +31 -0
  335. package/lib/public/modules/mcp-ui.js +23 -4
  336. package/lib/public/modules/mention.js +3 -0
  337. package/lib/public/modules/message-delivery.js +20 -2
  338. package/lib/public/modules/model-picker.js +2 -0
  339. package/lib/public/modules/pane-activation.js +214 -0
  340. package/lib/public/modules/pane-binding.js +82 -0
  341. package/lib/public/modules/pane-bridge.js +7 -4
  342. package/lib/public/modules/pane-browser-bridge.js +22 -0
  343. package/lib/public/modules/pane-file-bridge.js +4 -0
  344. package/lib/public/modules/pane-issue-bridge.js +4 -1
  345. package/lib/public/modules/pending-message-queue.js +1 -0
  346. package/lib/public/modules/permission-control.js +5 -4
  347. package/lib/public/modules/personal-settings-dialog.js +7 -1
  348. package/lib/public/modules/product-review.js +26 -0
  349. package/lib/public/modules/profile.js +1 -238
  350. package/lib/public/modules/project-access-recovery.js +17 -0
  351. package/lib/public/modules/project-admin-overview.js +21 -0
  352. package/lib/public/modules/project-chat-identity.js +13 -4
  353. package/lib/public/modules/project-logs-render.js +3 -0
  354. package/lib/public/modules/project-mate-navigation.js +144 -22
  355. package/lib/public/modules/rewind.js +5 -0
  356. package/lib/public/modules/scheduled-tasks.js +2 -0
  357. package/lib/public/modules/scheduler.js +2 -0
  358. package/lib/public/modules/search-clay-chat.js +5 -440
  359. package/lib/public/modules/session-actions.js +5 -2
  360. package/lib/public/modules/session-context-menu.js +5 -0
  361. package/lib/public/modules/session-create-form.js +10 -10
  362. package/lib/public/modules/session-folder-layout.js +1 -1
  363. package/lib/public/modules/session-folder-view-menu.js +9 -0
  364. package/lib/public/modules/session-github.js +85 -14
  365. package/lib/public/modules/session-rich-drafts.js +21 -0
  366. package/lib/public/modules/session-switch-defer.js +67 -0
  367. package/lib/public/modules/session-work-primary.js +51 -0
  368. package/lib/public/modules/settings-defaults.js +27 -28
  369. package/lib/public/modules/shared-browser-settings.js +112 -0
  370. package/lib/public/modules/shared-browser-tabs.js +13 -3
  371. package/lib/public/modules/shared-browser.js +29 -6
  372. package/lib/public/modules/sidebar-mobile.js +4 -3
  373. package/lib/public/modules/sidebar-projects.js +1 -0
  374. package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
  375. package/lib/public/modules/sidebar-sessions.js +1 -0
  376. package/lib/public/modules/split-group-restore.js +68 -0
  377. package/lib/public/modules/split-pair-ui.js +1 -0
  378. package/lib/public/modules/split-pane-reconciler.js +15 -0
  379. package/lib/public/modules/split-pane-renderer.js +87 -6
  380. package/lib/public/modules/split-session-boundary.js +1 -1
  381. package/lib/public/modules/split-view.js +60 -68
  382. package/lib/public/modules/sticky-note-markdown.js +72 -6
  383. package/lib/public/modules/sticky-notes-actions.js +30 -0
  384. package/lib/public/modules/sticky-notes-browser.js +9 -2
  385. package/lib/public/modules/sticky-notes-card.js +23 -7
  386. package/lib/public/modules/sticky-notes-checklist.js +116 -0
  387. package/lib/public/modules/sticky-notes-editor.js +108 -44
  388. package/lib/public/modules/sticky-notes-shared.js +50 -2
  389. package/lib/public/modules/sticky-notes-state.js +66 -0
  390. package/lib/public/modules/sticky-notes.js +34 -51
  391. package/lib/public/modules/stt-controller.js +4 -1
  392. package/lib/public/modules/stt-recording.js +1 -1
  393. package/lib/public/modules/stt.js +7 -2
  394. package/lib/public/modules/terminal.js +9 -0
  395. package/lib/public/modules/theme.js +8 -1
  396. package/lib/public/modules/thinking-lifecycle.js +33 -3
  397. package/lib/public/modules/thinking-view.js +23 -1
  398. package/lib/public/modules/tools.js +60 -11
  399. package/lib/public/modules/tui-grab.js +1 -2
  400. package/lib/public/modules/user-settings-appearance.js +10 -3
  401. package/lib/public/modules/user-settings-editors.js +1 -1
  402. package/lib/public/modules/user-settings-layout.js +11 -2
  403. package/lib/public/modules/user-settings-preferences.js +6 -2
  404. package/lib/public/modules/user-settings-profile.js +12 -2
  405. package/lib/public/modules/user-settings.js +3 -2
  406. package/lib/public/modules/vendor-login-browser.js +5 -3
  407. package/lib/public/modules/vendor-login.js +2 -2
  408. package/lib/public/modules/vendor-priority.js +15 -1
  409. package/lib/public/modules/wireframe-workbench.js +5 -2
  410. package/lib/public/muse-avatar.svg +4 -0
  411. package/lib/public/style.css +5 -0
  412. package/lib/public/sw.js +3 -1
  413. package/lib/safe-bash-commands.js +3 -45
  414. package/lib/scheduled-task-records.js +3 -1
  415. package/lib/scheduler.js +2 -0
  416. package/lib/sdk-bridge.js +342 -401
  417. package/lib/sdk-foreground-admission.js +16 -0
  418. package/lib/sdk-mcp-descriptors.js +2 -37
  419. package/lib/sdk-message-processor.js +52 -17
  420. package/lib/sdk-quota-snapshot.js +1 -1
  421. package/lib/sdk-response-recovery.js +1 -0
  422. package/lib/sdk-worker.js +2 -677
  423. package/lib/server-admin.js +63 -16
  424. package/lib/server-appearance-settings.js +13 -1
  425. package/lib/server-contextual-clay-settings.js +40 -0
  426. package/lib/server-contextual-mate-sessions.js +70 -0
  427. package/lib/server-dm.js +2 -1
  428. package/lib/server-global-ws.js +10 -20
  429. package/lib/server-home-chat-events.js +18 -4
  430. package/lib/server-home-chat.js +22 -20
  431. package/lib/server-home-clay-entry.js +23 -4
  432. package/lib/server-home-clay-session-links.js +29 -9
  433. package/lib/server-home-mate-creation.js +1 -0
  434. package/lib/server-home-mcp-consent.js +14 -0
  435. package/lib/server-mates.js +25 -62
  436. package/lib/server-owner-ui.js +118 -0
  437. package/lib/server-path-access.js +38 -0
  438. package/lib/server-project-removal.js +22 -0
  439. package/lib/server-settings.js +6 -1
  440. package/lib/server.js +163 -43
  441. package/lib/session-config-transition.js +45 -0
  442. package/lib/session-folders.js +7 -2
  443. package/lib/session-fork-history.js +21 -0
  444. package/lib/session-github.js +9 -2
  445. package/lib/session-hygiene.js +3 -35
  446. package/lib/session-permission-mode.js +4 -3
  447. package/lib/session-skill-scope.js +11 -0
  448. package/lib/session-visibility.js +5 -2
  449. package/lib/session-work-primary.js +50 -0
  450. package/lib/sessions.js +64 -99
  451. package/lib/shared-browser-cookie-sync.js +32 -0
  452. package/lib/shared-browser-cookies.js +79 -0
  453. package/lib/shared-browser-runtime.js +25 -9
  454. package/lib/shared-browser-storage-sync.js +43 -0
  455. package/lib/shared-browser-storage.js +101 -0
  456. package/lib/shared-browser-tools.js +2 -1
  457. package/lib/shared-browser-worker.js +46 -10
  458. package/lib/terminal-manager.js +65 -6
  459. package/lib/tool-llm.js +1 -1
  460. package/lib/tui-transcript-index.js +1 -132
  461. package/lib/users-contextual-clay-preferences.js +31 -0
  462. package/lib/users-permissions.js +2 -8
  463. package/lib/users.js +7 -0
  464. package/lib/vendor-login-browser.js +1 -11
  465. package/lib/workspace-assignment-service.js +25 -0
  466. package/lib/workspace-query-access.js +4 -1
  467. package/lib/workspace-query-mcp-server.js +1 -1
  468. package/lib/workspace-query-service.js +13 -2
  469. package/lib/ws-request.js +1 -0
  470. package/lib/ws-schema.js +18 -2
  471. package/lib/yoke/acp-agent-profiles.js +7 -5
  472. package/lib/yoke/adapters/antigravity.js +3 -14
  473. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  474. package/lib/yoke/adapters/claude.js +54 -50
  475. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  476. package/lib/yoke/adapters/codex.js +53 -111
  477. package/lib/yoke/adapters/kiro.js +3 -1
  478. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  479. package/lib/yoke/adapters/muse.js +122 -0
  480. package/lib/yoke/auth-events.js +17 -0
  481. package/lib/yoke/claude-hook-installer.js +271 -0
  482. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  483. package/lib/yoke/claude-maintenance.js +55 -0
  484. package/lib/yoke/claude-permission-patterns.js +53 -0
  485. package/lib/yoke/claude-response-recovery.js +155 -0
  486. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  487. package/lib/yoke/claude-worker-startup.js +28 -0
  488. package/lib/yoke/clay-skill-install.js +33 -0
  489. package/lib/yoke/cli-sessions.js +300 -0
  490. package/lib/yoke/codex-app-server.js +7 -12
  491. package/lib/yoke/codex-idle-recovery.js +81 -1
  492. package/lib/yoke/codex-recovery-admission.js +164 -0
  493. package/lib/yoke/configuration.js +13 -0
  494. package/lib/yoke/discovery.js +70 -0
  495. package/lib/yoke/errors.js +8 -0
  496. package/lib/yoke/host-environment.js +7 -0
  497. package/lib/yoke/index.js +9 -51
  498. package/lib/yoke/interface.js +116 -0
  499. package/lib/yoke/kiro-acp-server.js +5 -5
  500. package/lib/yoke/legacy-sessions.js +89 -0
  501. package/lib/yoke/login-protocol.js +25 -0
  502. package/lib/yoke/maintenance.js +12 -0
  503. package/lib/yoke/mcp-proxy.js +32 -0
  504. package/lib/yoke/mcp-source-adapters.js +91 -0
  505. package/lib/yoke/mcp-source-context.js +42 -0
  506. package/lib/yoke/mcp-source-discovery.js +169 -0
  507. package/lib/yoke/mcp-source-plugins.js +68 -0
  508. package/lib/yoke/mcp-source-restrictions.js +47 -0
  509. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  510. package/lib/yoke/model-preferences.js +6 -0
  511. package/lib/yoke/muse-artifacts.js +36 -0
  512. package/lib/yoke/muse-controls.js +50 -0
  513. package/lib/yoke/muse-input.js +64 -0
  514. package/lib/yoke/muse-items.js +157 -0
  515. package/lib/yoke/muse-policy.js +52 -0
  516. package/lib/yoke/muse-query.js +428 -0
  517. package/lib/yoke/muse-runtime.js +211 -0
  518. package/lib/yoke/muse-services.js +79 -0
  519. package/lib/yoke/muse-skills.js +79 -0
  520. package/lib/yoke/muse-turns.js +71 -0
  521. package/lib/yoke/options/acp.js +2 -0
  522. package/lib/yoke/options/antigravity.js +2 -0
  523. package/lib/yoke/options/claude.js +21 -0
  524. package/lib/yoke/options/codex-defaults.js +29 -0
  525. package/lib/yoke/options/codex-settings.js +21 -0
  526. package/lib/yoke/options/codex.js +6 -0
  527. package/lib/yoke/options/kiro-defaults.js +22 -0
  528. package/lib/yoke/options/kiro.js +5 -0
  529. package/lib/yoke/options/muse.js +5 -0
  530. package/lib/yoke/provider-contract.js +5 -0
  531. package/lib/yoke/providers/antigravity-executable.js +8 -0
  532. package/lib/yoke/providers/claude-executable.js +40 -0
  533. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  534. package/lib/yoke/providers/claude-process.js +97 -0
  535. package/lib/yoke/providers/claude-provision.js +75 -0
  536. package/lib/yoke/providers/codex-errors.js +8 -0
  537. package/lib/yoke/providers/muse-executable.js +17 -0
  538. package/lib/yoke/provisioning.js +6 -0
  539. package/lib/yoke/query-options.js +10 -0
  540. package/lib/yoke/response-recovery.js +41 -0
  541. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  542. package/lib/yoke/sdk-server-factory.js +7 -0
  543. package/lib/yoke/session-history.js +8 -0
  544. package/lib/yoke/session-tool-transport.js +34 -13
  545. package/lib/yoke/settings.js +23 -0
  546. package/lib/yoke/source-locations.js +4 -0
  547. package/lib/yoke/title-query.js +18 -7
  548. package/lib/yoke/tui-transcript-index.js +132 -0
  549. package/lib/yoke/usage.js +48 -0
  550. package/lib/yoke/user-input.js +13 -0
  551. package/lib/yoke/vendor-registry.js +81 -1
  552. package/package.json +10 -4
@@ -1,3 +1,6 @@
1
+ import { registerStudioPaint } from './clay-studio-render.js';
2
+ import { browserLinkTarget, initBrowserLinks } from './clay-browser-links.js';
3
+ import { browserSettingsHtml, bindBrowserSettings, renderBrowserSettings, closeBrowserSettings, handleBrowserSettingsMessage } from './shared-browser-settings.js';
1
4
  import { renderBrowserTabs } from './shared-browser-tabs.js';
2
5
  import { store } from './store.js';
3
6
  import { getWs } from './ws-ref.js';
@@ -50,15 +53,15 @@ function ensurePanel() {
50
53
  el.className = 'shared-browser-panel hidden';
51
54
  el.setAttribute('aria-label', 'Shared browser');
52
55
  el.innerHTML = '<header class="shared-browser-header"><span class="shared-browser-title">' + iconHtml('globe') + 'Browser</span><span class="shared-browser-phase" role="status">Ready</span><div class="shared-browser-window">' +
53
- iconButton('wide', 'chevrons-left-right', 'Widen browser panel') + iconButton('fullscreen', 'maximize-2', 'Toggle browser fullscreen') + iconButton('hide', 'x', 'Hide browser panel') + '</div></header>' +
56
+ iconButton('settings', 'settings-2', 'Browser settings') + iconButton('wide', 'chevrons-left-right', 'Widen browser panel') + iconButton('fullscreen', 'maximize-2', 'Toggle browser fullscreen') + iconButton('hide', 'x', 'Hide browser panel') + '</div></header>' +
54
57
  '<div class="shared-browser-tabs" role="tablist" aria-label="Browser tabs"></div><form class="shared-browser-address">' + iconButton('back', 'arrow-left', 'Back') + iconButton('forward', 'arrow-right', 'Forward') + iconButton('reload', 'rotate-cw', 'Reload') +
55
58
  '<input aria-label="Browser address" placeholder="Enter a URL" type="text" autocomplete="off" spellcheck="false"><button type="submit" aria-label="Open address">' + iconHtml('arrow-right') + '</button></form>' +
56
- '<div class="shared-browser-viewport"><div class="shared-browser-monitor"><div class="shared-browser-pointer-layer" aria-hidden="true"><div class="shared-browser-pointer" hidden><svg viewBox="0 0 24 28"><path d="M3 2 L3 22 L8 17 L12 26 L16 24 L12 15 L20 15 Z"/></svg><i></i></div></div><canvas width="1280" height="800" tabindex="0" aria-label="Shared browser page"></canvas>' +
57
- '<div class="shared-browser-empty">' + iconHtml('globe') + '<h3>A browser you can share with your Driver</h3><p>Enter an address to browse together.<br>Localhost connects to the Clay host.</p><p class="shared-browser-private">Cookies last only for this browser session.</p></div>' +
59
+ browserSettingsHtml() + '<div class="shared-browser-viewport"><div class="shared-browser-monitor"><div class="shared-browser-pointer-layer" aria-hidden="true"><div class="shared-browser-pointer" hidden><svg viewBox="0 0 24 28"><path d="M3 2 L3 22 L8 17 L12 26 L16 24 L12 15 L20 15 Z"/></svg><i></i></div></div><canvas width="1280" height="800" tabindex="0" aria-label="Shared browser page"></canvas>' +
60
+ '<div class="shared-browser-empty">' + iconHtml('globe') + '<h3>A browser you can use with Clay</h3><p>Enter an address to browse together.<br>Localhost connects to the Clay host.</p><p class="shared-browser-private">Site data lasts only for this browser session.</p></div>' +
58
61
  '<textarea class="shared-browser-keyboard" aria-label="Type into shared browser" autocomplete="off" autocapitalize="off" spellcheck="false"></textarea><span class="shared-browser-monitor-brand" aria-hidden="true">Clay Studio</span><span class="shared-browser-monitor-detail" aria-hidden="true"></span><span class="shared-browser-monitor-stand" aria-hidden="true"></span></div><div class="shared-browser-caption"><span class="shared-browser-monitor-label"></span>' + activityHtml() + '</div></div>' +
59
62
  '<p class="shared-browser-error hidden" role="status"></p>' +
60
63
  '<footer class="shared-browser-footer"><div class="shared-browser-control"><span class="shared-browser-control-status" role="status" aria-live="polite">You and Clay can control this browser</span><button type="button" data-action="control" aria-pressed="false"></button></div>' +
61
- '<div class="shared-browser-details">' + viewportMenuHtml() + '<button type="button" data-action="end">End browser</button></div></footer>';
64
+ '<div class="shared-browser-details"><span class="shared-browser-cookie-mode"></span>' + viewportMenuHtml() + '<button type="button" data-action="end">End browser</button></div></footer>';
62
65
  root.appendChild(el);
63
66
  el.querySelector('[data-action="hide"]').onclick = hideSharedBrowser;
64
67
  el.querySelector('[data-action="wide"]').onclick = function () { var wide = !(store.get('sharedBrowserUi') || {}).wide; ui({ wide: wide }); render(); };
@@ -69,8 +72,9 @@ function ensurePanel() {
69
72
  var browser = store.get('sharedBrowser');
70
73
  if (browser) send('control', { control: browser.control === 'user' ? 'agent' : 'user' });
71
74
  };
72
- el.querySelector('[data-action="end"]').onclick = function () { var browser = store.get('sharedBrowser'); send(browser && browser.phase === 'ended' ? 'open' : 'end'); };
75
+ el.querySelector('[data-action="end"]').onclick = function () { var browser = store.get('sharedBrowser'); send(browser && browser.phase === 'ended' ? 'open' : 'end', browser && browser.phase === 'ended' ? { incognito: browser.incognito } : undefined); };
73
76
  bindViewportMenu(el);
77
+ bindBrowserSettings(el);
74
78
  var observer = new ResizeObserver(layoutMonitor);
75
79
  observer.observe(el.querySelector('.shared-browser-viewport'));
76
80
  bindBrowserInput(el.querySelector('canvas'), el.querySelector('textarea'));
@@ -141,11 +145,16 @@ function render() {
141
145
  el.querySelector('[data-action="control"]').hidden = !live;
142
146
  el.querySelector('[data-action="end"]').disabled = !browser || !connected;
143
147
  el.querySelector('[data-action="end"]').textContent = browser && browser.phase === 'ended' ? 'New browser' : 'End browser';
148
+ var personal = browser && browser.incognito === false;
149
+ el.querySelector('.shared-browser-cookie-mode').textContent = personal ? 'Personal browser' : 'Incognito';
150
+ el.querySelector('.shared-browser-cookie-mode').title = personal ? 'Cookies and site storage are saved for your account across your Mates.' : 'Cookies and site storage are isolated and discarded when this tab ends.';
151
+ el.querySelector('.shared-browser-private').textContent = personal ? 'Your cookies and site storage are remembered across your Mates and browser restarts.' : 'Site data lasts only for this browser session.';
144
152
  var error = state.error || (browser && browser.error) || '';
145
153
  el.querySelector('.shared-browser-error').textContent = error;
146
154
  el.querySelector('.shared-browser-error').classList.toggle('hidden', !error);
147
155
  el.querySelector('.shared-browser-empty').classList.toggle('hidden', !!(browser && browser.url && state.hasFrame));
148
156
  renderViewportMenu(el, browser, operable);
157
+ renderBrowserSettings();
149
158
  renderBrowserActivity(el, browser, connected);
150
159
  layoutMonitor();
151
160
  }
@@ -163,6 +172,16 @@ function selectBrowserTab(id) {
163
172
  setBrowserTab(browser);
164
173
  send('view', { visible: desktop() && !document.hidden }); render();
165
174
  }
175
+ export function openSharedBrowserAt(value) {
176
+ var url = browserLinkTarget('browser:' + value);
177
+ if (!url) throw new Error('Enter a valid HTTP or HTTPS browser address.');
178
+ if (!desktop()) throw new Error('Clay Browser is available on desktop screens.');
179
+ if (!eligible()) throw new Error('Browser access is unavailable in this conversation.');
180
+ if (!store.get('connected')) throw new Error('Reconnect before opening this browser link.');
181
+ ensurePanel(); closeBrowserSettings(false);
182
+ claimRightWorkbench('browser'); store.set({ sharedBrowserOpen: true });
183
+ ui({ error: '' }); send('open', { url: url }); render();
184
+ }
166
185
  export function openSharedBrowser() {
167
186
  if (!eligible() || !store.get('connected')) return;
168
187
  ensurePanel();
@@ -175,6 +194,7 @@ export function openSharedBrowser() {
175
194
  }
176
195
  export function hideSharedBrowser() {
177
196
  closeViewportMenu();
197
+ closeBrowserSettings();
178
198
  clearBrowserInput();
179
199
  if (store.get('sharedBrowserOpen')) send('view', { visible: false });
180
200
  store.set({ sharedBrowserOpen: false });
@@ -184,6 +204,7 @@ export function hideSharedBrowser() {
184
204
  export function handleSharedBrowserMessage(msg) {
185
205
  if (!msg.type || msg.type.indexOf('shared_browser_') !== 0) return false;
186
206
  if (String(msg.sessionId) !== String(store.get('activeSessionId'))) return true;
207
+ if (handleBrowserSettingsMessage(msg)) return true;
187
208
  if (msg.type === 'shared_browser_state') {
188
209
  var old = store.get('sharedBrowser');
189
210
  var tabs = msg.browsers || (msg.browser ? [msg.browser] : []);
@@ -209,6 +230,7 @@ export function handleSharedBrowserMessage(msg) {
209
230
  var canvas = panel().querySelector('canvas'); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight;
210
231
  canvas.getContext('2d').drawImage(image, 0, 0);
211
232
  ui({ decoding: false, hasFrame: true }); render();
233
+ registerStudioPaint(msg, canvas, null, canvas);
212
234
  }
213
235
  };
214
236
  image.onerror = function () { if (store.get('activeSessionId') === sessionId) ui({ decoding: false }); };
@@ -217,6 +239,7 @@ export function handleSharedBrowserMessage(msg) {
217
239
  return true;
218
240
  }
219
241
  export function initSharedBrowser() {
242
+ initBrowserLinks();
220
243
  var button = document.getElementById('shared-browser-btn');
221
244
  if (button) button.onclick = openSharedBrowser;
222
245
  var toggle = document.getElementById('shared-browser-toggle-btn');
@@ -233,7 +256,7 @@ registerRightWorkbench('browser', hideSharedBrowser);
233
256
  store.subscribe(function (state, previous) {
234
257
  if (state.currentSlug !== previous.currentSlug || state.activeSessionId !== previous.activeSessionId || state.myUserId !== previous.myUserId) {
235
258
  clearBrowserInput(); releaseRightWorkbench('browser');
236
- store.set({ sharedBrowser: null, sharedBrowsers: [], sharedBrowserOpen: false, sharedBrowserUi: {} });
259
+ store.set({ sharedBrowser: null, sharedBrowsers: [], sharedBrowserOpen: false, sharedBrowserUi: {}, sharedBrowserSettings: {} });
237
260
  if (state.connected) send('state_request');
238
261
  render();
239
262
  } else if (state.connected !== previous.connected) {
@@ -1,4 +1,5 @@
1
- import { openMateWorkspace, isMateWorkspace } from './project-mate-navigation.js';
1
+ import { contextualMate } from './contextual-mate-identity.js';
2
+ import { activateContextualMate, isMateWorkspace } from './project-mate-navigation.js';
2
3
  import { appendGithubWork } from './session-github.js';
3
4
  // sidebar-mobile.js - Mobile sheet overlays, tab bar, and mobile-specific rendering
4
5
  // Extracted from sidebar.js (PR-38)
@@ -258,7 +259,7 @@ function renderSheetSessions(listEl) {
258
259
  }
259
260
 
260
261
  var visibleChipMates = getCachedMates().filter(function (m) {
261
- return m && !m.archived;
262
+ return m && !m.archived && contextualMate(m.id);
262
263
  });
263
264
  var sortedChipMates = visibleChipMates.sort(function (a, b) {
264
265
  var aBuiltin = a.builtinKey ? 1 : 0;
@@ -327,7 +328,7 @@ function renderSheetSessions(listEl) {
327
328
  renderMobileSessionsInto(sessionListEl);
328
329
  } else if (type === "mate") {
329
330
  closeMobileSheet();
330
- openMateWorkspace(mateId);
331
+ activateContextualMate(mateId);
331
332
  }
332
333
 
333
334
  refreshIcons();
@@ -822,6 +822,7 @@ function createIconItem(p, currentSlug) {
822
822
  var el = document.createElement("a");
823
823
  var isActive = p.slug === currentSlug && !currentDmUserId;
824
824
  el.className = "icon-strip-item" + (isActive ? " active" : "");
825
+ el.dataset.controlRuntime = p.controlRuntimeId || "";
825
826
  el.href = "/p/" + p.slug + "/";
826
827
  el.dataset.slug = p.slug;
827
828
 
@@ -353,7 +353,7 @@ function renderSection(section, ctx, kind) {
353
353
  body.appendChild(empty);
354
354
  }
355
355
  var view = currentFolderState().view;
356
- var dateGroups = isFavorites ? null : groupUnitsByDate(section.units, view.sort, view.direction);
356
+ var dateGroups = isFavorites || view.showDateHeadings === false ? null : groupUnitsByDate(section.units, view.sort, view.direction);
357
357
  if (dateGroups) {
358
358
  for (var g = 0; g < dateGroups.length; g++) {
359
359
  var ids = groupRootSessionIds(dateGroups[g].units);
@@ -826,6 +826,7 @@ function renderSessionItem(s, options) {
826
826
  el.className = "session-item" + (displaySession.active ? " active" : "") + (isMatch ? " search-match" : "");
827
827
  if (itemOptions.worker) el.classList.add("session-worker-item");
828
828
  el.dataset.sessionId = s.id;
829
+ el.dataset.controlSessionOrigin = s.sessionOriginId || '';
829
830
 
830
831
  var textSpan = document.createElement("span");
831
832
  textSpan.className = "session-item-text";
@@ -0,0 +1,68 @@
1
+ import { store } from './store.js';
2
+ import { getWs } from './ws-ref.js';
3
+ import { getCachedSessions } from './sidebar-sessions.js';
4
+ import { isCurrentProjectSessionReady } from './split-session-boundary.js';
5
+ import { splitPanesMatchProject, reconcileRestoredSplit } from './project-activation.js';
6
+ import { splitGroupMemberIds } from './split-group-helpers.js';
7
+ import { splitPaneForSession } from './split-pane-reconciler.js';
8
+ import { clearProjectSplitState } from './split-session-boundary.js';
9
+
10
+ export function reconcileSplitIdentity(state, previous, host) {
11
+ var ownerChanged = (previous.authIdentityLoaded === true || state.splitIdentityHydrated) && state.myUserId !== previous.myUserId;
12
+ if (state.authIdentityLoaded && !state.splitIdentityHydrated) store.set({ splitIdentityHydrated: true });
13
+ if (state.currentSlug === previous.currentSlug && state.myUserId === previous.myUserId) return false;
14
+ Array.from(host.querySelectorAll('.split-pane-frame')).forEach(function (frame) {
15
+ if (frame.clayPane) frame.clayPane.suspend();
16
+ });
17
+ host.innerHTML = '';
18
+ if (ownerChanged) {
19
+ // This socket was authenticated as the previous owner. Fresh metadata on
20
+ // that connection cannot establish the replacement owner's pane boundary.
21
+ store.set({ splitIdentityBlockedSocket: getWs(), paneBindingSessions: [] });
22
+ clearProjectSplitState();
23
+ } else if (state.splitPanes) store.set({ splitPanes: null });
24
+ return true;
25
+ }
26
+
27
+ // The initial owner response can arrive after history and split metadata.
28
+ // Wait for it so identity cleanup cannot discard panes we just restored.
29
+ export function restoreSplitGroup(openGroup) {
30
+ var state = store.snap();
31
+ if (state.authIdentityLoaded === false || state.isMultiUserMode && !state.myUserId) return;
32
+ if (!isCurrentProjectSessionReady(state, getWs())) return;
33
+ var split = state.splitPanes;
34
+ if (split && !splitPanesMatchProject(split, state.currentSlug)) {
35
+ store.set({ splitPanes: null });
36
+ return;
37
+ }
38
+ if (state.paneMode) return;
39
+ if (split) {
40
+ var reconciliation = reconcileRestoredSplit(split, state.splitGroups);
41
+ if (reconciliation.action === "clear") {
42
+ store.set({ splitPanes: null });
43
+ return;
44
+ }
45
+ if (reconciliation.action === "rebuild") {
46
+ var rebuilt = reconciliation.group;
47
+ if (rebuilt.members.some(function (id) { return !getCachedSessions().some(function (session) { return session.id === id; }); })) {
48
+ store.set({ splitPanes: null });
49
+ return;
50
+ }
51
+ store.set({ splitPanes: {
52
+ groupId: rebuilt.id,
53
+ panes: splitGroupMemberIds(rebuilt).map(function (id) { return splitPaneForSession(id, state.currentSlug, getCachedSessions()); }),
54
+ } });
55
+ }
56
+ return;
57
+ }
58
+ var activeId = store.get('activeSessionId');
59
+ if (!activeId) return;
60
+ var groups = store.get('splitGroups') || [];
61
+ for (var i = 0; i < groups.length; i++) {
62
+ var members = groups[i].members || [];
63
+ if (members.indexOf(activeId) !== -1) {
64
+ openGroup(groups[i]);
65
+ return;
66
+ }
67
+ }
68
+ }
@@ -236,6 +236,7 @@ function sendSetPair(groupId, driverId) {
236
236
 
237
237
  export function syncPairChrome(host, split) {
238
238
  if (!host || !split || !split.groupId) return;
239
+ if (Array.from(host.querySelectorAll('.split-pane-frame')).some(function (frame) { return !!frame.dataset.requestedSessionId; })) return;
239
240
  var groups = store.get('splitGroups') || [];
240
241
  var group = null;
241
242
  for (var i = 0; i < groups.length; i++) {
@@ -2,6 +2,11 @@
2
2
  // (and their iframe browsing contexts) are reused by stable project/session
3
3
  // identity while metadata and visual order are refreshed.
4
4
 
5
+ export function splitPaneForSession(id, slug, sessions) {
6
+ var session = (sessions || []).find(function (item) { return item.id === id; });
7
+ return { slug: slug, sessionId: id, title: session && session.title || ('Session ' + id) };
8
+ }
9
+
5
10
  export function splitPaneIdentity(pane) {
6
11
  return String(pane && pane.slug || "") + "#" + String(pane && pane.sessionId || "");
7
12
  }
@@ -16,9 +21,19 @@ export function reconcileSplitPanes(host, panes, createPane, updatePane) {
16
21
  var pane = desired[pi];
17
22
  var key = splitPaneIdentity(pane);
18
23
  var paneEl = byKey.get(key);
24
+ if (!paneEl) {
25
+ for (var ci = 0; ci < existing.length; ci++) {
26
+ var candidate = existing[ci], frame = candidate.querySelector('.split-pane-frame');
27
+ if (!used.has(candidate) && frame && frame.dataset.projectSlug === pane.slug && frame.clayPane &&
28
+ !desired.some(function (item) { return splitPaneIdentity(item) === candidate.dataset.splitPaneKey; })) {
29
+ paneEl = candidate; break;
30
+ }
31
+ }
32
+ }
19
33
  if (!paneEl) paneEl = createPane(pane, pi);
20
34
  paneEl.dataset.splitPaneKey = key;
21
35
  updatePane(paneEl, pane, pi);
36
+ if (paneEl.style) paneEl.style.order = String(pi);
22
37
  used.add(paneEl);
23
38
  if (!paneEl.parentNode) host.appendChild(paneEl);
24
39
  }
@@ -6,6 +6,8 @@ import { formatTokens } from './app-panels.js';
6
6
  import { VENDOR_AVATARS, VENDOR_NAMES } from './app-rendering.js';
7
7
  import { createPermissionControl, bindPermissionControl, renderPermissionControl } from './permission-control.js';
8
8
  import { splitGroupRoles } from './split-group-helpers.js';
9
+ import { paneTarget, livePaneBinding, samePaneTarget } from './pane-binding.js';
10
+ import { syncPairChrome } from './split-pair-ui.js';
9
11
 
10
12
  function sessionById(sessionId) {
11
13
  var sessions = getCachedSessions() || [];
@@ -17,17 +19,31 @@ function paneUrl(pane) {
17
19
  return "/p/" + encodeURIComponent(pane.slug) + "/?pane=1&session=" + encodeURIComponent(pane.sessionId);
18
20
  }
19
21
 
22
+ function headerBindingStamp(frame) {
23
+ var live = frame.clayPane && frame.clayPane.identity();
24
+ return JSON.stringify([frame.dataset.sessionId, frame.dataset.sessionOriginId,
25
+ live && live.binding && live.binding.requestId, live && live.binding && live.binding.generation]);
26
+ }
27
+
20
28
  function startPaneRename(header, titleEl, pane) {
21
29
  if (header.querySelector(".split-pane-rename-input")) return;
22
30
  var input = document.createElement("input");
23
31
  input.type = "text"; input.className = "split-pane-rename-input"; input.value = pane.title;
24
32
  titleEl.style.display = "none"; header.insertBefore(input, titleEl); input.focus(); input.select();
25
33
  var done = false;
34
+ var section = header.parentNode, frame = section.querySelector('.split-pane-frame');
35
+ var origin = frame.dataset.sessionOriginId, binding = frame.clayPane && frame.clayPane.identity().binding, socket = getWs();
36
+ function current() {
37
+ var live = frame.clayPane && frame.clayPane.identity();
38
+ return header.isConnected && !header.inert && socket === getWs() && store.get('connected') &&
39
+ frame.dataset.sessionId === String(pane.sessionId) && frame.dataset.sessionOriginId === origin && !frame.dataset.requestedSessionId &&
40
+ (!frame.clayPane || livePaneBinding(frame) && live.binding === binding);
41
+ }
26
42
  function finish(commit) {
27
43
  if (done) return;
28
44
  done = true;
29
45
  var newTitle = input.value.trim(); input.remove(); titleEl.style.display = "";
30
- if (!commit || !newTitle || newTitle === pane.title) return;
46
+ if (!commit || !current() || !newTitle || newTitle === pane.title) return;
31
47
  pane.title = newTitle; titleEl.textContent = newTitle;
32
48
  var ws = getWs();
33
49
  if (ws && ws.readyState === 1) ws.send(JSON.stringify({ type: "rename_session", id: pane.sessionId, title: newTitle }));
@@ -37,6 +53,7 @@ function startPaneRename(header, titleEl, pane) {
37
53
  if (event.key === "Escape") { event.preventDefault(); finish(false); }
38
54
  });
39
55
  input.addEventListener("blur", function () { finish(true); });
56
+ header.addEventListener('clay-pane-retarget', function cancel() { finish(false); header.removeEventListener('clay-pane-retarget', cancel); });
40
57
  input.addEventListener("click", function (event) { event.stopPropagation(); });
41
58
  }
42
59
 
@@ -73,33 +90,97 @@ export function createSplitPane(pane, closePane) {
73
90
  var vendorIcon = document.createElement("img"); vendorIcon.className = "split-pane-vendor";
74
91
  vendorIcon.src = VENDOR_AVATARS[vendor] || VENDOR_AVATARS.claude; vendorIcon.alt = ""; vendorIcon.title = VENDOR_NAMES[vendor] || vendor; header.appendChild(vendorIcon);
75
92
  var title = document.createElement("span"); title.className = "split-pane-title"; title.textContent = pane.title; title.title = "Rename session";
76
- title.addEventListener("click", function () { startPaneRename(header, title, pane); }); header.appendChild(title);
93
+ title.addEventListener("click", function () { var current = sessionById(Number(paneEl.dataset.sessionId)); if (current) startPaneRename(header, title, { sessionId: current.id, title: current.title }); }); header.appendChild(title);
77
94
  var frame = document.createElement("iframe"); frame.className = "split-pane-frame"; frame.dataset.projectSlug = pane.slug;
78
95
  frame.dataset.sessionId = String(pane.sessionId); frame.src = paneUrl(pane); frame.title = pane.title;
96
+ frame.dataset.sessionOriginId = session && session.sessionOriginId || '';
97
+ header.addEventListener('pointerdown', function () { header.dataset.pointerSessionId = frame.dataset.sessionId; header.dataset.pointerBinding = headerBindingStamp(frame); });
98
+ header.addEventListener('click', function (event) {
99
+ if (frame.clayPane && (!livePaneBinding(frame) || event.detail && header.dataset.pointerBinding !== headerBindingStamp(frame))) {
100
+ event.preventDefault(); event.stopImmediatePropagation();
101
+ }
102
+ }, true);
103
+ ['keydown', 'keyup'].forEach(function (name) {
104
+ header.addEventListener(name, function (event) {
105
+ var stamp = headerBindingStamp(frame);
106
+ if (name === 'keydown' && !event.repeat) header.dataset.keyBinding = stamp;
107
+ if (header.inert || header.dataset.keyBinding !== stamp) { event.preventDefault(); event.stopImmediatePropagation(); }
108
+ }, true);
109
+ });
79
110
  var ctxChip = document.createElement("button"); ctxChip.type = "button"; ctxChip.className = "split-pane-context"; ctxChip.title = "Context usage";
80
111
  ctxChip.innerHTML = '<span class="split-pane-context-bar"><span class="split-pane-context-fill"></span></span><span class="split-pane-context-label"></span>';
81
- ctxChip.addEventListener("click", function () { if (frame.contentWindow) frame.contentWindow.postMessage({ type: "clay-pane-toggle-context" }, window.location.origin); }); header.appendChild(ctxChip);
112
+ ctxChip.addEventListener("click", function () { if (frame.contentWindow && (!frame.clayPane || livePaneBinding(frame))) frame.contentWindow.postMessage({ type: "clay-pane-toggle-context", paneBinding: frame.clayPane && frame.clayPane.identity().binding }, window.location.origin); }); header.appendChild(ctxChip);
82
113
  var fullAccess = createPermissionControl("split-pane-full-access hidden", "Driver session permission mode");
83
- updatePaneFullAccessButton(fullAccess, session); bindPermissionControl(fullAccess, function () { return permissionState(sessionById(pane.sessionId)); }); header.appendChild(fullAccess); header.insertBefore(fullAccess, ctxChip);
114
+ updatePaneFullAccessButton(fullAccess, session); bindPermissionControl(fullAccess, function () { return permissionState(sessionById(Number(paneEl.dataset.sessionId))); }); header.appendChild(fullAccess); header.insertBefore(fullAccess, ctxChip);
84
115
  var close = document.createElement("button"); close.type = "button"; close.className = "split-pane-close"; close.title = "Close pane"; close.setAttribute("aria-label", "Close pane"); close.innerHTML = iconHtml("x");
85
116
  close.dataset.sessionId = String(pane.sessionId); close.addEventListener("click", function () { closePane(Number(this.dataset.sessionId)); }); header.appendChild(close);
117
+ frame.addEventListener('clay-pane-ready', function () {
118
+ var id = Number(frame.dataset.requestedSessionId || frame.dataset.sessionId), current = sessionById(id);
119
+ var live = frame.clayPane && frame.clayPane.identity(), target = paneTarget(store.snap(), getCachedSessions(), id);
120
+ if (!current || !live || !live.ready || !samePaneTarget(target, live.binding) || live.sessionId !== id) return;
121
+ frame.dataset.sessionId = String(id); delete frame.dataset.requestedSessionId;
122
+ frame.dataset.sessionOriginId = live.binding.sessionOriginId;
123
+ updateSplitPaneMetadata(paneEl, { slug: frame.dataset.projectSlug, sessionId: id, title: current.title });
124
+ syncPairChrome(paneEl.parentNode, store.get('splitPanes'));
125
+ });
126
+ frame.addEventListener('clay-pane-activation-failed', function () {
127
+ var id = Number(frame.dataset.requestedSessionId || frame.dataset.sessionId);
128
+ var fallbackTarget = paneTarget(store.snap(), getCachedSessions(), id);
129
+ if (!fallbackTarget) { header.inert = true; return; }
130
+ frame.dataset.sessionOriginId = fallbackTarget.sessionOriginId;
131
+ frame.src = paneUrl({ slug: frame.dataset.projectSlug, sessionId: id });
132
+ frame.dataset.sessionId = String(id); delete frame.dataset.requestedSessionId;
133
+ });
86
134
  paneEl.appendChild(header); paneEl.appendChild(frame); return paneEl;
87
135
  }
88
136
 
89
137
  export function updateSplitPaneMetadata(paneEl, pane) {
90
138
  var session = sessionById(pane.sessionId); var header = paneEl.querySelector(".split-pane-header");
91
139
  var title = paneEl.querySelector(".split-pane-title"); var frame = paneEl.querySelector(".split-pane-frame"); var vendor = paneEl.querySelector(".split-pane-vendor");
140
+ var live = frame && frame.clayPane && frame.clayPane.identity();
141
+ var retarget = frame && (Number(frame.dataset.sessionId) !== pane.sessionId || frame.dataset.sessionOriginId !== (session && session.sessionOriginId || '') || frame.clayPane && (!live || !live.ready));
142
+ if (retarget && header) {
143
+ header.dispatchEvent(new Event('clay-pane-retarget'));
144
+ header.inert = true;
145
+ header.title = 'Loading conversation';
146
+ if (title) { title.style.display = ''; title.textContent = 'Loading conversation'; }
147
+ if (vendor) vendor.hidden = true;
148
+ var permission = paneEl.querySelector('.split-pane-full-access');
149
+ if (permission) permission.classList.add('hidden');
150
+ resetPaneContextChip(paneEl);
151
+ }
152
+ if (frame && frame.clayPane && retarget) {
153
+ var target = paneTarget(store.snap(), getCachedSessions(), pane.sessionId);
154
+ if (target && frame.clayPane.source === frame.contentWindow && frame.clayPane.document === frame.contentDocument && frame.clayPane.activate(pane.sessionId, false, target)) {
155
+ frame.dataset.requestedSessionId = String(pane.sessionId);
156
+ if (header) header.inert = true;
157
+ return;
158
+ }
159
+ frame.src = paneUrl(pane);
160
+ frame.dataset.sessionId = String(pane.sessionId); frame.dataset.projectSlug = pane.slug;
161
+ frame.dataset.sessionOriginId = session && session.sessionOriginId || '';
162
+ }
163
+ if (header) header.inert = false;
92
164
  paneEl.dataset.sessionId = String(pane.sessionId); paneEl.dataset.projectSlug = pane.slug;
93
165
  if (header) header.title = pane.title; if (title && title.style.display !== "none") title.textContent = pane.title; if (frame) frame.title = pane.title;
94
- if (vendor) { var vendorName = session && session.vendor || "claude"; vendor.src = VENDOR_AVATARS[vendorName] || VENDOR_AVATARS.claude; vendor.title = VENDOR_NAMES[vendorName] || vendorName; }
166
+ if (vendor) { vendor.hidden = false; var vendorName = session && session.vendor || "claude"; vendor.src = VENDOR_AVATARS[vendorName] || VENDOR_AVATARS.claude; vendor.title = VENDOR_NAMES[vendorName] || vendorName; }
167
+ updatePaneFullAccessButton(paneEl.querySelector('.split-pane-full-access'), session);
95
168
  var close = paneEl.querySelector(".split-pane-close");
96
169
  if (close) {
97
170
  close.dataset.sessionId = String(pane.sessionId); close.disabled = false; close.title = "Close pane"; close.setAttribute("aria-label", close.title);
98
171
  }
99
172
  }
100
173
 
174
+ function resetPaneContextChip(paneEl) {
175
+ var chip = paneEl.querySelector('.split-pane-context'); if (!chip) return;
176
+ chip.classList.remove('has-data'); chip.title = 'Context usage';
177
+ var fill = chip.querySelector('.split-pane-context-fill'), label = chip.querySelector('.split-pane-context-label');
178
+ if (fill) { fill.style.width = '0%'; fill.className = 'split-pane-context-fill'; }
179
+ if (label) label.textContent = '';
180
+ }
181
+
101
182
  export function updatePaneContextChip(paneEl, msg) {
102
- if (!paneEl) return; var chip = paneEl.querySelector(".split-pane-context"); if (!chip) return; var pct = msg.pct || 0; if (pct <= 0) return;
183
+ if (!paneEl) return; var chip = paneEl.querySelector(".split-pane-context"); if (!chip) return; var pct = msg.pct || 0; if (pct <= 0) { resetPaneContextChip(paneEl); return; }
103
184
  chip.classList.add("has-data"); var fill = chip.querySelector(".split-pane-context-fill"); var label = chip.querySelector(".split-pane-context-label");
104
185
  fill.style.width = Math.min(100, pct).toFixed(1) + "%"; fill.className = "split-pane-context-fill" + (msg.cls || ""); label.textContent = pct.toFixed(0) + "%";
105
186
  var tip = "Context " + pct.toFixed(0) + "% (" + formatTokens(msg.used || 0) + " / " + formatTokens(msg.win || 0) + " tokens)";
@@ -2,7 +2,7 @@ import { store } from './store.js';
2
2
  import { isProjectSessionReady } from './project-activation.js';
3
3
 
4
4
  export function isCurrentProjectSessionReady(state, socket) {
5
- return isProjectSessionReady(state, socket);
5
+ return socket !== state.splitIdentityBlockedSocket && isProjectSessionReady(state, socket);
6
6
  }
7
7
 
8
8
  export function clearProjectSplitState() {