clay-server 5.2.0-beta.1 → 5.2.0-beta.11

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 (608) hide show
  1. package/README.md +0 -4
  2. package/lib/account-auth-socket.js +1 -0
  3. package/lib/builtin-mates.js +19 -16
  4. package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
  5. package/lib/canonical-clay-record-authority.js +15 -0
  6. package/lib/canonical-clay-scheduling-authority.js +19 -0
  7. package/lib/claude-hook-installer.js +1 -239
  8. package/lib/claude-jsonl-watcher.js +1 -204
  9. package/lib/clay-control-presentation-binding.js +96 -0
  10. package/lib/clay-control-presentation.js +128 -0
  11. package/lib/clay-control-target-projection.js +26 -0
  12. package/lib/clay-mate-chat-receipts.js +26 -0
  13. package/lib/clay-mate-chat.js +88 -0
  14. package/lib/clay-mate-knowledge-input.js +26 -0
  15. package/lib/clay-mate-knowledge.js +95 -0
  16. package/lib/clay-mate-lifecycle.js +95 -0
  17. package/lib/clay-product-control-input.js +33 -0
  18. package/lib/clay-product-control-tools.js +52 -0
  19. package/lib/clay-product-control.js +250 -0
  20. package/lib/clay-project-lifecycle.js +154 -0
  21. package/lib/clay-project-record-input.js +44 -0
  22. package/lib/clay-project-records.js +84 -0
  23. package/lib/clay-scheduling-input.js +21 -0
  24. package/lib/clay-scheduling-receipts.js +26 -0
  25. package/lib/clay-scheduling.js +119 -0
  26. package/lib/clay-screen-controls.js +104 -0
  27. package/lib/clay-skill-install.js +1 -33
  28. package/lib/clay-vendor-usage.js +44 -0
  29. package/lib/clay-workspace-controls.js +84 -0
  30. package/lib/clay-workspace-input.js +17 -0
  31. package/lib/clay-workspace-receipts.js +26 -0
  32. package/lib/cli-sessions.js +1 -300
  33. package/lib/codex-defaults.js +1 -28
  34. package/lib/context-usage.js +3 -2
  35. package/lib/contextual-screen-snapshot.js +38 -0
  36. package/lib/daemon-project-access.js +11 -0
  37. package/lib/daemon-project-lifecycle-callbacks.js +15 -0
  38. package/lib/daemon-project-lifecycle.js +262 -0
  39. package/lib/daemon-projects.js +1 -1
  40. package/lib/daemon.js +78 -276
  41. package/lib/default-ai-runtime.js +4 -8
  42. package/lib/dm-digest-cursor.js +120 -0
  43. package/lib/email-mcp-server.js +1 -1
  44. package/lib/github-star-count.js +147 -0
  45. package/lib/issues-service.js +29 -15
  46. package/lib/kiro-defaults.js +1 -22
  47. package/lib/knowledge-db-import-validation.js +46 -0
  48. package/lib/knowledge-db-import.js +99 -0
  49. package/lib/knowledge-db-service.js +24 -33
  50. package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
  51. package/lib/knowledge-db-storage-nedb.js +66 -0
  52. package/lib/knowledge-db-storage.js +72 -0
  53. package/lib/knowledge-db-validation.js +0 -0
  54. package/lib/knowledge-document-index.js +2 -1
  55. package/lib/knowledge-file-store.js +7 -1
  56. package/lib/knowledge-product-operations.js +46 -0
  57. package/lib/mate-avatar-catalog.js +12 -0
  58. package/lib/mate-avatar-migration.js +41 -0
  59. package/lib/mate-context-service.js +138 -0
  60. package/lib/mate-context-tools.js +21 -0
  61. package/lib/mate-creation-mcp-server.js +2 -0
  62. package/lib/mate-knowledge-canonical-access.js +10 -0
  63. package/lib/mate-knowledge-mate-bound.js +53 -0
  64. package/lib/mate-knowledge-mcp-server.js +55 -8
  65. package/lib/mate-knowledge-service.js +16 -34
  66. package/lib/mate-knowledge-text-tools.js +106 -0
  67. package/lib/mate-lifecycle-service.js +94 -0
  68. package/lib/mate-message-delivery.js +43 -0
  69. package/lib/mate-ready-creation.js +9 -1
  70. package/lib/mate-schedule-input.js +29 -0
  71. package/lib/mate-schedule-lifecycle.js +151 -0
  72. package/lib/mate-scheduling.js +103 -0
  73. package/lib/mates.js +18 -6
  74. package/lib/mcp-agent-tools.js +117 -0
  75. package/lib/mcp-connection-store.js +119 -15
  76. package/lib/mcp-import-credentials.js +31 -0
  77. package/lib/mcp-local-transport.js +13 -0
  78. package/lib/mcp-oauth.js +8 -6
  79. package/lib/mcp-proxy.js +2 -32
  80. package/lib/mcp-query-bridge.js +30 -0
  81. package/lib/mcp-remote-connections.js +74 -20
  82. package/lib/mcp-source-adapters.js +1 -0
  83. package/lib/mcp-source-context.js +1 -0
  84. package/lib/mcp-source-discovery.js +1 -0
  85. package/lib/mcp-source-plugins.js +1 -0
  86. package/lib/mcp-source-restrictions.js +1 -0
  87. package/lib/mcp-tool-policy.js +9 -0
  88. package/lib/notes-checklist.js +92 -0
  89. package/lib/notes.js +51 -4
  90. package/lib/os-user-diagnostics.js +2 -4
  91. package/lib/os-users.js +24 -70
  92. package/lib/pane-pending-interactions.js +20 -0
  93. package/lib/pane-session-activation.js +114 -0
  94. package/lib/pane-session-transport.js +26 -0
  95. package/lib/project-admin-overview.js +51 -0
  96. package/lib/project-ask-user.js +8 -4
  97. package/lib/project-connection.js +14 -10
  98. package/lib/project-control-git-view.js +12 -0
  99. package/lib/project-debate.js +1 -0
  100. package/lib/project-delegated-follow-up.js +2 -1
  101. package/lib/project-directory-claim.js +65 -0
  102. package/lib/project-file-operations.js +61 -0
  103. package/lib/project-filesystem.js +15 -85
  104. package/lib/project-full-access.js +23 -2
  105. package/lib/project-http.js +7 -4
  106. package/lib/project-knowledge.js +32 -18
  107. package/lib/project-lifecycle-operations.js +98 -0
  108. package/lib/project-lifecycle-process-witness.js +32 -0
  109. package/lib/project-lifecycle-runtime.js +50 -0
  110. package/lib/project-linux-access.js +22 -0
  111. package/lib/project-logs-canonical-clay.js +27 -0
  112. package/lib/project-logs-clay-query.js +16 -0
  113. package/lib/project-logs-schema.js +4 -2
  114. package/lib/project-logs-service.js +8 -7
  115. package/lib/project-logs.js +1 -0
  116. package/lib/project-loop.js +1 -0
  117. package/lib/project-mate-chat-control.js +55 -0
  118. package/lib/project-mate-creation-proposal.js +18 -3
  119. package/lib/project-mate-interaction.js +40 -62
  120. package/lib/project-mcp.js +54 -16
  121. package/lib/project-models.js +14 -31
  122. package/lib/project-notifications.js +76 -17
  123. package/lib/project-ownership.js +77 -0
  124. package/lib/project-pair-result-delivery.js +14 -3
  125. package/lib/project-pair-usage.js +12 -13
  126. package/lib/project-pending-message-queue.js +4 -1
  127. package/lib/project-product-control.js +89 -0
  128. package/lib/project-product-session-queue.js +46 -0
  129. package/lib/project-push-access.js +28 -0
  130. package/lib/project-scheduled-message-queue.js +30 -0
  131. package/lib/project-scheduled-messages.js +67 -68
  132. package/lib/project-scheduled-task-control.js +83 -0
  133. package/lib/project-scheduled-tasks.js +13 -2
  134. package/lib/project-scheduling-access.js +10 -0
  135. package/lib/project-session-actions.js +65 -0
  136. package/lib/project-session-delete.js +8 -1
  137. package/lib/project-session-document.js +27 -7
  138. package/lib/project-session-github.js +63 -19
  139. package/lib/project-session-history-actions.js +167 -0
  140. package/lib/project-session-linear.js +14 -6
  141. package/lib/project-session-notes.js +40 -11
  142. package/lib/project-session-pair.js +1 -1
  143. package/lib/project-session-runtime-actions.js +64 -0
  144. package/lib/project-session-spawn.js +2 -3
  145. package/lib/project-session-vendor.js +55 -0
  146. package/lib/project-sessions.js +160 -290
  147. package/lib/project-shared-browser.js +78 -17
  148. package/lib/project-start-protocol.js +29 -0
  149. package/lib/project-studio-presentation.js +58 -0
  150. package/lib/project-user-message.js +67 -1
  151. package/lib/project-vendor-login.js +8 -36
  152. package/lib/project-workspace-operations.js +126 -0
  153. package/lib/project-workspace-query.js +19 -2
  154. package/lib/project.js +181 -45
  155. package/lib/public/app.js +71 -17
  156. package/lib/public/appearance-bootstrap.js +16 -0
  157. package/lib/public/css/clay-tool-activity.css +51 -0
  158. package/lib/public/css/clay-workspace.css +29 -0
  159. package/lib/public/css/command-palette.css +12 -33
  160. package/lib/public/css/contextual-clay.css +240 -0
  161. package/lib/public/css/filebrowser.css +1 -1
  162. package/lib/public/css/home-debate-planning.css +2 -0
  163. package/lib/public/css/home-mate-creation.css +5 -0
  164. package/lib/public/css/input.css +6 -0
  165. package/lib/public/css/mate-avatar-gallery.css +12 -0
  166. package/lib/public/css/mate-conversation.css +10 -5
  167. package/lib/public/css/mate-loading-scene.css +21 -0
  168. package/lib/public/css/messages.css +6 -2
  169. package/lib/public/css/overlays.css +68 -258
  170. package/lib/public/css/project-admin-overview.css +13 -0
  171. package/lib/public/css/project-mate-creation.css +5 -6
  172. package/lib/public/css/project-start.css +108 -0
  173. package/lib/public/css/projects-hub.css +53 -14
  174. package/lib/public/css/session-folders.css +11 -0
  175. package/lib/public/css/session-github.css +46 -1
  176. package/lib/public/css/settings-shell.css +103 -0
  177. package/lib/public/css/shared-browser.css +35 -1
  178. package/lib/public/css/sidebar.css +7 -0
  179. package/lib/public/css/sticky-notes.css +87 -1
  180. package/lib/public/css/title-bar.css +79 -0
  181. package/lib/public/index.html +61 -68
  182. package/lib/public/mate-avatars/B01.png +0 -0
  183. package/lib/public/mate-avatars/B02.png +0 -0
  184. package/lib/public/mate-avatars/B03.png +0 -0
  185. package/lib/public/mate-avatars/B04.png +0 -0
  186. package/lib/public/mate-avatars/B05.png +0 -0
  187. package/lib/public/mate-avatars/B06.png +0 -0
  188. package/lib/public/mate-avatars/B07.png +0 -0
  189. package/lib/public/mate-avatars/B08.png +0 -0
  190. package/lib/public/mate-avatars/B09.png +0 -0
  191. package/lib/public/mate-avatars/B10.png +0 -0
  192. package/lib/public/mate-avatars/B11.png +0 -0
  193. package/lib/public/mate-avatars/B12.png +0 -0
  194. package/lib/public/mate-avatars/B13.png +0 -0
  195. package/lib/public/mate-avatars/B14.png +0 -0
  196. package/lib/public/mate-avatars/B15.png +0 -0
  197. package/lib/public/mate-avatars/B16.png +0 -0
  198. package/lib/public/mate-avatars/B17.png +0 -0
  199. package/lib/public/mate-avatars/B18.png +0 -0
  200. package/lib/public/mate-avatars/B19.png +0 -0
  201. package/lib/public/mate-avatars/B20.png +0 -0
  202. package/lib/public/mate-avatars/B21.png +0 -0
  203. package/lib/public/mate-avatars/B22.png +0 -0
  204. package/lib/public/mate-avatars/B23.png +0 -0
  205. package/lib/public/mate-avatars/B24.png +0 -0
  206. package/lib/public/mate-avatars/B25.png +0 -0
  207. package/lib/public/mate-avatars/B26.png +0 -0
  208. package/lib/public/mate-avatars/B27.png +0 -0
  209. package/lib/public/mate-avatars/B28.png +0 -0
  210. package/lib/public/mate-avatars/B29.png +0 -0
  211. package/lib/public/mate-avatars/B30.png +0 -0
  212. package/lib/public/mate-avatars/B31.png +0 -0
  213. package/lib/public/mate-avatars/B32.png +0 -0
  214. package/lib/public/mate-avatars/B33.png +0 -0
  215. package/lib/public/mate-avatars/B34.png +0 -0
  216. package/lib/public/mate-avatars/B35.png +0 -0
  217. package/lib/public/mate-avatars/B36.png +0 -0
  218. package/lib/public/mate-avatars/B37.png +0 -0
  219. package/lib/public/mate-avatars/B38.png +0 -0
  220. package/lib/public/mate-avatars/B39.png +0 -0
  221. package/lib/public/mate-avatars/B40.png +0 -0
  222. package/lib/public/mate-avatars/B41.png +0 -0
  223. package/lib/public/mate-avatars/B42.png +0 -0
  224. package/lib/public/mate-avatars/B43.png +0 -0
  225. package/lib/public/mate-avatars/B44.png +0 -0
  226. package/lib/public/mate-avatars/B45.png +0 -0
  227. package/lib/public/mate-avatars/B46.png +0 -0
  228. package/lib/public/mate-avatars/B47.png +0 -0
  229. package/lib/public/mate-avatars/B48.png +0 -0
  230. package/lib/public/mate-avatars/C01.png +0 -0
  231. package/lib/public/mate-avatars/C02.png +0 -0
  232. package/lib/public/mate-avatars/C03.png +0 -0
  233. package/lib/public/mate-avatars/C04.png +0 -0
  234. package/lib/public/mate-avatars/C05.png +0 -0
  235. package/lib/public/mate-avatars/C06.png +0 -0
  236. package/lib/public/mate-avatars/C07.png +0 -0
  237. package/lib/public/mate-avatars/C08.png +0 -0
  238. package/lib/public/mate-avatars/C09.png +0 -0
  239. package/lib/public/mate-avatars/C10.png +0 -0
  240. package/lib/public/mate-avatars/C11.png +0 -0
  241. package/lib/public/mate-avatars/C12.png +0 -0
  242. package/lib/public/mate-avatars/C13.png +0 -0
  243. package/lib/public/mate-avatars/C14.png +0 -0
  244. package/lib/public/mate-avatars/C15.png +0 -0
  245. package/lib/public/mate-avatars/C16.png +0 -0
  246. package/lib/public/mate-avatars/C17.png +0 -0
  247. package/lib/public/mate-avatars/C18.png +0 -0
  248. package/lib/public/mate-avatars/C19.png +0 -0
  249. package/lib/public/mate-avatars/C20.png +0 -0
  250. package/lib/public/mate-avatars/C21.png +0 -0
  251. package/lib/public/mate-avatars/C22.png +0 -0
  252. package/lib/public/mate-avatars/C23.png +0 -0
  253. package/lib/public/mate-avatars/C24.png +0 -0
  254. package/lib/public/mate-avatars/C25.png +0 -0
  255. package/lib/public/mate-avatars/C26.png +0 -0
  256. package/lib/public/mate-avatars/C27.png +0 -0
  257. package/lib/public/mate-avatars/C28.png +0 -0
  258. package/lib/public/mate-avatars/C29.png +0 -0
  259. package/lib/public/mate-avatars/C30.png +0 -0
  260. package/lib/public/mate-avatars/C31.png +0 -0
  261. package/lib/public/mate-avatars/C32.png +0 -0
  262. package/lib/public/mate-avatars/C33.png +0 -0
  263. package/lib/public/mate-avatars/C34.png +0 -0
  264. package/lib/public/mate-avatars/C35.png +0 -0
  265. package/lib/public/mate-avatars/C36.png +0 -0
  266. package/lib/public/mate-avatars/C37.png +0 -0
  267. package/lib/public/mate-avatars/C38.png +0 -0
  268. package/lib/public/mate-avatars/C39.png +0 -0
  269. package/lib/public/mate-avatars/C40.png +0 -0
  270. package/lib/public/mate-avatars/C41.png +0 -0
  271. package/lib/public/mate-avatars/C42.png +0 -0
  272. package/lib/public/mate-avatars/C43.png +0 -0
  273. package/lib/public/mate-avatars/C44.png +0 -0
  274. package/lib/public/mate-avatars/C45.png +0 -0
  275. package/lib/public/mate-avatars/C46.png +0 -0
  276. package/lib/public/mate-avatars/C47.png +0 -0
  277. package/lib/public/mate-avatars/C48.png +0 -0
  278. package/lib/public/mate-avatars/catalog.json +482 -0
  279. package/lib/public/mate-avatars/lead-clay.png +0 -0
  280. package/lib/public/modules/admin-settings-invitations.js +2 -2
  281. package/lib/public/modules/admin-settings-projects.js +8 -4
  282. package/lib/public/modules/admin-settings-ui.js +20 -4
  283. package/lib/public/modules/admin-settings-users.js +4 -4
  284. package/lib/public/modules/app-connection.js +11 -1
  285. package/lib/public/modules/app-favicon.js +18 -9
  286. package/lib/public/modules/app-header.js +7 -4
  287. package/lib/public/modules/app-home-hub.js +2 -1
  288. package/lib/public/modules/app-loop-ui.js +2 -0
  289. package/lib/public/modules/app-message-router.js +22 -1
  290. package/lib/public/modules/app-messages.js +125 -19
  291. package/lib/public/modules/app-misc.js +3 -1
  292. package/lib/public/modules/app-notifications.js +11 -5
  293. package/lib/public/modules/app-panels.js +61 -123
  294. package/lib/public/modules/app-projects.js +14 -407
  295. package/lib/public/modules/app-rate-limit.js +19 -28
  296. package/lib/public/modules/app-rendering.js +4 -3
  297. package/lib/public/modules/avatar.js +15 -41
  298. package/lib/public/modules/chat-render-runtime.js +20 -0
  299. package/lib/public/modules/clay-browser-links.js +47 -0
  300. package/lib/public/modules/clay-control-activity.js +214 -0
  301. package/lib/public/modules/clay-control-copy.js +36 -0
  302. package/lib/public/modules/clay-control-detail-targets.js +44 -0
  303. package/lib/public/modules/clay-control-object-targets.js +52 -0
  304. package/lib/public/modules/clay-control-target-visibility.js +12 -0
  305. package/lib/public/modules/clay-control-targets.js +44 -0
  306. package/lib/public/modules/clay-log-links.js +23 -0
  307. package/lib/public/modules/clay-navigation-render.js +52 -0
  308. package/lib/public/modules/clay-owner-navigation.js +33 -0
  309. package/lib/public/modules/clay-session-links.js +31 -0
  310. package/lib/public/modules/clay-studio-bridge.js +20 -0
  311. package/lib/public/modules/clay-studio-document.js +67 -0
  312. package/lib/public/modules/clay-studio-render.js +146 -0
  313. package/lib/public/modules/clay-tool-activity.js +140 -0
  314. package/lib/public/modules/clay-tool-presentation.js +343 -0
  315. package/lib/public/modules/command-palette.js +162 -40
  316. package/lib/public/modules/contextual-ask-session.js +26 -0
  317. package/lib/public/modules/contextual-clay-geometry.js +155 -0
  318. package/lib/public/modules/contextual-clay-session.js +130 -0
  319. package/lib/public/modules/contextual-clay-workspace.js +169 -0
  320. package/lib/public/modules/contextual-clay.js +252 -0
  321. package/lib/public/modules/contextual-composer.js +91 -0
  322. package/lib/public/modules/contextual-mate-context.js +117 -0
  323. package/lib/public/modules/contextual-mate-hint.js +40 -0
  324. package/lib/public/modules/contextual-mate-identity.js +23 -0
  325. package/lib/public/modules/contextual-mate-sessions.js +134 -0
  326. package/lib/public/modules/contextual-search.js +137 -0
  327. package/lib/public/modules/contextual-session-citations.js +58 -0
  328. package/lib/public/modules/debate.js +1 -0
  329. package/lib/public/modules/default-ai.js +11 -3
  330. package/lib/public/modules/elicitation-form.js +5 -0
  331. package/lib/public/modules/filebrowser.js +20 -1
  332. package/lib/public/modules/generation-stop.js +8 -5
  333. package/lib/public/modules/git-panel.js +3 -1
  334. package/lib/public/modules/github-star.js +66 -0
  335. package/lib/public/modules/history-replay-batch.js +13 -1
  336. package/lib/public/modules/home-debate-live.js +2 -0
  337. package/lib/public/modules/home-debate-planning.js +7 -7
  338. package/lib/public/modules/home-mate-avatar-editor.js +127 -208
  339. package/lib/public/modules/home-mate-chat.js +8 -6
  340. package/lib/public/modules/home-mate-creation.js +73 -1
  341. package/lib/public/modules/home-mate-settings.js +19 -12
  342. package/lib/public/modules/icon-strip-tooltip.js +2 -1
  343. package/lib/public/modules/input.js +88 -10
  344. package/lib/public/modules/issues-render.js +3 -2
  345. package/lib/public/modules/knowledge-db-workbench.js +4 -4
  346. package/lib/public/modules/markdown.js +6 -34
  347. package/lib/public/modules/mate-avatar-catalog.js +97 -0
  348. package/lib/public/modules/mate-knowledge-workbench.js +1 -1
  349. package/lib/public/modules/mate-loading-scene.js +17 -0
  350. package/lib/public/modules/mate-management.js +40 -7
  351. package/lib/public/modules/mcp-connection-view.js +31 -13
  352. package/lib/public/modules/mcp-discovery-view.js +31 -0
  353. package/lib/public/modules/mcp-ui.js +23 -4
  354. package/lib/public/modules/mention.js +3 -0
  355. package/lib/public/modules/message-delivery.js +20 -2
  356. package/lib/public/modules/model-picker.js +2 -0
  357. package/lib/public/modules/pane-activation.js +214 -0
  358. package/lib/public/modules/pane-binding.js +82 -0
  359. package/lib/public/modules/pane-bridge.js +7 -4
  360. package/lib/public/modules/pane-browser-bridge.js +22 -0
  361. package/lib/public/modules/pane-file-bridge.js +4 -0
  362. package/lib/public/modules/pane-issue-bridge.js +4 -1
  363. package/lib/public/modules/pending-message-queue.js +1 -0
  364. package/lib/public/modules/permission-control.js +5 -4
  365. package/lib/public/modules/personal-settings-dialog.js +7 -1
  366. package/lib/public/modules/product-review.js +26 -0
  367. package/lib/public/modules/profile.js +12 -241
  368. package/lib/public/modules/project-access-recovery.js +17 -0
  369. package/lib/public/modules/project-admin-overview.js +21 -0
  370. package/lib/public/modules/project-chat-identity.js +13 -4
  371. package/lib/public/modules/project-logs-render.js +3 -0
  372. package/lib/public/modules/project-mate-creation-workspace.js +13 -4
  373. package/lib/public/modules/project-mate-navigation.js +144 -22
  374. package/lib/public/modules/project-session-visibility-settings.js +19 -16
  375. package/lib/public/modules/project-settings.js +119 -129
  376. package/lib/public/modules/project-start-dialog.js +130 -0
  377. package/lib/public/modules/project-start-folder-state.js +78 -0
  378. package/lib/public/modules/project-start-folder-view.js +190 -0
  379. package/lib/public/modules/project-start-forms.js +66 -0
  380. package/lib/public/modules/project-start-path.js +60 -0
  381. package/lib/public/modules/project-start-state.js +54 -0
  382. package/lib/public/modules/project-start-submit.js +67 -0
  383. package/lib/public/modules/projects-hub-view.js +33 -14
  384. package/lib/public/modules/projects-hub.js +10 -6
  385. package/lib/public/modules/rewind.js +5 -0
  386. package/lib/public/modules/scheduled-tasks.js +2 -0
  387. package/lib/public/modules/scheduler.js +2 -0
  388. package/lib/public/modules/search-clay-chat.js +5 -440
  389. package/lib/public/modules/server-settings.js +36 -91
  390. package/lib/public/modules/session-actions.js +5 -2
  391. package/lib/public/modules/session-context-menu.js +5 -0
  392. package/lib/public/modules/session-create-form.js +10 -10
  393. package/lib/public/modules/session-folder-layout.js +1 -1
  394. package/lib/public/modules/session-folder-view-menu.js +9 -0
  395. package/lib/public/modules/session-github.js +85 -14
  396. package/lib/public/modules/session-rich-drafts.js +21 -0
  397. package/lib/public/modules/session-switch-defer.js +67 -0
  398. package/lib/public/modules/session-work-primary.js +51 -0
  399. package/lib/public/modules/settings-defaults.js +27 -28
  400. package/lib/public/modules/settings-project-target.js +56 -0
  401. package/lib/public/modules/settings-select.js +1 -1
  402. package/lib/public/modules/settings-shell-registry.js +88 -0
  403. package/lib/public/modules/settings-shell-view.js +104 -0
  404. package/lib/public/modules/settings-shell.js +342 -0
  405. package/lib/public/modules/shared-browser-settings.js +112 -0
  406. package/lib/public/modules/shared-browser-tabs.js +13 -3
  407. package/lib/public/modules/shared-browser.js +29 -6
  408. package/lib/public/modules/sidebar-mobile.js +12 -33
  409. package/lib/public/modules/sidebar-projects.js +3 -1
  410. package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
  411. package/lib/public/modules/sidebar-sessions.js +1 -0
  412. package/lib/public/modules/split-group-restore.js +68 -0
  413. package/lib/public/modules/split-pair-ui.js +1 -0
  414. package/lib/public/modules/split-pane-reconciler.js +15 -0
  415. package/lib/public/modules/split-pane-renderer.js +87 -6
  416. package/lib/public/modules/split-session-boundary.js +1 -1
  417. package/lib/public/modules/split-view.js +60 -68
  418. package/lib/public/modules/sticky-note-markdown.js +72 -6
  419. package/lib/public/modules/sticky-notes-actions.js +30 -0
  420. package/lib/public/modules/sticky-notes-browser.js +9 -2
  421. package/lib/public/modules/sticky-notes-card.js +23 -7
  422. package/lib/public/modules/sticky-notes-checklist.js +116 -0
  423. package/lib/public/modules/sticky-notes-editor.js +108 -44
  424. package/lib/public/modules/sticky-notes-shared.js +50 -2
  425. package/lib/public/modules/sticky-notes-state.js +66 -0
  426. package/lib/public/modules/sticky-notes.js +34 -51
  427. package/lib/public/modules/stt-controller.js +4 -1
  428. package/lib/public/modules/stt-recording.js +1 -1
  429. package/lib/public/modules/stt.js +7 -2
  430. package/lib/public/modules/terminal.js +9 -0
  431. package/lib/public/modules/theme.js +18 -3
  432. package/lib/public/modules/thinking-lifecycle.js +33 -3
  433. package/lib/public/modules/thinking-view.js +23 -1
  434. package/lib/public/modules/tools.js +60 -11
  435. package/lib/public/modules/tui-grab.js +1 -2
  436. package/lib/public/modules/user-settings-appearance.js +10 -3
  437. package/lib/public/modules/user-settings-editors.js +1 -1
  438. package/lib/public/modules/user-settings-layout.js +14 -30
  439. package/lib/public/modules/user-settings-preferences.js +6 -2
  440. package/lib/public/modules/user-settings-profile.js +13 -3
  441. package/lib/public/modules/user-settings.js +18 -84
  442. package/lib/public/modules/vendor-login-browser.js +5 -3
  443. package/lib/public/modules/vendor-login.js +2 -2
  444. package/lib/public/modules/vendor-priority.js +15 -1
  445. package/lib/public/modules/vendor-usage-format.js +93 -0
  446. package/lib/public/modules/vendor-usage-list.js +45 -0
  447. package/lib/public/modules/vendor-usage-model.js +215 -0
  448. package/lib/public/modules/vendor-usage-overview.js +312 -0
  449. package/lib/public/modules/wireframe-workbench.js +5 -2
  450. package/lib/public/muse-avatar.svg +4 -0
  451. package/lib/public/style.css +14 -6
  452. package/lib/public/sw.js +3 -1
  453. package/lib/public/welcome-art/conversation-desk.png +0 -0
  454. package/lib/public/welcome-art/mate-clay.png +0 -0
  455. package/lib/public/welcome-art/project-clay.png +0 -0
  456. package/lib/safe-bash-commands.js +3 -45
  457. package/lib/scheduled-task-records.js +3 -1
  458. package/lib/scheduler.js +2 -0
  459. package/lib/sdk-bridge.js +348 -402
  460. package/lib/sdk-foreground-admission.js +16 -0
  461. package/lib/sdk-mcp-descriptors.js +2 -37
  462. package/lib/sdk-message-processor.js +61 -18
  463. package/lib/sdk-quota-snapshot.js +21 -3
  464. package/lib/sdk-response-recovery.js +1 -0
  465. package/lib/sdk-worker.js +2 -677
  466. package/lib/server-admin.js +63 -16
  467. package/lib/server-appearance-settings.js +13 -1
  468. package/lib/server-contextual-clay-settings.js +40 -0
  469. package/lib/server-contextual-mate-sessions.js +70 -0
  470. package/lib/server-dm.js +2 -1
  471. package/lib/server-github-stars.js +39 -0
  472. package/lib/server-global-ws.js +26 -32
  473. package/lib/server-home-chat-events.js +18 -4
  474. package/lib/server-home-chat.js +22 -20
  475. package/lib/server-home-clay-entry.js +23 -4
  476. package/lib/server-home-clay-session-links.js +29 -9
  477. package/lib/server-home-mate-creation.js +1 -0
  478. package/lib/server-home-mcp-consent.js +14 -0
  479. package/lib/server-mates.js +25 -62
  480. package/lib/server-owner-ui.js +118 -0
  481. package/lib/server-path-access.js +38 -0
  482. package/lib/server-project-removal.js +22 -0
  483. package/lib/server-settings.js +6 -1
  484. package/lib/server.js +167 -43
  485. package/lib/session-config-transition.js +45 -0
  486. package/lib/session-folders.js +7 -2
  487. package/lib/session-fork-history.js +21 -0
  488. package/lib/session-github.js +9 -2
  489. package/lib/session-hygiene.js +3 -35
  490. package/lib/session-notes-mcp-server.js +26 -4
  491. package/lib/session-notes-writes.js +88 -0
  492. package/lib/session-permission-mode.js +4 -3
  493. package/lib/session-skill-scope.js +11 -0
  494. package/lib/session-visibility.js +25 -10
  495. package/lib/session-work-primary.js +50 -0
  496. package/lib/sessions.js +66 -99
  497. package/lib/shared-browser-cookie-sync.js +32 -0
  498. package/lib/shared-browser-cookies.js +79 -0
  499. package/lib/shared-browser-runtime.js +25 -9
  500. package/lib/shared-browser-storage-sync.js +43 -0
  501. package/lib/shared-browser-storage.js +101 -0
  502. package/lib/shared-browser-tools.js +2 -1
  503. package/lib/shared-browser-worker.js +46 -10
  504. package/lib/terminal-manager.js +65 -6
  505. package/lib/tool-llm.js +1 -1
  506. package/lib/tui-transcript-index.js +1 -132
  507. package/lib/users-contextual-clay-preferences.js +31 -0
  508. package/lib/users-permissions.js +2 -8
  509. package/lib/users.js +7 -0
  510. package/lib/vendor-login-browser.js +1 -11
  511. package/lib/vendor-usage-acp-readers.js +97 -0
  512. package/lib/vendor-usage-capabilities.js +88 -0
  513. package/lib/vendor-usage-http-readers.js +214 -0
  514. package/lib/vendor-usage-metrics.js +47 -0
  515. package/lib/vendor-usage-native-readers.js +106 -0
  516. package/lib/vendor-usage-overview.js +406 -0
  517. package/lib/vendor-usage-service.js +281 -0
  518. package/lib/workspace-assignment-service.js +25 -0
  519. package/lib/workspace-query-access.js +4 -1
  520. package/lib/workspace-query-mcp-server.js +1 -1
  521. package/lib/workspace-query-service.js +13 -2
  522. package/lib/ws-request.js +1 -0
  523. package/lib/ws-schema.js +22 -4
  524. package/lib/yoke/acp-agent-profiles.js +7 -5
  525. package/lib/yoke/adapters/antigravity.js +3 -14
  526. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  527. package/lib/yoke/adapters/claude.js +66 -50
  528. package/lib/yoke/adapters/codex-query-contract.js +25 -0
  529. package/lib/yoke/adapters/codex.js +98 -123
  530. package/lib/yoke/adapters/kiro.js +3 -1
  531. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  532. package/lib/yoke/adapters/muse.js +122 -0
  533. package/lib/yoke/auth-events.js +17 -0
  534. package/lib/yoke/claude-hook-installer.js +272 -0
  535. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  536. package/lib/yoke/claude-maintenance.js +55 -0
  537. package/lib/yoke/claude-permission-patterns.js +53 -0
  538. package/lib/yoke/claude-response-recovery.js +155 -0
  539. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  540. package/lib/yoke/claude-worker-startup.js +28 -0
  541. package/lib/yoke/clay-skill-install.js +33 -0
  542. package/lib/yoke/cli-sessions.js +300 -0
  543. package/lib/yoke/codex-app-server.js +7 -12
  544. package/lib/yoke/codex-dynamic-tool-names.js +80 -0
  545. package/lib/yoke/codex-idle-recovery.js +81 -1
  546. package/lib/yoke/codex-model-catalog.js +37 -3
  547. package/lib/yoke/codex-recovery-admission.js +164 -0
  548. package/lib/yoke/configuration.js +13 -0
  549. package/lib/yoke/discovery.js +70 -0
  550. package/lib/yoke/errors.js +8 -0
  551. package/lib/yoke/host-environment.js +7 -0
  552. package/lib/yoke/index.js +9 -51
  553. package/lib/yoke/interface.js +116 -0
  554. package/lib/yoke/kiro-acp-server.js +5 -5
  555. package/lib/yoke/legacy-sessions.js +89 -0
  556. package/lib/yoke/login-protocol.js +25 -0
  557. package/lib/yoke/maintenance.js +12 -0
  558. package/lib/yoke/mcp-proxy.js +32 -0
  559. package/lib/yoke/mcp-source-adapters.js +91 -0
  560. package/lib/yoke/mcp-source-context.js +42 -0
  561. package/lib/yoke/mcp-source-discovery.js +169 -0
  562. package/lib/yoke/mcp-source-plugins.js +68 -0
  563. package/lib/yoke/mcp-source-restrictions.js +47 -0
  564. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  565. package/lib/yoke/model-preferences.js +6 -0
  566. package/lib/yoke/muse-artifacts.js +36 -0
  567. package/lib/yoke/muse-controls.js +50 -0
  568. package/lib/yoke/muse-input.js +64 -0
  569. package/lib/yoke/muse-items.js +157 -0
  570. package/lib/yoke/muse-policy.js +52 -0
  571. package/lib/yoke/muse-query.js +428 -0
  572. package/lib/yoke/muse-runtime.js +211 -0
  573. package/lib/yoke/muse-services.js +92 -0
  574. package/lib/yoke/muse-skills.js +79 -0
  575. package/lib/yoke/muse-turns.js +71 -0
  576. package/lib/yoke/options/acp.js +2 -0
  577. package/lib/yoke/options/antigravity.js +2 -0
  578. package/lib/yoke/options/claude.js +21 -0
  579. package/lib/yoke/options/codex-defaults.js +29 -0
  580. package/lib/yoke/options/codex-settings.js +21 -0
  581. package/lib/yoke/options/codex.js +6 -0
  582. package/lib/yoke/options/kiro-defaults.js +22 -0
  583. package/lib/yoke/options/kiro.js +5 -0
  584. package/lib/yoke/options/muse.js +5 -0
  585. package/lib/yoke/provider-contract.js +5 -0
  586. package/lib/yoke/providers/antigravity-executable.js +8 -0
  587. package/lib/yoke/providers/claude-executable.js +40 -0
  588. package/lib/yoke/providers/claude-model-descriptions.js +34 -0
  589. package/lib/yoke/providers/claude-process.js +97 -0
  590. package/lib/yoke/providers/claude-provision.js +75 -0
  591. package/lib/yoke/providers/codex-errors.js +8 -0
  592. package/lib/yoke/providers/muse-executable.js +17 -0
  593. package/lib/yoke/provisioning.js +6 -0
  594. package/lib/yoke/query-options.js +10 -0
  595. package/lib/yoke/response-recovery.js +41 -0
  596. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  597. package/lib/yoke/sdk-server-factory.js +7 -0
  598. package/lib/yoke/session-history.js +8 -0
  599. package/lib/yoke/session-tool-transport.js +34 -13
  600. package/lib/yoke/settings.js +23 -0
  601. package/lib/yoke/source-locations.js +4 -0
  602. package/lib/yoke/title-query.js +18 -7
  603. package/lib/yoke/tui-transcript-index.js +132 -0
  604. package/lib/yoke/usage.js +48 -0
  605. package/lib/yoke/user-input.js +13 -0
  606. package/lib/yoke/vendor-registry.js +87 -3
  607. package/package.json +11 -4
  608. package/lib/public/modules/server-settings-navigation.js +0 -39
@@ -0,0 +1,112 @@
1
+ import { store } from './store.js';
2
+ import { getWs } from './ws-ref.js';
3
+ import { escapeHtml as escapeText } from './utils.js';
4
+
5
+ function escapeHtml(value) { return escapeText(String(value)).replace(/"/g, '"').replace(/'/g, '''); }
6
+ function state() { return store.get('sharedBrowserSettings') || {}; }
7
+ function set(patch) { store.set({ sharedBrowserSettings: Object.assign({}, state(), patch) }); }
8
+ function root() { return document.getElementById('shared-browser-settings'); }
9
+ function button(label, action, target, description) {
10
+ return '<button type="button" data-settings-action="' + action + '" data-target="' + escapeHtml(target || '') + '" data-label="' + escapeHtml(description || target || '') + '">' + escapeHtml(label) + '</button>';
11
+ }
12
+ function request(operation, target) {
13
+ var ws = getWs();
14
+ if (!ws || ws.readyState !== 1) { set({ error: 'Reconnect to manage browser data.', pending: false }); renderBrowserSettings(); return; }
15
+ var id = crypto.randomUUID();
16
+ set({ pending: true, requestId: id, error: '', notice: '' });
17
+ ws.send(JSON.stringify({ type: 'shared_browser_settings', sessionId: store.get('activeSessionId'), requestId: id, operation: operation, target: target }));
18
+ renderBrowserSettings();
19
+ setTimeout(function () {
20
+ if (state().requestId === id && state().pending) { set({ pending: false, error: 'The request timed out. Refresh to check the saved state.' }); renderBrowserSettings(); }
21
+ }, 15000);
22
+ }
23
+ export function closeBrowserSettings(restoreFocus) {
24
+ var wasOpen = !!state().open;
25
+ set({ open: false, review: null }); renderBrowserSettings();
26
+ var trigger = document.querySelector('[data-action="settings"]'); if (trigger && wasOpen && restoreFocus !== false) trigger.focus();
27
+ }
28
+ export function browserSettingsHtml() {
29
+ return '<section id="shared-browser-settings" class="shared-browser-settings" aria-label="Browser settings" hidden></section>';
30
+ }
31
+ export function bindBrowserSettings(panel) {
32
+ panel.querySelector('[data-action="settings"]').onclick = function () {
33
+ set({ open: true, page: 'sites', data: null, review: null, filter: '' });
34
+ request('list');
35
+ root().querySelector('[data-settings-action="back"]').focus();
36
+ };
37
+ root().addEventListener('keydown', function (event) {
38
+ if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); closeBrowserSettings(); }
39
+ });
40
+ root().addEventListener('input', function (event) {
41
+ if (event.target.matches('[data-settings-filter]')) { set({ filter: event.target.value }); renderRows(); root().dataset.key = JSON.stringify([state(), store.get('connected')]); }
42
+ });
43
+ root().addEventListener('click', function (event) {
44
+ var control = event.target.closest('[data-settings-action]');
45
+ if (!control || control.disabled) return;
46
+ var action = control.dataset.settingsAction;
47
+ if (action === 'back') { closeBrowserSettings(); return; }
48
+ if (action === 'sites' || action === 'history') { set({ page: action, filter: '', review: null, notice: '', error: '' }); renderBrowserSettings(); return; }
49
+ if (action === 'refresh') { request('list'); return; }
50
+ if (action === 'cancel') { set({ review: null }); renderBrowserSettings(); root().querySelector('[data-settings-action="refresh"]').focus(); return; }
51
+ if (action === 'confirm') { var review = state().review; if (review) request(review.action, review.target); return; }
52
+ set({ notice: '', error: '', review: { action: action, target: control.dataset.target, label: control.dataset.label || control.dataset.target } });
53
+ renderBrowserSettings(); root().querySelector('[data-settings-action="cancel"]').focus();
54
+ });
55
+ }
56
+ function renderRows() {
57
+ var el = root(), s = state(); if (!el || !s.open) return;
58
+ var rows = el.querySelector('.browser-settings-rows'); if (!rows) return;
59
+ var filter = (s.filter || '').toLowerCase();
60
+ var data = s.data || { sites: [], history: [] };
61
+ if (s.page === 'history') {
62
+ rows.innerHTML = data.history.filter(function (entry) { return entry.url.toLowerCase().includes(filter); }).map(function (entry) {
63
+ return '<div class="browser-settings-row"><div><span class="browser-settings-url">' + escapeHtml(entry.url) + '</span><small>' + escapeHtml(new Date(entry.at).toLocaleString()) + '</small></div>' + button('Remove', 'delete_history', entry.id, entry.url) + '</div>';
64
+ }).join('');
65
+ } else {
66
+ rows.innerHTML = data.sites.filter(function (site) { return site.host.toLowerCase().includes(filter); }).map(function (site) {
67
+ return '<details><summary>' + escapeHtml(site.host) + '<small>' + site.cookies.length + (site.cookies.length === 1 ? ' cookie · ' : ' cookies · ') + site.origins.length + (site.origins.length === 1 ? ' storage origin' : ' storage origins') + '</small></summary><div class="browser-settings-row"><span>Cookies and site storage</span>' + button('Remove site data', 'delete_site', site.host) + '</div>' +
68
+ site.origins.map(function (origin) { return '<p class="browser-settings-origin">' + escapeHtml(origin.origin) + '<small>' + origin.localStorage + ' localStorage entries · ' + origin.databases + ' IndexedDB databases</small></p>'; }).join('') +
69
+ site.cookies.map(function (cookie) {
70
+ var info = cookie.domain + cookie.path + ' · ' + (cookie.expires === -1 ? 'Session cookie' : 'Expires ' + new Date(cookie.expires * 1000).toLocaleDateString()) + (cookie.httpOnly ? ' · HttpOnly' : '') + (cookie.secure ? ' · Secure' : '') + (cookie.partitioned ? ' · Partitioned' : '');
71
+ return '<div class="browser-settings-row"><div><span>' + escapeHtml(cookie.name) + '</span><small>' + escapeHtml(info) + '</small></div>' + button('Remove cookie', 'delete_cookie', cookie.id, cookie.name + ' · ' + cookie.domain + cookie.path) + '</div>';
72
+ }).join('') + '</details>';
73
+ }).join('');
74
+ }
75
+ if (!rows.innerHTML) rows.innerHTML = '<p class="browser-settings-muted">' + (s.pending && !s.data ? 'Loading saved data…' : filter ? 'No matching entries.' : s.page === 'history' ? 'No saved browsing history.' : 'No saved cookies or site data.') + '</p>';
76
+ rows.querySelectorAll('button').forEach(function (control) { control.disabled = !!s.pending || !store.get('connected'); });
77
+ }
78
+ export function renderBrowserSettings() {
79
+ var el = root(); if (!el) return;
80
+ var s = state(), panel = el.closest('.shared-browser-panel');
81
+ var browser = store.get('sharedBrowser');
82
+ var trigger = panel.querySelector('[data-action="settings"]');
83
+ trigger.hidden = !(browser && browser.personalCookiesAvailable);
84
+ trigger.disabled = !store.get('connected');
85
+ trigger.setAttribute('aria-expanded', String(!!s.open));
86
+ el.hidden = !s.open;
87
+ panel.classList.toggle('browser-settings-open', !!s.open);
88
+ if (!s.open) return;
89
+ var key = JSON.stringify([s, store.get('connected')]); if (el.dataset.key === key) return; el.dataset.key = key;
90
+ var page = s.page || 'sites';
91
+ el.innerHTML = '<div class="browser-settings-heading">' + button('Back to browser', 'back') + '<h3>Browser settings</h3></div><p class="browser-settings-muted">Personal · Shared across your Mates. Incognito tabs do not save data here.</p>' +
92
+ '<nav aria-label="Browser settings sections">' + button('Cookies & site data', 'sites') + button('History', 'history') + '</nav>' +
93
+ '<p class="browser-settings-muted">' + (page === 'sites' ? 'Cookies, localStorage and IndexedDB are saved for your account. New personal tabs restore saved site storage. Removing data may sign you out. Removals also apply to open personal tabs. Sites may create new data afterwards.' : 'Your latest 500 page visits. Clearing this list leaves open tabs, their Back/Forward navigation and conversation activity unchanged.') + '</p>' +
94
+ '<div class="browser-settings-tools"><input data-settings-filter aria-label="Filter saved browser data" placeholder="' + (page === 'sites' ? 'Find a site' : 'Find a page') + '" value="' + escapeHtml(s.filter || '') + '">' + button('Refresh', 'refresh') + button(page === 'sites' ? 'Clear all site data' : 'Clear history', page === 'sites' ? 'clear_data' : 'clear_history') + '</div>' +
95
+ '<p class="browser-settings-feedback" role="status">' + escapeHtml(s.error || (!store.get('connected') ? 'Disconnected. Reconnect and refresh to see current saved data.' : s.pending ? 'Updating…' : s.notice || '')) + '</p>' +
96
+ (s.review ? '<div class="browser-settings-review" role="group" aria-label="Confirm removal"><strong>' + (s.review.action.includes('history') ? 'Remove browsing history?' : 'Remove saved site data?') + '</strong><p>' + (s.review.action.includes('history') ? 'This removes ' + (s.review.action === 'clear_history' ? 'all saved visits' : 'this saved visit') + ' from your personal history.' : s.review.action === 'delete_cookie' ? 'This removes ' + escapeHtml(s.review.label) + ' across your personal Mate browsers and may sign you out.' : 'This removes ' + (s.review.action === 'clear_data' ? 'all cookies and site storage' : 'cookies and storage for ' + escapeHtml(s.review.target)) + ' across your personal Mate browsers and may sign you out.') + '</p>' + button('Cancel', 'cancel') + button('Remove', 'confirm') + '</div>' : '') +
97
+ '<div class="browser-settings-rows"></div>';
98
+ el.querySelector('[data-settings-action="' + page + '"]').setAttribute('aria-current', 'page');
99
+ el.querySelectorAll('button').forEach(function (control) { control.disabled = control.dataset.settingsAction !== 'back' && (!!s.pending || !store.get('connected')); });
100
+ renderRows();
101
+ }
102
+ export function handleBrowserSettingsMessage(msg) {
103
+ if (!msg.requestId || msg.requestId !== state().requestId) return false;
104
+ if (msg.type === 'shared_browser_settings') {
105
+ var removed = !!state().review;
106
+ set({ data: msg.settings, pending: false, review: null, error: '', notice: removed ? 'Removed from your saved browser data.' : '' });
107
+ } else if (msg.type === 'shared_browser_error') set({ pending: false, error: msg.error });
108
+ else return false;
109
+ renderBrowserSettings();
110
+ if (state().open && removed) root().querySelector('[data-settings-action="refresh"]').focus();
111
+ return true;
112
+ }
@@ -1,10 +1,11 @@
1
+ import { iconHtml, refreshIcons } from './icons.js';
1
2
  import { store } from './store.js';
2
3
 
3
4
  export function renderBrowserTabs(el, select, send) {
4
5
  var bar = el.querySelector('.shared-browser-tabs');
5
6
  var tabs = store.get('sharedBrowsers') || [];
6
7
  var selected = store.get('sharedBrowser');
7
- var key = JSON.stringify([tabs.map(function (tab) { return [tab.id, tab.url, tab.control, tab.phase]; }), selected && selected.id, store.get('connected')]);
8
+ var key = JSON.stringify([tabs.map(function (tab) { return [tab.id, tab.url, tab.control, tab.phase, tab.incognito, tab.personalCookiesAvailable]; }), selected && selected.id, store.get('connected')]);
8
9
  if (bar.dataset.key === key) return;
9
10
  bar.dataset.key = key;
10
11
  bar.replaceChildren();
@@ -14,9 +15,9 @@ export function renderBrowserTabs(el, select, send) {
14
15
  button.setAttribute('aria-selected', String(!!selected && selected.id === tab.id));
15
16
  var title = 'Tab ' + (index + 1);
16
17
  try { if (tab.url) title = new URL(tab.url).hostname; } catch (e) {}
17
- var label = document.createElement('span'); label.textContent = title;
18
+ var label = document.createElement('span'); label.textContent = title + (tab.personalCookiesAvailable && tab.incognito ? ' · Incognito' : '');
18
19
  var owner = document.createElement('small'); owner.textContent = tab.phase === 'ended' ? 'Ended' : tab.control === 'agent' ? 'Shared' : 'You only';
19
- button.append(label, owner); button.title = title + ' · ' + (tab.phase === 'ended' ? 'Ended' : tab.control === 'agent' ? 'You and Clay can control this tab' : 'Only you can control this tab. Clay is paused.');
20
+ button.append(label, owner); button.title = title + ' · ' + (tab.incognito === false ? 'Personal browser' : 'Incognito') + ' · ' + (tab.phase === 'ended' ? 'Ended' : tab.control === 'agent' ? 'You and Clay can control this tab' : 'Only you can control this tab. Clay is paused.');
20
21
  button.onclick = function () { select(tab.id); };
21
22
  button.onkeydown = function (event) {
22
23
  var next = event.key === 'ArrowRight' ? (index + 1) % tabs.length : event.key === 'ArrowLeft' ? (index + tabs.length - 1) % tabs.length : event.key === 'Home' ? 0 : event.key === 'End' ? tabs.length - 1 : -1;
@@ -28,6 +29,15 @@ export function renderBrowserTabs(el, select, send) {
28
29
  item.append(button, close); bar.appendChild(item);
29
30
  });
30
31
  var add = document.createElement('button'); add.type = 'button'; add.textContent = '+'; add.setAttribute('aria-label', 'New browser tab'); add.disabled = !store.get('connected');
32
+ add.title = selected && selected.personalCookiesAvailable ? 'New tab · Personal browser' : 'New incognito tab';
31
33
  add.onclick = function () { send('open', { newTab: true }); };
32
34
  bar.appendChild(add);
35
+ if (selected && selected.personalCookiesAvailable) {
36
+ var incognito = document.createElement('button'); incognito.type = 'button';
37
+ incognito.innerHTML = iconHtml('glasses');
38
+ incognito.setAttribute('aria-label', 'New incognito tab'); incognito.title = 'New incognito tab · Site data is not saved';
39
+ incognito.disabled = !store.get('connected');
40
+ incognito.onclick = function () { send('open', { newTab: true, incognito: true }); };
41
+ bar.appendChild(incognito); refreshIcons();
42
+ }
33
43
  }
@@ -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)
@@ -9,7 +10,7 @@ import { iconHtml, refreshIcons } from './icons.js';
9
10
  import { parseEmojis } from './markdown.js';
10
11
  import { getCurrentTheme, getChatLayout, setChatLayout } from './theme.js';
11
12
  import { openCommandPalette } from './command-palette.js';
12
- import { openProjectSettings } from './project-settings.js';
13
+ import { openSettings } from './settings-shell.js';
13
14
  import { getCachedSessions, openSessionContextMenu } from './sidebar-sessions.js';
14
15
  import { renderSessionPresence } from './session-presence-ui.js';
15
16
  import {
@@ -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();
@@ -1032,6 +1033,7 @@ export function renderSheetTools(listEl) {
1032
1033
 
1033
1034
  function renderSheetSettings(listEl) {
1034
1035
  var items = [
1036
+ { icon: "user-cog", label: "Personal Settings", action: "personal-settings" },
1035
1037
  { icon: "folder-cog", label: "Project Settings", action: "project-settings" },
1036
1038
  { icon: "settings", label: "Server Settings", action: "server-settings" }
1037
1039
  ];
@@ -1043,35 +1045,12 @@ function renderSheetSettings(listEl) {
1043
1045
  btn.innerHTML = '<i data-lucide="' + item.icon + '"></i><span class="mobile-more-item-label">' + item.label + '</span>';
1044
1046
  btn.addEventListener("click", function () {
1045
1047
  closeMobileSheet();
1046
- if (item.action === "project-settings") {
1047
- setTimeout(function () {
1048
- // Find current project data
1049
- var proj = null;
1050
- for (var pi = 0; pi < getCachedProjectList().length; pi++) {
1051
- if (getCachedProjectList()[pi].slug === getCachedCurrentSlug()) {
1052
- proj = getCachedProjectList()[pi];
1053
- break;
1054
- }
1055
- }
1056
- // For mate projects, use mate display name instead of slug
1057
- if (proj && proj.isMate && getCachedMates().length > 0) {
1058
- var mateId = getCachedCurrentSlug().replace("mate-", "");
1059
- var _mates = getCachedMates();
1060
- for (var mi = 0; mi < _mates.length; mi++) {
1061
- var mp = _mates[mi].profile || {};
1062
- if (_mates[mi].id === mateId) {
1063
- proj = Object.assign({}, proj, { name: mp.displayName || _mates[mi].name || proj.name });
1064
- break;
1065
- }
1066
- }
1067
- }
1068
- if (proj && store.get('ownerLocked')) proj = Object.assign({}, proj, { ownerLocked: true });
1069
- openProjectSettings(getCachedCurrentSlug(), proj);
1070
- }, 250);
1071
- } else if (item.action === "server-settings") {
1072
- var settingsBtn = document.getElementById("server-settings-btn");
1073
- if (settingsBtn) setTimeout(function () { settingsBtn.click(); }, 250);
1074
- }
1048
+ // The shell resolves each scope to its exact page and falls back for
1049
+ // accounts that may not use it. Project settings target the open
1050
+ // workspace first.
1051
+ var route = item.action === "project-settings" ? { scope: "project", slug: getCachedCurrentSlug() }
1052
+ : item.action === "server-settings" ? { scope: "server" } : { scope: "personal" };
1053
+ setTimeout(function () { openSettings(route); }, 250);
1075
1054
  });
1076
1055
  listEl.appendChild(btn);
1077
1056
  })(items[i]);
@@ -10,7 +10,8 @@ import { store } from './store.js';
10
10
  import { getWs } from './ws-ref.js';
11
11
  import { closeSidebar } from './sidebar.js';
12
12
  import { showIconTooltip, hideIconTooltip, bindIconTooltip, closeUserCtxMenu, getCurrentDmUserId } from './sidebar-mates.js';
13
- import { switchProject, openAddProjectModal, getCachedProjects } from './app-projects.js';
13
+ import { switchProject, getCachedProjects } from './app-projects.js';
14
+ import { openAddProjectModal } from './project-start-dialog.js';
14
15
  import { showHomeHub } from './app-home-hub.js';
15
16
  import { getPendingTuiAttention } from './app-notifications.js';
16
17
  import { isExternalWorktree, externalWorktreeTooltip, appendExternalWorktreeBadge } from './worktree-location.js';
@@ -822,6 +823,7 @@ function createIconItem(p, currentSlug) {
822
823
  var el = document.createElement("a");
823
824
  var isActive = p.slug === currentSlug && !currentDmUserId;
824
825
  el.className = "icon-strip-item" + (isActive ? " active" : "");
826
+ el.dataset.controlRuntime = p.controlRuntimeId || "";
825
827
  el.href = "/p/" + p.slug + "/";
826
828
  el.dataset.slug = p.slug;
827
829
 
@@ -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
  }