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
package/lib/sessions.js CHANGED
@@ -3,7 +3,7 @@ var path = require("path");
3
3
  var config = require("./config");
4
4
  var utils = require("./utils");
5
5
  var users = require("./users");
6
- var { CODEX_DEFAULTS } = require("./codex-defaults");
6
+ var providerDefaults = require("./yoke/settings").defaults();
7
7
  var hygiene = require("./session-hygiene");
8
8
  var backgroundTaskTiming = require("./background-task-timing");
9
9
  var sessionProvenance = require("./session-provenance");
@@ -39,16 +39,16 @@ function createSessionManager(opts) {
39
39
  var permissionRequestIndex = {}; // requestId -> sessionLocalId (O(1) lookup)
40
40
  var capabilitiesByVendor = null; // set by sdk-bridge after adapter init
41
41
  var defaultVendor = null; // set by sdk-bridge
42
- var codexApproval = CODEX_DEFAULTS.approval;
43
- var codexSandbox = CODEX_DEFAULTS.sandbox;
44
- var codexWebSearch = CODEX_DEFAULTS.webSearch;
42
+ var codexApproval = providerDefaults.codexApproval;
43
+ var codexSandbox = providerDefaults.codexSandbox;
44
+ var codexWebSearch = providerDefaults.codexWebSearch;
45
45
 
46
46
  // --- Session persistence (centralized in ~/.clay/sessions/{encoded-cwd}/) ---
47
47
  var sessionsBase = opts.sessionsBase || path.join(config.CONFIG_DIR, "sessions");
48
48
  var encodedCwd = utils.resolveEncodedDir(sessionsBase, cwd);
49
49
  var sessionsDir = path.join(sessionsBase, encodedCwd);
50
50
  fs.mkdirSync(sessionsDir, { recursive: true });
51
- var cliSessionsDir = opts.cliSessionsDir || path.join(config.REAL_HOME, ".claude", "projects", utils.encodeCwd(cwd));
51
+ var cliSessionsDir = opts.cliSessionsDir || require("./yoke/legacy-sessions").directory(config.REAL_HOME, cwd);
52
52
  var deletedCliSessionsPath = path.join(sessionsDir, "deleted-cli-sessions.json");
53
53
  var deletedCliSessionIds = new Set();
54
54
  try {
@@ -77,29 +77,6 @@ function createSessionManager(opts) {
77
77
  }
78
78
  }
79
79
 
80
- function readCliTranscriptHead(filePath) {
81
- var MAX_READ = 64 * 1024;
82
- try {
83
- var stat = fs.statSync(filePath);
84
- var fd = fs.openSync(filePath, "r");
85
- var bytesToRead = Math.min(stat.size, MAX_READ);
86
- var buf = Buffer.alloc(bytesToRead);
87
- fs.readSync(fd, buf, 0, bytesToRead, 0);
88
- fs.closeSync(fd);
89
- var lines = buf.toString("utf8").split("\n");
90
- var events = [];
91
- for (var i = 0; i < lines.length; i++) {
92
- if (!lines[i]) continue;
93
- try {
94
- var event = JSON.parse(lines[i]);
95
- if (event && typeof event === "object") events.push(event);
96
- } catch (e) {}
97
- }
98
- return events;
99
- } catch (e) {
100
- return null;
101
- }
102
- }
103
80
 
104
81
  // Auto-migrate sessions from legacy locations:
105
82
  // v1: {cwd}/.claude-relay/sessions/
@@ -179,6 +156,7 @@ function createSessionManager(opts) {
179
156
  };
180
157
  if (session.githubLinks) metaObj.githubLinks = session.githubLinks;
181
158
  if (session.linearLinks) metaObj.linearLinks = session.linearLinks;
159
+ if (session.workPrimary) metaObj.workPrimary = session.workPrimary;
182
160
  if (session.ownerId) metaObj.ownerId = session.ownerId;
183
161
  if (session.vendor) metaObj.vendor = session.vendor;
184
162
  if (session.codexDynamicToolCatalogVersion) metaObj.codexDynamicToolCatalogVersion = session.codexDynamicToolCatalogVersion;
@@ -188,6 +166,7 @@ function createSessionManager(opts) {
188
166
  if (session.codexLinearToolCatalogVersion) metaObj.codexLinearToolCatalogVersion = session.codexLinearToolCatalogVersion;
189
167
  if (session.codexSharedBrowserToolCatalogVersion) metaObj.codexSharedBrowserToolCatalogVersion = session.codexSharedBrowserToolCatalogVersion;
190
168
  if (session.codexIssuesToolCatalogVersion) metaObj.codexIssuesToolCatalogVersion = session.codexIssuesToolCatalogVersion;
169
+ if (session.codexNotesToolCatalogVersion) metaObj.codexNotesToolCatalogVersion = session.codexNotesToolCatalogVersion;
191
170
  if (session.model) metaObj.model = session.model;
192
171
  if (session.effort) metaObj.effort = session.effort;
193
172
  // Persist the session's "born" mode so TUI sessions reappear after a
@@ -226,10 +205,18 @@ function createSessionManager(opts) {
226
205
  if (session.homeDebatePlanning) metaObj.homeDebatePlanning = true;
227
206
  if (session.homeDebatePhase) metaObj.homeDebatePhase = session.homeDebatePhase;
228
207
  if (session.homeDebateInitialTopic) metaObj.homeDebateInitialTopic = session.homeDebateInitialTopic;
208
+ if (session.mateScheduleDraft) metaObj.mateScheduleDraft = session.mateScheduleDraft;
209
+ if (session.mateSchedules) metaObj.mateSchedules = session.mateSchedules;
210
+ if (session.clayWorkspaceReceipts) metaObj.clayWorkspaceReceipts = session.clayWorkspaceReceipts;
211
+ if (session.clayMateChatReceipts) metaObj.clayMateChatReceipts = session.clayMateChatReceipts;
212
+ if (session.claySchedulingReceipts) metaObj.claySchedulingReceipts = session.claySchedulingReceipts;
229
213
  if (session.mateCreationMode) metaObj.mateCreationMode = true;
230
214
  if (session.homeMateCreationPhase) metaObj.homeMateCreationPhase = session.homeMateCreationPhase;
215
+ if (session.contextualCreationMateStamp) metaObj.contextualCreationMateStamp = session.contextualCreationMateStamp;
216
+ if (session.contextualCreationRequestId) metaObj.contextualCreationRequestId = session.contextualCreationRequestId;
231
217
  if (session.homeClayEntryRequestId) metaObj.homeClayEntryRequestId = session.homeClayEntryRequestId;
232
218
  if (session.homeClayEntryMode) metaObj.homeClayEntryMode = session.homeClayEntryMode;
219
+ if (session.homeClayEntryText) metaObj.homeClayEntryText = session.homeClayEntryText;
233
220
  metaObj.sessionOriginId = provenanceMeta.sessionOriginId;
234
221
  if (provenanceMeta.sessionProvenance) metaObj.sessionProvenance = provenanceMeta.sessionProvenance;
235
222
  if (Array.isArray(session._workerGenerations)) metaObj.workerGenerations = session._workerGenerations;
@@ -356,6 +343,7 @@ function createSessionManager(opts) {
356
343
  titleAutoGenerated: m.titleAutoGenerated === true,
357
344
  githubLinks: Array.isArray(m.githubLinks) ? m.githubLinks.slice(0, 8) : [],
358
345
  linearLinks: Array.isArray(m.linearLinks) ? m.linearLinks.slice(0, 8) : [],
346
+ workPrimary: m.workPrimary || {},
359
347
  titleManuallySet: m.titleManuallySet === true || legacyTitleProtected,
360
348
  createdAt: m.createdAt || Date.now(),
361
349
  lastActivity: loaded[i].mtime || m.createdAt || Date.now(),
@@ -371,6 +359,7 @@ function createSessionManager(opts) {
371
359
  session.codexLinearToolCatalogVersion = Number(m.codexLinearToolCatalogVersion || 0);
372
360
  session.codexSharedBrowserToolCatalogVersion = Number(m.codexSharedBrowserToolCatalogVersion || 0);
373
361
  session.codexIssuesToolCatalogVersion = Number(m.codexIssuesToolCatalogVersion || 0);
362
+ session.codexNotesToolCatalogVersion = Number(m.codexNotesToolCatalogVersion || 0);
374
363
  session.model = m.model || deriveSessionModel(loaded[i].history);
375
364
  session.effort = m.effort || null;
376
365
  if (m.loop) session.loop = m.loop;
@@ -384,10 +373,18 @@ function createSessionManager(opts) {
384
373
  if (m.homeDebatePlanning) session.homeDebatePlanning = true;
385
374
  if (m.homeDebatePhase) session.homeDebatePhase = m.homeDebatePhase;
386
375
  if (m.homeDebateInitialTopic) session.homeDebateInitialTopic = m.homeDebateInitialTopic;
376
+ if (m.mateScheduleDraft) session.mateScheduleDraft = m.mateScheduleDraft;
377
+ if (m.mateSchedules) session.mateSchedules = m.mateSchedules;
378
+ if (Array.isArray(m.clayWorkspaceReceipts)) session.clayWorkspaceReceipts = m.clayWorkspaceReceipts;
379
+ if (Array.isArray(m.clayMateChatReceipts)) session.clayMateChatReceipts = m.clayMateChatReceipts;
380
+ if (Array.isArray(m.claySchedulingReceipts)) session.claySchedulingReceipts = m.claySchedulingReceipts;
387
381
  if (m.mateCreationMode) session.mateCreationMode = true;
388
382
  if (m.homeMateCreationPhase) session.homeMateCreationPhase = m.homeMateCreationPhase;
383
+ if (m.contextualCreationMateStamp) session.contextualCreationMateStamp = m.contextualCreationMateStamp;
384
+ if (m.contextualCreationRequestId) session.contextualCreationRequestId = m.contextualCreationRequestId;
389
385
  if (m.homeClayEntryRequestId) session.homeClayEntryRequestId = m.homeClayEntryRequestId;
390
386
  if (m.homeClayEntryMode) session.homeClayEntryMode = m.homeClayEntryMode;
387
+ if (m.homeClayEntryText) session.homeClayEntryText = m.homeClayEntryText;
391
388
  if (m.ownerId) session.ownerId = m.ownerId;
392
389
  session.sessionOriginId = m.sessionOriginId || null;
393
390
  session._provenanceMigrationNeeded = sessionProvenance.restore(m, session);
@@ -458,9 +455,6 @@ function createSessionManager(opts) {
458
455
  // - Warmup shape: 1 real "hi" prompt, optional automatic interruption,
459
456
  // and 0 assistant messages (covered by daemon cleanup but defensive)
460
457
  function adoptOrphanedCliSessions() {
461
- var files;
462
- try { files = fs.readdirSync(cliSessionsDir); } catch (e) { return; }
463
-
464
458
  // Build set of cliSessionIds Clay already tracks
465
459
  var knownCliIds = new Set();
466
460
  sessions.forEach(function (s) {
@@ -469,56 +463,10 @@ function createSessionManager(opts) {
469
463
 
470
464
  var adopted = 0;
471
465
 
472
- for (var i = 0; i < files.length; i++) {
473
- if (!files[i].endsWith(".jsonl")) continue;
474
- var cliSid = files[i].slice(0, -".jsonl".length);
475
- if (knownCliIds.has(cliSid)) continue;
476
- if (deletedCliSessionIds.has(cliSid)) continue;
477
-
478
- var fp = path.join(cliSessionsDir, files[i]);
479
- var events = readCliTranscriptHead(fp);
480
- if (!events) continue;
481
- var userCount = 0;
482
- var firstUserText = null;
483
- var createdAtIso = null;
484
- for (var li = 0; li < events.length; li++) {
485
- var ev = events[li];
486
- if (ev.type === "user" && ev.message && ev.message.role === "user") {
487
- userCount++;
488
- if (firstUserText == null) {
489
- var c = ev.message.content;
490
- if (typeof c === "string") {
491
- firstUserText = c;
492
- } else if (Array.isArray(c)) {
493
- var parts = [];
494
- for (var ci = 0; ci < c.length; ci++) {
495
- if (c[ci] && c[ci].type === "text" && typeof c[ci].text === "string") parts.push(c[ci].text);
496
- }
497
- firstUserText = parts.join("");
498
- }
499
- if (ev.timestamp && !createdAtIso) createdAtIso = ev.timestamp;
500
- }
501
- }
502
- }
503
-
504
- if (userCount === 0) continue;
505
- // Defensive warmup skip (daemon also cleans these)
506
- if (hygiene.isClaudeWarmupTranscript(events)) continue;
507
-
508
- // Title: first user message trimmed/truncated. Fall back to a
509
- // neutral label so the sidebar entry is identifiable.
510
- var title = (firstUserText || "").trim().replace(/\s+/g, " ");
511
- if (title.length > 60) title = title.slice(0, 57) + "...";
512
- if (!title) title = "Imported CLI session";
513
-
514
- var createdAt = Date.now();
515
- if (createdAtIso) {
516
- var t = Date.parse(createdAtIso);
517
- if (!isNaN(t)) createdAt = t;
518
- }
519
- var lastActivity = createdAt;
520
- try { lastActivity = fs.statSync(fp).mtimeMs; } catch (e) {}
521
-
466
+ var candidates = require("./yoke/legacy-sessions").candidates(cliSessionsDir, knownCliIds, deletedCliSessionIds);
467
+ for (var i = 0; i < candidates.length; i++) {
468
+ var candidate = candidates[i], cliSid = candidate.id;
469
+ var title = candidate.title, createdAt = candidate.createdAt, lastActivity = candidate.lastActivity;
522
470
  var localId = nextLocalId++;
523
471
  var session = {
524
472
  localId: localId,
@@ -536,7 +484,7 @@ function createSessionManager(opts) {
536
484
  history: [],
537
485
  messageUUIDs: [],
538
486
  lastRewindUuid: null,
539
- vendor: "claude",
487
+ vendor: candidate.vendor,
540
488
  mode: "tui",
541
489
  // Adopted from an external `claude` run in this cwd, not started by
542
490
  // Clay. Notification emitters must stay silent for these until the
@@ -568,10 +516,7 @@ function createSessionManager(opts) {
568
516
  var stale = [];
569
517
  sessions.forEach(function (session) {
570
518
  if (!session.adopted || !session.cliSessionId) return;
571
- var transcriptPath = path.join(cliSessionsDir, session.cliSessionId + ".jsonl");
572
- var events = readCliTranscriptHead(transcriptPath);
573
- var missingEmptySource = !fs.existsSync(transcriptPath) && (!session.history || session.history.length === 0);
574
- if (missingEmptySource || (events && hygiene.isClaudeWarmupTranscript(events))) stale.push(session.localId);
519
+ if (require("./yoke/legacy-sessions").obsolete(cliSessionsDir, session)) stale.push(session.localId);
575
520
  });
576
521
  for (var i = 0; i < stale.length; i++) deleteSessionQuiet(stale[i]);
577
522
  if (stale.length > 0) {
@@ -624,11 +569,13 @@ function createSessionManager(opts) {
624
569
  var unreadMap = wsUnread || singleUserUnread;
625
570
  return {
626
571
  id: s.localId,
572
+ sessionOriginId: s.sessionOriginId || null,
627
573
  cliSessionId: s.cliSessionId || null,
628
574
  createdAt: s.createdAt || 0,
629
575
  title: s.title || "New Session",
630
576
  githubLinks: s.githubLinks || [],
631
577
  linearLinks: s.linearLinks || [],
578
+ workPrimary: s.workPrimary || {},
632
579
  active: isActive,
633
580
  isProcessing: s.isProcessing,
634
581
  // Sidebar badge: user work only. Ambient housekeeping is surfaced in the
@@ -833,8 +780,8 @@ function createSessionManager(opts) {
833
780
  }
834
781
 
835
782
  // History entries include tool activity and streamed output, so opening a
836
- // conversation needs a wider window than each incremental scroll-up page.
837
- var INITIAL_HISTORY_SIZE = 500;
783
+ // conversation starts with a 300-entry target, aligned to a complete user turn.
784
+ var INITIAL_HISTORY_SIZE = 300;
838
785
  var HISTORY_PAGE_SIZE = 100;
839
786
 
840
787
  function findTurnBoundary(history, targetIndex) {
@@ -844,8 +791,9 @@ function createSessionManager(opts) {
844
791
  return 0;
845
792
  }
846
793
 
847
- function replayHistory(session, fromIndex, targetWs, transform) {
848
- var _send = (targetWs && sendTo) ? function (obj) { sendTo(targetWs, obj); } : send;
794
+ function replayHistory(session, fromIndex, targetWs, transform, snapshotSend) {
795
+ var _send = snapshotSend || ((targetWs && sendTo) ? function (obj) { sendTo(targetWs, obj); } : send);
796
+ var sendHistory = snapshotSend && snapshotSend.history || _send;
849
797
  var total = session.history.length;
850
798
  if (typeof fromIndex !== "number") {
851
799
  if (total <= INITIAL_HISTORY_SIZE) {
@@ -855,7 +803,7 @@ function createSessionManager(opts) {
855
803
  }
856
804
  }
857
805
 
858
- _send({ type: "history_meta", total: total, from: fromIndex });
806
+ sendHistory({ type: "history_meta", total: total, from: fromIndex });
859
807
 
860
808
  for (var i = fromIndex; i < total; i++) {
861
809
  var _item = session.history[i];
@@ -864,7 +812,10 @@ function createSessionManager(opts) {
864
812
  if (_item && (_item.type === "mention_user" || _item.type === "mention_response")) {
865
813
  console.log("[DEBUG replayHistory] sending mention at index=" + i + " from=" + fromIndex + " total=" + total + " type=" + _item.type + " mate=" + (_item.mateName || ""));
866
814
  }
867
- _send(transform ? transform(_item) : _item);
815
+ var normalizedItem = require("./yoke/usage").clientEvent(_item, session.vendor || "claude");
816
+ var replayItem = transform ? transform(normalizedItem) : normalizedItem;
817
+ if (replayItem && typeof replayItem === "object") replayItem = Object.assign({}, replayItem, { _historyIndex: i });
818
+ sendHistory(replayItem);
868
819
  }
869
820
 
870
821
  // Find the last result message in the full history for accurate context data
@@ -872,9 +823,11 @@ function createSessionManager(opts) {
872
823
  var lastModelUsage = null;
873
824
  var lastCost = null;
874
825
  var lastStreamInputTokens = null;
826
+ var lastContext = null;
875
827
  for (var j = total - 1; j >= 0; j--) {
876
828
  if (session.history[j].type === "result") {
877
- var r = session.history[j];
829
+ var r = require("./yoke/usage").clientEvent(session.history[j], session.vendor || "claude");
830
+ lastContext = r.context || null;
878
831
  lastUsage = r.usage || null;
879
832
  lastModelUsage = r.modelUsage || null;
880
833
  lastCost = r.cost != null ? r.cost : null;
@@ -883,16 +836,17 @@ function createSessionManager(opts) {
883
836
  }
884
837
  }
885
838
 
886
- _send({ type: "history_done", lastUsage: lastUsage, lastModelUsage: lastModelUsage, lastCost: lastCost, lastStreamInputTokens: lastStreamInputTokens, contextUsage: session.lastContextUsage || null });
839
+ sendHistory({ type: "history_done", controlHistoryRevision: require("./clay-control-target-projection").digest(session.history || []), sessionId: session.localId, sessionOriginId: session.sessionOriginId || null, lastUsage: lastUsage, lastModelUsage: lastModelUsage, lastCost: lastCost, lastStreamInputTokens: lastStreamInputTokens, context: lastContext, contextUsage: require("./yoke/usage").context(session.lastContextUsage, session.vendor || "claude") });
887
840
  for (var vi = 0; vi < sessionViewedListeners.length; vi++) {
888
841
  try { sessionViewedListeners[vi](session, targetWs, _send); } catch (e) {}
889
842
  }
890
843
  }
891
844
 
892
- function switchSession(localId, targetWs, transform) {
845
+ function switchSession(localId, targetWs, transform, snapshotSend, snapshotGuard) {
893
846
  var session = sessions.get(localId);
894
847
  if (!session) return;
895
848
  if (typeof onSessionHydrate === "function") onSessionHydrate(session);
849
+ if (snapshotGuard && !snapshotGuard()) return;
896
850
 
897
851
  // Pane sockets (split-view iframes) pin their session via switch_session
898
852
  // but must not move the project-global active pointer: reloads and
@@ -913,7 +867,7 @@ function createSessionManager(opts) {
913
867
  singleUserUnread[localId] = 0;
914
868
 
915
869
  // In multi-user mode with a specific client, only send to that client
916
- var _send = (targetWs && sendTo) ? function (obj) { sendTo(targetWs, obj); } : send;
870
+ var _send = snapshotSend || ((targetWs && sendTo) ? function (obj) { sendTo(targetWs, obj); } : send);
917
871
 
918
872
  var _capsByVendor = capabilitiesByVendor || {};
919
873
  var _sessionVendor = session.vendor || defaultVendor || "claude";
@@ -926,7 +880,7 @@ function createSessionManager(opts) {
926
880
  || [];
927
881
  _send({ type: "slash_commands", commands: _vendorCmds, vendor: _sessionVendor });
928
882
  broadcastSessionList();
929
- replayHistory(session, undefined, targetWs, transform);
883
+ replayHistory(session, undefined, targetWs, transform, snapshotSend);
930
884
 
931
885
  if (session.isProcessing) {
932
886
  _send({ type: "status", status: "processing" });
@@ -944,10 +898,15 @@ function createSessionManager(opts) {
944
898
  toolInput: p.toolInput,
945
899
  toolUseId: p.toolUseId,
946
900
  decisionReason: p.decisionReason,
901
+ defaultToNo: p.defaultToNo,
902
+ suppressAlwaysAllowRule: p.suppressAlwaysAllowRule,
903
+ mateId: p.mateId || undefined,
904
+ vendor: p.vendor || session.vendor || undefined,
947
905
  });
948
906
  }
949
907
 
950
908
  // Re-send active mention indicator so returning clients restore the mate avatar state
909
+ if (snapshotSend) require('./pane-pending-interactions').send(session, _send);
951
910
  if (session._mentionInProgress && session._mentionActiveMateId) {
952
911
  _send({ type: "mention_processing", mateId: session._mentionActiveMateId, active: true });
953
912
  }
@@ -1080,6 +1039,14 @@ function createSessionManager(opts) {
1080
1039
  }
1081
1040
  }
1082
1041
 
1042
+ // An activated pane socket only accepts frames carrying its exact binding;
1043
+ // the transport adds it, or withholds the frame if the binding is stale.
1044
+ function sendLiveToSocket(ws, session, obj, data) {
1045
+ if (!ws._clayPaneActivation) { ws.send(data); return; }
1046
+ var panePayload = require("./pane-session-transport").outbound(ws, obj, session.localId);
1047
+ if (panePayload) ws.send(JSON.stringify(panePayload));
1048
+ }
1049
+
1083
1050
  function doSendToSession(session, obj) {
1084
1051
  // Send to active clients without recording to history/disk (ephemeral data)
1085
1052
  if (sendEach) {
@@ -1088,7 +1055,7 @@ function createSessionManager(opts) {
1088
1055
  if (filterFn && !filterFn(session)) return;
1089
1056
  if (session.homeDebatePlanning === true) return;
1090
1057
  if (ws._clayActiveSession === session.localId && ws.readyState === 1) {
1091
- ws.send(data);
1058
+ sendLiveToSocket(ws, session, obj, data);
1092
1059
  }
1093
1060
  });
1094
1061
  } else if (session.localId === activeSessionId) {
@@ -1120,7 +1087,7 @@ function createSessionManager(opts) {
1120
1087
  if (filterFn && !filterFn(session)) return;
1121
1088
  if (session.homeDebatePlanning === true) return;
1122
1089
  if (ws._clayActiveSession === session.localId) {
1123
- if (ws.readyState === 1) ws.send(data);
1090
+ if (ws.readyState === 1) sendLiveToSocket(ws, session, outgoingObj, data);
1124
1091
  } else if (session.isProcessing && !session._ioThrottle) {
1125
1092
  if (!ioData) ioData = JSON.stringify({ type: "session_io", id: session.localId });
1126
1093
  if (ws.readyState === 1) ws.send(ioData);
@@ -0,0 +1,32 @@
1
+ var cookieKey = require('./shared-browser-cookies').cookieKey;
2
+
3
+ // Only the private worker pipe carries cookies. They never enter browser state or tool output.
4
+ function attachCookieSync(context, initial, send) {
5
+ var pending = null;
6
+ var previous = initial;
7
+ var nextId = 0;
8
+ function receive(message) {
9
+ if (!pending || pending.id !== message.id) return;
10
+ var entry = pending; pending = null; clearTimeout(entry.timer);
11
+ if (message.error) entry.reject(new Error(message.error));
12
+ else entry.resolve(message.cookies);
13
+ }
14
+ async function sync() {
15
+ var current = await context.cookies();
16
+ var cookies = await new Promise(function (resolve, reject) {
17
+ pending = { id: ++nextId, resolve: resolve, reject: reject, timer: setTimeout(function () { pending = null; reject(new Error('Could not synchronize browser cookies')); }, 4000) };
18
+ try { send({ type: 'cookies', id: pending.id, previous: previous, cookies: current }); }
19
+ catch (error) { clearTimeout(pending.timer); pending = null; reject(error); }
20
+ });
21
+ var remote = new Map(cookies.map(function (cookie) { return [cookieKey(cookie), cookie]; }));
22
+ var local = new Map(current.map(function (cookie) { return [cookieKey(cookie), cookie]; }));
23
+ var updates = cookies.filter(function (cookie) { return JSON.stringify(local.get(cookieKey(cookie))) !== JSON.stringify(cookie); });
24
+ current.forEach(function (cookie) {
25
+ if (!remote.has(cookieKey(cookie))) updates.push(Object.assign({}, cookie, { expires: 1 }));
26
+ });
27
+ if (updates.length) await context.addCookies(updates);
28
+ previous = cookies;
29
+ }
30
+ return { start: function () { return context.addCookies(initial); }, sync: sync, receive: receive };
31
+ }
32
+ module.exports = { attachCookieSync: attachCookieSync };
@@ -0,0 +1,79 @@
1
+ var fs = require('fs');
2
+ var path = require('path');
3
+ var crypto = require('crypto');
4
+
5
+ function cookieKey(cookie) {
6
+ return JSON.stringify([cookie.domain, cookie.path, cookie.name, cookie.partitionKey || '']);
7
+ }
8
+ function cookieMap(cookies) {
9
+ if (!Array.isArray(cookies) || cookies.length > 10000 || JSON.stringify(cookies).length > 2 * 1024 * 1024) throw new Error('Browser cookies exceed the storage limit');
10
+ var result = new Map();
11
+ cookies.forEach(function (cookie) {
12
+ if (!cookie || typeof cookie.name !== 'string' || typeof cookie.value !== 'string' || typeof cookie.domain !== 'string' || typeof cookie.path !== 'string') throw new Error('Invalid browser cookie');
13
+ result.set(cookieKey(cookie), cookie);
14
+ });
15
+ return result;
16
+ }
17
+ function same(a, b) { return JSON.stringify(a) === JSON.stringify(b); }
18
+
19
+ // Merge only a tab's changes, so an idle tab cannot overwrite another tab's login or logout.
20
+ function mergeCookies(saved, previous, current) {
21
+ var merged = cookieMap(saved), before = cookieMap(previous), after = cookieMap(current);
22
+ before.forEach(function (cookie, key) {
23
+ if (!after.has(key) && same(merged.get(key), cookie)) merged.delete(key);
24
+ });
25
+ after.forEach(function (cookie, key) {
26
+ if (!same(before.get(key), cookie)) merged.set(key, cookie);
27
+ });
28
+ return Array.from(merged.values()).filter(function (cookie) { return cookie.expires === -1 || cookie.expires > Date.now() / 1000; });
29
+ }
30
+
31
+ function attachEncryptedStore(root, name, empty) {
32
+ var directory = path.join(root, name);
33
+ function ownerKey(owner) {
34
+ if (typeof owner !== 'string' || !owner || owner.length > 256) throw new Error('Browser data owner is required');
35
+ return crypto.createHash('sha256').update(owner).digest('hex');
36
+ }
37
+ function masterKey() {
38
+ fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
39
+ var file = path.join(directory, '.key');
40
+ try { fs.writeFileSync(file, crypto.randomBytes(32), { flag: 'wx', mode: 0o600 }); }
41
+ catch (error) { if (error.code !== 'EEXIST') throw error; }
42
+ return fs.readFileSync(file);
43
+ }
44
+ function read(owner) {
45
+ var id = ownerKey(owner), raw;
46
+ try { raw = fs.readFileSync(path.join(directory, id + '.json'), 'utf8'); }
47
+ catch (error) { if (error.code === 'ENOENT') return empty(); throw new Error('Could not read saved browser data'); }
48
+ try {
49
+ var parts = JSON.parse(raw).map(function (part) { return Buffer.from(part, 'base64'); });
50
+ var cipher = crypto.createDecipheriv('aes-256-gcm', masterKey(), parts[0]);
51
+ cipher.setAAD(Buffer.from(id)); cipher.setAuthTag(parts[1]);
52
+ var cookies = JSON.parse(Buffer.concat([cipher.update(parts[2]), cipher.final()]).toString('utf8'));
53
+ return cookies;
54
+ } catch (error) { throw new Error('Could not decrypt saved browser data'); }
55
+ }
56
+ function write(owner, cookies) {
57
+ var id = ownerKey(owner), iv = crypto.randomBytes(12);
58
+ var cipher = crypto.createCipheriv('aes-256-gcm', masterKey(), iv);
59
+ cipher.setAAD(Buffer.from(id));
60
+ var bytes = Buffer.concat([cipher.update(JSON.stringify(cookies), 'utf8'), cipher.final()]);
61
+ var file = path.join(directory, id + '.json'), temp = file + '.' + crypto.randomBytes(8).toString('hex') + '.tmp';
62
+ try {
63
+ fs.writeFileSync(temp, JSON.stringify([iv, cipher.getAuthTag(), bytes].map(function (part) { return part.toString('base64'); })), { mode: 0o600 });
64
+ fs.renameSync(temp, file);
65
+ } finally { try { fs.unlinkSync(temp); } catch (error) { if (error.code !== 'ENOENT') throw error; } }
66
+ return cookies;
67
+ }
68
+ return { read: read, write: write };
69
+ }
70
+ function attachCookieStore(root) {
71
+ var disk = attachEncryptedStore(root, 'browser-cookies', function () { return []; });
72
+ function read(owner) { return mergeCookies(disk.read(owner), [], []); }
73
+ return { read: read, clear: function (owner) { disk.write(owner, []); }, exchange: function (owner, previous, current) {
74
+ var saved = read(owner), merged = mergeCookies(saved, previous, current);
75
+ if (!same(saved, merged)) disk.write(owner, merged);
76
+ return merged;
77
+ } };
78
+ }
79
+ module.exports = { attachEncryptedStore: attachEncryptedStore, attachCookieStore: attachCookieStore, mergeCookies: mergeCookies, cookieKey: cookieKey };
@@ -5,6 +5,8 @@ var buildUserEnv = require("./build-user-env").buildUserEnv;
5
5
  var wrapSpawnAsUser = require("./os-users").wrapSpawnAsUser;
6
6
 
7
7
  function createRuntime(options) {
8
+ var initialStorage = options.storage ? options.storage.read() : null;
9
+ var initialCookies = options.cookies ? options.cookies.read() : null;
8
10
  var identity = options.identity;
9
11
  var env = buildUserEnv(identity);
10
12
  if (process.platform === "win32" && !identity) {
@@ -14,7 +16,9 @@ function createRuntime(options) {
14
16
  if (identity) { opts.uid = identity.uid; opts.gid = identity.gid; }
15
17
  var spec = wrapSpawnAsUser(process.execPath, [path.join(__dirname, "shared-browser-worker.js")], opts);
16
18
  var child = spawn(spec.command, spec.args, spec.options);
19
+ var exited = new Promise(function (resolve) { child.once("close", resolve); });
17
20
  var closed = false;
21
+ var closing = false;
18
22
  var nextId = 0;
19
23
  var pending = new Map();
20
24
  var buffer = "";
@@ -25,19 +29,30 @@ function createRuntime(options) {
25
29
  function fail(message) {
26
30
  pending.forEach(function (entry) { clearTimeout(entry.timer); entry.reject(new Error(message)); });
27
31
  pending.clear();
28
- if (!closed) options.onEvent({ type: "error", error: message });
32
+ if (!closed && !closing) options.onEvent({ type: "error", error: message });
29
33
  }
30
34
  child.stdin.on("error", function () {});
31
35
  child.stdout.setEncoding("utf8");
32
36
  child.stdout.on("data", function (chunk) {
33
37
  buffer += chunk;
34
- if (buffer.length > 8 * 1024 * 1024) { fail("Browser response too large"); child.kill(); return; }
38
+ if (buffer.length > 32 * 1024 * 1024) { fail("Browser response too large"); child.kill(); return; }
35
39
  var at;
36
40
  while ((at = buffer.indexOf("\n")) >= 0) {
37
41
  var line = buffer.slice(0, at); buffer = buffer.slice(at + 1);
38
42
  try {
39
43
  var message = JSON.parse(line);
40
- if (message.type === "result") {
44
+ if (message.type === "storage") {
45
+ try {
46
+ if (!options.storage) throw new Error("Personal site data is unavailable");
47
+ send({ type: "storage", id: message.id, storage: options.storage.exchange(message.previous, message.storage) });
48
+ } catch (error) { send({ type: "storage", id: message.id, error: "Could not save personal browser site data" }); }
49
+ } else if (message.type === "cookies") {
50
+ try {
51
+ if (!options.cookies) throw new Error("Personal cookies are unavailable");
52
+ var cookies = options.cookies.exchange(message.previous, message.cookies);
53
+ send({ type: "cookies", id: message.id, cookies: cookies });
54
+ } catch (error) { send({ type: "cookies", id: message.id, error: "Could not save personal browser cookies" }); }
55
+ } else if (message.type === "result") {
41
56
  var entry = pending.get(message.id);
42
57
  if (entry) { clearTimeout(entry.timer); pending.delete(message.id); if (message.error) entry.reject(new Error(message.error)); else entry.resolve(message.value); }
43
58
  } else options.onEvent(message);
@@ -45,8 +60,8 @@ function createRuntime(options) {
45
60
  }
46
61
  });
47
62
  child.on("error", function () { fail("Browser process could not start"); });
48
- child.on("exit", function () { fail("Browser process ended"); });
49
- send({ type: "start" });
63
+ child.on("exit", function () { fail("Browser process ended"); closed = true; });
64
+ send({ type: "start", cookies: initialCookies, storage: initialStorage });
50
65
  return {
51
66
  control: function (epoch) {
52
67
  return new Promise(function (resolve, reject) {
@@ -78,13 +93,14 @@ function createRuntime(options) {
78
93
  });
79
94
  },
80
95
  close: function () {
81
- if (closed) return;
82
- closed = true;
96
+ if (closed || closing) return exited;
97
+ closing = true;
83
98
  fail("Browser closed");
84
- child.stdin.end();
85
- var timer = setTimeout(function () { child.kill("SIGKILL"); }, 5000);
99
+ try { send({ type: "close" }); } catch (error) { child.stdin.end(); }
100
+ var timer = setTimeout(function () { child.kill("SIGKILL"); }, 30000);
86
101
  timer.unref();
87
102
  child.once("exit", function () { clearTimeout(timer); });
103
+ return exited;
88
104
  },
89
105
  };
90
106
  }
@@ -0,0 +1,43 @@
1
+ var cookieKey = require('./shared-browser-cookies').cookieKey;
2
+ // Saved website data only crosses the private worker pipe, never the agent tool channel.
3
+ function attachStorageSync(context, initial, send) {
4
+ var previous = initial, pending = null, nextId = 0;
5
+ function receive(message) {
6
+ if (!pending || pending.id !== message.id) return;
7
+ var entry = pending; pending = null; clearTimeout(entry.timer);
8
+ if (message.error) entry.reject(new Error(message.error)); else entry.resolve(message.storage);
9
+ }
10
+ async function sync() {
11
+ var current = await context.storageState({ indexedDB: true });
12
+ var saved = await new Promise(function (resolve, reject) {
13
+ pending = { id: ++nextId, resolve: resolve, reject: reject, timer: setTimeout(function () { pending = null; reject(new Error('Could not synchronize browser site data')); }, 10000) };
14
+ try { send({ type: 'storage', id: pending.id, previous: previous, storage: current }); }
15
+ catch (error) { clearTimeout(pending.timer); pending = null; reject(error); }
16
+ });
17
+ var remote = new Map(saved.cookies.map(function (cookie) { return [cookieKey(cookie), cookie]; }));
18
+ var local = new Map(current.cookies.map(function (cookie) { return [cookieKey(cookie), cookie]; }));
19
+ var updates = saved.cookies.filter(function (cookie) { return JSON.stringify(local.get(cookieKey(cookie))) !== JSON.stringify(cookie); });
20
+ current.cookies.forEach(function (cookie) { if (!remote.has(cookieKey(cookie))) updates.push(Object.assign({}, cookie, { expires: 1 })); });
21
+ if (updates.length) await context.addCookies(updates);
22
+ if (previous.generation !== saved.generation) {
23
+ var deletions = (saved.deletions || []).filter(function (entry) { return entry.generation > previous.generation; });
24
+ var unknown = !deletions.length || deletions[0].generation > previous.generation + 1;
25
+ var removed = current.origins.filter(function (origin) {
26
+ return unknown || deletions.some(function (entry) { return entry.operation === 'clear_data' || (entry.operation === 'delete_site' && new URL(origin.origin).hostname === entry.target); });
27
+ });
28
+ if (removed.length) {
29
+ var page = context.pages()[0] || await context.newPage();
30
+ var cdp = await context.newCDPSession(page);
31
+ try {
32
+ for (var origin of removed) await cdp.send('Storage.clearDataForOrigin', { origin: origin.origin, storageTypes: 'local_storage,indexeddb' });
33
+ } finally { await cdp.detach(); }
34
+ }
35
+ current = await context.storageState({ indexedDB: true });
36
+ }
37
+ // Restore origin storage on new tabs, rather than replacing live IndexedDB connections.
38
+ // Each open tab contributes only its own changes. Human removals also clear live origins.
39
+ previous = { generation: saved.generation, cookies: saved.cookies, origins: current.origins };
40
+ }
41
+ return { start: function () { return context.setStorageState({ cookies: initial.cookies, origins: initial.origins }); }, sync: sync, receive: receive };
42
+ }
43
+ module.exports = { attachStorageSync: attachStorageSync };