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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (588) hide show
  1. package/lib/account-auth-policy.js +21 -0
  2. package/lib/account-auth-socket.js +30 -0
  3. package/lib/account-auth-throttle.js +44 -0
  4. package/lib/account-auth-transport.js +48 -0
  5. package/lib/account-login-page.js +28 -0
  6. package/lib/account-passkey-challenges.js +31 -0
  7. package/lib/account-passkey-page.js +89 -0
  8. package/lib/account-passkey-policy.js +39 -0
  9. package/lib/account-password-page.js +69 -0
  10. package/lib/account-passwords.js +36 -0
  11. package/lib/account-remembered.js +77 -0
  12. package/lib/account-session-page.js +51 -0
  13. package/lib/account-session-store.js +82 -0
  14. package/lib/builtin-mates.js +19 -16
  15. package/lib/bundled-skills/clay-agent-browser/SKILL.md +6 -2
  16. package/lib/canonical-clay-record-authority.js +15 -0
  17. package/lib/canonical-clay-scheduling-authority.js +19 -0
  18. package/lib/claude-hook-installer.js +1 -239
  19. package/lib/claude-jsonl-watcher.js +1 -204
  20. package/lib/clay-control-presentation-binding.js +96 -0
  21. package/lib/clay-control-presentation.js +128 -0
  22. package/lib/clay-control-target-projection.js +26 -0
  23. package/lib/clay-mate-chat-receipts.js +26 -0
  24. package/lib/clay-mate-chat.js +88 -0
  25. package/lib/clay-mate-knowledge-input.js +26 -0
  26. package/lib/clay-mate-knowledge.js +95 -0
  27. package/lib/clay-mate-lifecycle.js +95 -0
  28. package/lib/clay-product-control-input.js +33 -0
  29. package/lib/clay-product-control-tools.js +51 -0
  30. package/lib/clay-product-control.js +247 -0
  31. package/lib/clay-project-lifecycle.js +154 -0
  32. package/lib/clay-project-record-input.js +44 -0
  33. package/lib/clay-project-records.js +84 -0
  34. package/lib/clay-scheduling-input.js +21 -0
  35. package/lib/clay-scheduling-receipts.js +26 -0
  36. package/lib/clay-scheduling.js +119 -0
  37. package/lib/clay-screen-controls.js +104 -0
  38. package/lib/clay-skill-install.js +1 -33
  39. package/lib/clay-workspace-controls.js +84 -0
  40. package/lib/clay-workspace-input.js +17 -0
  41. package/lib/clay-workspace-receipts.js +26 -0
  42. package/lib/cli-sessions.js +1 -300
  43. package/lib/codex-defaults.js +1 -28
  44. package/lib/context-usage.js +3 -2
  45. package/lib/contextual-screen-snapshot.js +38 -0
  46. package/lib/daemon-project-access.js +11 -0
  47. package/lib/daemon-project-lifecycle-callbacks.js +15 -0
  48. package/lib/daemon-project-lifecycle.js +262 -0
  49. package/lib/daemon-projects.js +1 -1
  50. package/lib/daemon.js +80 -276
  51. package/lib/default-ai-runtime.js +4 -8
  52. package/lib/dm-digest-cursor.js +120 -0
  53. package/lib/email-mcp-server.js +1 -1
  54. package/lib/issues-service.js +29 -15
  55. package/lib/kiro-defaults.js +1 -22
  56. package/lib/knowledge-db-import-validation.js +46 -0
  57. package/lib/knowledge-db-import.js +99 -0
  58. package/lib/knowledge-db-service.js +24 -33
  59. package/lib/knowledge-db-storage-nedb-maintenance.js +99 -0
  60. package/lib/knowledge-db-storage-nedb.js +66 -0
  61. package/lib/knowledge-db-storage.js +72 -0
  62. package/lib/knowledge-db-validation.js +0 -0
  63. package/lib/knowledge-document-index.js +2 -1
  64. package/lib/knowledge-file-store.js +7 -1
  65. package/lib/knowledge-product-operations.js +46 -0
  66. package/lib/mate-avatar-catalog.js +12 -0
  67. package/lib/mate-avatar-migration.js +41 -0
  68. package/lib/mate-context-service.js +138 -0
  69. package/lib/mate-context-tools.js +21 -0
  70. package/lib/mate-creation-mcp-server.js +2 -0
  71. package/lib/mate-knowledge-canonical-access.js +10 -0
  72. package/lib/mate-knowledge-mate-bound.js +53 -0
  73. package/lib/mate-knowledge-mcp-server.js +55 -8
  74. package/lib/mate-knowledge-service.js +16 -34
  75. package/lib/mate-knowledge-text-tools.js +106 -0
  76. package/lib/mate-lifecycle-service.js +94 -0
  77. package/lib/mate-message-delivery.js +43 -0
  78. package/lib/mate-ready-creation.js +9 -1
  79. package/lib/mate-schedule-input.js +29 -0
  80. package/lib/mate-schedule-lifecycle.js +151 -0
  81. package/lib/mate-scheduling.js +103 -0
  82. package/lib/mates.js +18 -6
  83. package/lib/mcp-agent-tools.js +117 -0
  84. package/lib/mcp-connection-store.js +119 -15
  85. package/lib/mcp-import-credentials.js +31 -0
  86. package/lib/mcp-local-transport.js +13 -0
  87. package/lib/mcp-oauth.js +8 -6
  88. package/lib/mcp-proxy.js +2 -32
  89. package/lib/mcp-query-bridge.js +30 -0
  90. package/lib/mcp-remote-connections.js +74 -20
  91. package/lib/mcp-source-adapters.js +1 -0
  92. package/lib/mcp-source-context.js +1 -0
  93. package/lib/mcp-source-discovery.js +1 -0
  94. package/lib/mcp-source-plugins.js +1 -0
  95. package/lib/mcp-source-restrictions.js +1 -0
  96. package/lib/mcp-tool-policy.js +9 -0
  97. package/lib/migrate-single-user.js +3 -23
  98. package/lib/notes-checklist.js +50 -0
  99. package/lib/notes.js +49 -3
  100. package/lib/os-user-diagnostics.js +2 -4
  101. package/lib/os-users.js +24 -70
  102. package/lib/pane-pending-interactions.js +20 -0
  103. package/lib/pane-session-activation.js +114 -0
  104. package/lib/pane-session-transport.js +26 -0
  105. package/lib/project-admin-overview.js +51 -0
  106. package/lib/project-ask-user.js +8 -4
  107. package/lib/project-connection.js +14 -10
  108. package/lib/project-control-git-view.js +12 -0
  109. package/lib/project-debate.js +1 -0
  110. package/lib/project-delegated-follow-up.js +2 -1
  111. package/lib/project-directory-claim.js +65 -0
  112. package/lib/project-file-operations.js +61 -0
  113. package/lib/project-filesystem.js +15 -85
  114. package/lib/project-full-access.js +23 -2
  115. package/lib/project-http.js +7 -4
  116. package/lib/project-knowledge.js +32 -18
  117. package/lib/project-lifecycle-operations.js +98 -0
  118. package/lib/project-lifecycle-process-witness.js +32 -0
  119. package/lib/project-lifecycle-runtime.js +50 -0
  120. package/lib/project-linux-access.js +22 -0
  121. package/lib/project-logs-canonical-clay.js +27 -0
  122. package/lib/project-logs-clay-query.js +16 -0
  123. package/lib/project-logs-schema.js +4 -2
  124. package/lib/project-logs-service.js +8 -7
  125. package/lib/project-logs.js +1 -0
  126. package/lib/project-loop.js +1 -0
  127. package/lib/project-mate-chat-control.js +55 -0
  128. package/lib/project-mate-creation-proposal.js +18 -3
  129. package/lib/project-mate-interaction.js +40 -62
  130. package/lib/project-mcp.js +54 -16
  131. package/lib/project-models.js +14 -31
  132. package/lib/project-notifications.js +76 -17
  133. package/lib/project-ownership.js +77 -0
  134. package/lib/project-pair-result-delivery.js +14 -3
  135. package/lib/project-pair-usage.js +12 -13
  136. package/lib/project-pending-message-queue.js +4 -1
  137. package/lib/project-product-control.js +89 -0
  138. package/lib/project-product-session-queue.js +46 -0
  139. package/lib/project-push-access.js +28 -0
  140. package/lib/project-scheduled-message-queue.js +30 -0
  141. package/lib/project-scheduled-messages.js +67 -68
  142. package/lib/project-scheduled-task-control.js +83 -0
  143. package/lib/project-scheduled-tasks.js +13 -2
  144. package/lib/project-scheduling-access.js +10 -0
  145. package/lib/project-server-settings.js +1 -0
  146. package/lib/project-session-actions.js +65 -0
  147. package/lib/project-session-delete.js +8 -1
  148. package/lib/project-session-document.js +27 -7
  149. package/lib/project-session-github.js +63 -19
  150. package/lib/project-session-history-actions.js +167 -0
  151. package/lib/project-session-linear.js +14 -6
  152. package/lib/project-session-notes.js +7 -3
  153. package/lib/project-session-pair.js +1 -1
  154. package/lib/project-session-runtime-actions.js +64 -0
  155. package/lib/project-session-spawn.js +2 -3
  156. package/lib/project-session-vendor.js +55 -0
  157. package/lib/project-sessions.js +103 -272
  158. package/lib/project-shared-browser.js +78 -17
  159. package/lib/project-studio-presentation.js +58 -0
  160. package/lib/project-user-knowledge.js +2 -1
  161. package/lib/project-user-message.js +67 -1
  162. package/lib/project-vendor-login.js +6 -36
  163. package/lib/project-workspace-operations.js +126 -0
  164. package/lib/project-workspace-query.js +19 -2
  165. package/lib/project.js +178 -45
  166. package/lib/public/app.js +46 -0
  167. package/lib/public/appearance-bootstrap.js +16 -0
  168. package/lib/public/auth/account-login.css +98 -0
  169. package/lib/public/auth/account-login.js +104 -0
  170. package/lib/public/css/clay-tool-activity.css +51 -0
  171. package/lib/public/css/clay-workspace.css +29 -0
  172. package/lib/public/css/command-palette.css +12 -33
  173. package/lib/public/css/contextual-clay.css +240 -0
  174. package/lib/public/css/home-debate-planning.css +2 -0
  175. package/lib/public/css/home-mate-creation.css +5 -0
  176. package/lib/public/css/input.css +6 -0
  177. package/lib/public/css/mate-avatar-gallery.css +12 -0
  178. package/lib/public/css/mate-conversation.css +10 -5
  179. package/lib/public/css/messages.css +6 -2
  180. package/lib/public/css/overlays.css +4 -2
  181. package/lib/public/css/project-admin-overview.css +13 -0
  182. package/lib/public/css/session-folders.css +11 -0
  183. package/lib/public/css/session-github.css +46 -1
  184. package/lib/public/css/shared-browser.css +35 -1
  185. package/lib/public/css/sticky-notes.css +87 -1
  186. package/lib/public/css/user-settings-sessions.css +42 -0
  187. package/lib/public/index.html +28 -10
  188. package/lib/public/mate-avatars/B01.png +0 -0
  189. package/lib/public/mate-avatars/B02.png +0 -0
  190. package/lib/public/mate-avatars/B03.png +0 -0
  191. package/lib/public/mate-avatars/B04.png +0 -0
  192. package/lib/public/mate-avatars/B05.png +0 -0
  193. package/lib/public/mate-avatars/B06.png +0 -0
  194. package/lib/public/mate-avatars/B07.png +0 -0
  195. package/lib/public/mate-avatars/B08.png +0 -0
  196. package/lib/public/mate-avatars/B09.png +0 -0
  197. package/lib/public/mate-avatars/B10.png +0 -0
  198. package/lib/public/mate-avatars/B11.png +0 -0
  199. package/lib/public/mate-avatars/B12.png +0 -0
  200. package/lib/public/mate-avatars/B13.png +0 -0
  201. package/lib/public/mate-avatars/B14.png +0 -0
  202. package/lib/public/mate-avatars/B15.png +0 -0
  203. package/lib/public/mate-avatars/B16.png +0 -0
  204. package/lib/public/mate-avatars/B17.png +0 -0
  205. package/lib/public/mate-avatars/B18.png +0 -0
  206. package/lib/public/mate-avatars/B19.png +0 -0
  207. package/lib/public/mate-avatars/B20.png +0 -0
  208. package/lib/public/mate-avatars/B21.png +0 -0
  209. package/lib/public/mate-avatars/B22.png +0 -0
  210. package/lib/public/mate-avatars/B23.png +0 -0
  211. package/lib/public/mate-avatars/B24.png +0 -0
  212. package/lib/public/mate-avatars/B25.png +0 -0
  213. package/lib/public/mate-avatars/B26.png +0 -0
  214. package/lib/public/mate-avatars/B27.png +0 -0
  215. package/lib/public/mate-avatars/B28.png +0 -0
  216. package/lib/public/mate-avatars/B29.png +0 -0
  217. package/lib/public/mate-avatars/B30.png +0 -0
  218. package/lib/public/mate-avatars/B31.png +0 -0
  219. package/lib/public/mate-avatars/B32.png +0 -0
  220. package/lib/public/mate-avatars/B33.png +0 -0
  221. package/lib/public/mate-avatars/B34.png +0 -0
  222. package/lib/public/mate-avatars/B35.png +0 -0
  223. package/lib/public/mate-avatars/B36.png +0 -0
  224. package/lib/public/mate-avatars/B37.png +0 -0
  225. package/lib/public/mate-avatars/B38.png +0 -0
  226. package/lib/public/mate-avatars/B39.png +0 -0
  227. package/lib/public/mate-avatars/B40.png +0 -0
  228. package/lib/public/mate-avatars/B41.png +0 -0
  229. package/lib/public/mate-avatars/B42.png +0 -0
  230. package/lib/public/mate-avatars/B43.png +0 -0
  231. package/lib/public/mate-avatars/B44.png +0 -0
  232. package/lib/public/mate-avatars/B45.png +0 -0
  233. package/lib/public/mate-avatars/B46.png +0 -0
  234. package/lib/public/mate-avatars/B47.png +0 -0
  235. package/lib/public/mate-avatars/B48.png +0 -0
  236. package/lib/public/mate-avatars/C01.png +0 -0
  237. package/lib/public/mate-avatars/C02.png +0 -0
  238. package/lib/public/mate-avatars/C03.png +0 -0
  239. package/lib/public/mate-avatars/C04.png +0 -0
  240. package/lib/public/mate-avatars/C05.png +0 -0
  241. package/lib/public/mate-avatars/C06.png +0 -0
  242. package/lib/public/mate-avatars/C07.png +0 -0
  243. package/lib/public/mate-avatars/C08.png +0 -0
  244. package/lib/public/mate-avatars/C09.png +0 -0
  245. package/lib/public/mate-avatars/C10.png +0 -0
  246. package/lib/public/mate-avatars/C11.png +0 -0
  247. package/lib/public/mate-avatars/C12.png +0 -0
  248. package/lib/public/mate-avatars/C13.png +0 -0
  249. package/lib/public/mate-avatars/C14.png +0 -0
  250. package/lib/public/mate-avatars/C15.png +0 -0
  251. package/lib/public/mate-avatars/C16.png +0 -0
  252. package/lib/public/mate-avatars/C17.png +0 -0
  253. package/lib/public/mate-avatars/C18.png +0 -0
  254. package/lib/public/mate-avatars/C19.png +0 -0
  255. package/lib/public/mate-avatars/C20.png +0 -0
  256. package/lib/public/mate-avatars/C21.png +0 -0
  257. package/lib/public/mate-avatars/C22.png +0 -0
  258. package/lib/public/mate-avatars/C23.png +0 -0
  259. package/lib/public/mate-avatars/C24.png +0 -0
  260. package/lib/public/mate-avatars/C25.png +0 -0
  261. package/lib/public/mate-avatars/C26.png +0 -0
  262. package/lib/public/mate-avatars/C27.png +0 -0
  263. package/lib/public/mate-avatars/C28.png +0 -0
  264. package/lib/public/mate-avatars/C29.png +0 -0
  265. package/lib/public/mate-avatars/C30.png +0 -0
  266. package/lib/public/mate-avatars/C31.png +0 -0
  267. package/lib/public/mate-avatars/C32.png +0 -0
  268. package/lib/public/mate-avatars/C33.png +0 -0
  269. package/lib/public/mate-avatars/C34.png +0 -0
  270. package/lib/public/mate-avatars/C35.png +0 -0
  271. package/lib/public/mate-avatars/C36.png +0 -0
  272. package/lib/public/mate-avatars/C37.png +0 -0
  273. package/lib/public/mate-avatars/C38.png +0 -0
  274. package/lib/public/mate-avatars/C39.png +0 -0
  275. package/lib/public/mate-avatars/C40.png +0 -0
  276. package/lib/public/mate-avatars/C41.png +0 -0
  277. package/lib/public/mate-avatars/C42.png +0 -0
  278. package/lib/public/mate-avatars/C43.png +0 -0
  279. package/lib/public/mate-avatars/C44.png +0 -0
  280. package/lib/public/mate-avatars/C45.png +0 -0
  281. package/lib/public/mate-avatars/C46.png +0 -0
  282. package/lib/public/mate-avatars/C47.png +0 -0
  283. package/lib/public/mate-avatars/C48.png +0 -0
  284. package/lib/public/mate-avatars/catalog.json +482 -0
  285. package/lib/public/mate-avatars/lead-clay.png +0 -0
  286. package/lib/public/modules/account-auth-settings.js +71 -0
  287. package/lib/public/modules/account-transport-settings.js +51 -0
  288. package/lib/public/modules/admin-settings-projects.js +6 -2
  289. package/lib/public/modules/app-connection.js +11 -1
  290. package/lib/public/modules/app-favicon.js +18 -9
  291. package/lib/public/modules/app-header.js +7 -4
  292. package/lib/public/modules/app-loop-ui.js +2 -0
  293. package/lib/public/modules/app-message-router.js +22 -1
  294. package/lib/public/modules/app-messages.js +119 -17
  295. package/lib/public/modules/app-misc.js +3 -1
  296. package/lib/public/modules/app-notifications.js +11 -5
  297. package/lib/public/modules/app-panels.js +61 -123
  298. package/lib/public/modules/app-projects.js +13 -0
  299. package/lib/public/modules/app-rate-limit.js +7 -27
  300. package/lib/public/modules/app-rendering.js +4 -3
  301. package/lib/public/modules/avatar.js +15 -41
  302. package/lib/public/modules/chat-render-runtime.js +20 -0
  303. package/lib/public/modules/clay-browser-links.js +47 -0
  304. package/lib/public/modules/clay-control-activity.js +214 -0
  305. package/lib/public/modules/clay-control-copy.js +36 -0
  306. package/lib/public/modules/clay-control-detail-targets.js +44 -0
  307. package/lib/public/modules/clay-control-object-targets.js +52 -0
  308. package/lib/public/modules/clay-control-target-visibility.js +12 -0
  309. package/lib/public/modules/clay-control-targets.js +44 -0
  310. package/lib/public/modules/clay-log-links.js +23 -0
  311. package/lib/public/modules/clay-navigation-render.js +52 -0
  312. package/lib/public/modules/clay-owner-navigation.js +33 -0
  313. package/lib/public/modules/clay-session-links.js +31 -0
  314. package/lib/public/modules/clay-studio-bridge.js +20 -0
  315. package/lib/public/modules/clay-studio-document.js +67 -0
  316. package/lib/public/modules/clay-studio-render.js +146 -0
  317. package/lib/public/modules/clay-tool-activity.js +140 -0
  318. package/lib/public/modules/clay-tool-presentation.js +342 -0
  319. package/lib/public/modules/command-palette.js +162 -40
  320. package/lib/public/modules/contextual-ask-session.js +26 -0
  321. package/lib/public/modules/contextual-clay-geometry.js +155 -0
  322. package/lib/public/modules/contextual-clay-session.js +130 -0
  323. package/lib/public/modules/contextual-clay-workspace.js +169 -0
  324. package/lib/public/modules/contextual-clay.js +250 -0
  325. package/lib/public/modules/contextual-composer.js +91 -0
  326. package/lib/public/modules/contextual-mate-context.js +117 -0
  327. package/lib/public/modules/contextual-mate-hint.js +40 -0
  328. package/lib/public/modules/contextual-mate-identity.js +23 -0
  329. package/lib/public/modules/contextual-mate-sessions.js +134 -0
  330. package/lib/public/modules/contextual-search.js +137 -0
  331. package/lib/public/modules/contextual-session-citations.js +58 -0
  332. package/lib/public/modules/debate.js +1 -0
  333. package/lib/public/modules/default-ai.js +11 -3
  334. package/lib/public/modules/elicitation-form.js +5 -0
  335. package/lib/public/modules/filebrowser.js +20 -1
  336. package/lib/public/modules/generation-stop.js +8 -5
  337. package/lib/public/modules/git-panel.js +3 -1
  338. package/lib/public/modules/history-replay-batch.js +13 -1
  339. package/lib/public/modules/home-debate-live.js +2 -0
  340. package/lib/public/modules/home-debate-planning.js +7 -7
  341. package/lib/public/modules/home-mate-avatar-editor.js +127 -208
  342. package/lib/public/modules/home-mate-chat.js +8 -6
  343. package/lib/public/modules/home-mate-creation.js +73 -1
  344. package/lib/public/modules/home-mate-settings.js +19 -12
  345. package/lib/public/modules/icon-strip-tooltip.js +2 -1
  346. package/lib/public/modules/input.js +88 -10
  347. package/lib/public/modules/issues-render.js +3 -2
  348. package/lib/public/modules/knowledge-db-workbench.js +4 -4
  349. package/lib/public/modules/markdown.js +6 -34
  350. package/lib/public/modules/mate-avatar-catalog.js +97 -0
  351. package/lib/public/modules/mate-knowledge-workbench.js +1 -1
  352. package/lib/public/modules/mate-management.js +40 -7
  353. package/lib/public/modules/mcp-connection-view.js +31 -13
  354. package/lib/public/modules/mcp-discovery-view.js +31 -0
  355. package/lib/public/modules/mcp-ui.js +23 -4
  356. package/lib/public/modules/mention.js +3 -0
  357. package/lib/public/modules/message-delivery.js +20 -2
  358. package/lib/public/modules/model-picker.js +2 -0
  359. package/lib/public/modules/pane-activation.js +214 -0
  360. package/lib/public/modules/pane-binding.js +82 -0
  361. package/lib/public/modules/pane-bridge.js +7 -4
  362. package/lib/public/modules/pane-browser-bridge.js +22 -0
  363. package/lib/public/modules/pane-file-bridge.js +4 -0
  364. package/lib/public/modules/pane-issue-bridge.js +4 -1
  365. package/lib/public/modules/passkey-browser.js +69 -0
  366. package/lib/public/modules/passkey-server-settings.js +57 -0
  367. package/lib/public/modules/pending-message-queue.js +1 -0
  368. package/lib/public/modules/permission-control.js +5 -4
  369. package/lib/public/modules/personal-settings-dialog.js +7 -1
  370. package/lib/public/modules/product-review.js +26 -0
  371. package/lib/public/modules/profile.js +1 -238
  372. package/lib/public/modules/project-access-recovery.js +17 -0
  373. package/lib/public/modules/project-admin-overview.js +21 -0
  374. package/lib/public/modules/project-chat-identity.js +13 -4
  375. package/lib/public/modules/project-logs-render.js +6 -2
  376. package/lib/public/modules/project-mate-navigation.js +144 -22
  377. package/lib/public/modules/rewind.js +5 -0
  378. package/lib/public/modules/scheduled-tasks.js +2 -0
  379. package/lib/public/modules/scheduler.js +2 -0
  380. package/lib/public/modules/search-clay-chat.js +5 -440
  381. package/lib/public/modules/server-settings-controls.js +10 -0
  382. package/lib/public/modules/server-settings.js +7 -2
  383. package/lib/public/modules/session-actions.js +5 -2
  384. package/lib/public/modules/session-context-menu.js +5 -0
  385. package/lib/public/modules/session-create-form.js +10 -10
  386. package/lib/public/modules/session-folder-layout.js +1 -1
  387. package/lib/public/modules/session-folder-view-menu.js +9 -0
  388. package/lib/public/modules/session-github.js +85 -14
  389. package/lib/public/modules/session-rich-drafts.js +21 -0
  390. package/lib/public/modules/session-switch-defer.js +67 -0
  391. package/lib/public/modules/session-work-primary.js +51 -0
  392. package/lib/public/modules/settings-defaults.js +27 -28
  393. package/lib/public/modules/shared-browser-settings.js +112 -0
  394. package/lib/public/modules/shared-browser-tabs.js +13 -3
  395. package/lib/public/modules/shared-browser.js +29 -6
  396. package/lib/public/modules/sidebar-mobile.js +4 -3
  397. package/lib/public/modules/sidebar-projects.js +1 -0
  398. package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
  399. package/lib/public/modules/sidebar-sessions.js +1 -0
  400. package/lib/public/modules/split-group-restore.js +68 -0
  401. package/lib/public/modules/split-pair-ui.js +1 -0
  402. package/lib/public/modules/split-pane-reconciler.js +15 -0
  403. package/lib/public/modules/split-pane-renderer.js +87 -6
  404. package/lib/public/modules/split-session-boundary.js +1 -1
  405. package/lib/public/modules/split-view.js +60 -68
  406. package/lib/public/modules/sticky-note-markdown.js +72 -6
  407. package/lib/public/modules/sticky-notes-actions.js +30 -0
  408. package/lib/public/modules/sticky-notes-browser.js +9 -2
  409. package/lib/public/modules/sticky-notes-card.js +23 -7
  410. package/lib/public/modules/sticky-notes-checklist.js +116 -0
  411. package/lib/public/modules/sticky-notes-editor.js +108 -44
  412. package/lib/public/modules/sticky-notes-shared.js +50 -2
  413. package/lib/public/modules/sticky-notes-state.js +66 -0
  414. package/lib/public/modules/sticky-notes.js +34 -51
  415. package/lib/public/modules/stt-controller.js +4 -1
  416. package/lib/public/modules/stt-recording.js +1 -1
  417. package/lib/public/modules/stt.js +7 -2
  418. package/lib/public/modules/terminal.js +9 -0
  419. package/lib/public/modules/theme.js +8 -1
  420. package/lib/public/modules/thinking-lifecycle.js +33 -3
  421. package/lib/public/modules/thinking-view.js +23 -1
  422. package/lib/public/modules/tools.js +60 -11
  423. package/lib/public/modules/tui-grab.js +1 -2
  424. package/lib/public/modules/user-settings-account.js +14 -1
  425. package/lib/public/modules/user-settings-appearance.js +10 -3
  426. package/lib/public/modules/user-settings-editors.js +1 -1
  427. package/lib/public/modules/user-settings-layout.js +11 -2
  428. package/lib/public/modules/user-settings-preferences.js +6 -2
  429. package/lib/public/modules/user-settings-profile.js +12 -2
  430. package/lib/public/modules/user-settings-sessions.js +120 -0
  431. package/lib/public/modules/user-settings.js +6 -2
  432. package/lib/public/modules/vendor-login-browser.js +5 -3
  433. package/lib/public/modules/vendor-login.js +2 -2
  434. package/lib/public/modules/vendor-priority.js +15 -1
  435. package/lib/public/modules/wireframe-workbench.js +5 -2
  436. package/lib/public/modules/you-activity.js +3 -1
  437. package/lib/public/modules/you.js +91 -6
  438. package/lib/public/muse-avatar.svg +4 -0
  439. package/lib/public/style.css +6 -0
  440. package/lib/public/sw.js +3 -1
  441. package/lib/safe-bash-commands.js +3 -45
  442. package/lib/scheduled-task-records.js +3 -1
  443. package/lib/scheduler.js +2 -0
  444. package/lib/sdk-bridge.js +342 -401
  445. package/lib/sdk-foreground-admission.js +16 -0
  446. package/lib/sdk-mcp-descriptors.js +2 -37
  447. package/lib/sdk-message-processor.js +52 -17
  448. package/lib/sdk-quota-snapshot.js +1 -1
  449. package/lib/sdk-response-recovery.js +1 -0
  450. package/lib/sdk-worker.js +2 -677
  451. package/lib/server-account-passkeys.js +186 -0
  452. package/lib/server-account-passwords.js +127 -0
  453. package/lib/server-account-security.js +53 -0
  454. package/lib/server-admin.js +63 -16
  455. package/lib/server-appearance-settings.js +13 -1
  456. package/lib/server-auth.js +107 -79
  457. package/lib/server-contextual-clay-settings.js +40 -0
  458. package/lib/server-contextual-mate-sessions.js +70 -0
  459. package/lib/server-dm.js +2 -1
  460. package/lib/server-global-ws.js +10 -20
  461. package/lib/server-home-chat-events.js +18 -4
  462. package/lib/server-home-chat.js +22 -20
  463. package/lib/server-home-clay-entry.js +23 -4
  464. package/lib/server-home-clay-session-links.js +29 -9
  465. package/lib/server-home-mate-creation.js +1 -0
  466. package/lib/server-home-mcp-consent.js +14 -0
  467. package/lib/server-mates.js +25 -62
  468. package/lib/server-owner-ui.js +118 -0
  469. package/lib/server-path-access.js +38 -0
  470. package/lib/server-project-removal.js +22 -0
  471. package/lib/server-settings.js +8 -2
  472. package/lib/server.js +165 -43
  473. package/lib/session-config-transition.js +45 -0
  474. package/lib/session-folders.js +7 -2
  475. package/lib/session-fork-history.js +21 -0
  476. package/lib/session-github.js +9 -2
  477. package/lib/session-hygiene.js +3 -35
  478. package/lib/session-permission-mode.js +4 -3
  479. package/lib/session-skill-scope.js +11 -0
  480. package/lib/session-visibility.js +5 -2
  481. package/lib/session-work-primary.js +50 -0
  482. package/lib/sessions.js +64 -99
  483. package/lib/shared-browser-cookie-sync.js +32 -0
  484. package/lib/shared-browser-cookies.js +79 -0
  485. package/lib/shared-browser-runtime.js +25 -9
  486. package/lib/shared-browser-storage-sync.js +43 -0
  487. package/lib/shared-browser-storage.js +101 -0
  488. package/lib/shared-browser-tools.js +2 -1
  489. package/lib/shared-browser-worker.js +46 -10
  490. package/lib/terminal-manager.js +65 -6
  491. package/lib/tool-llm.js +1 -1
  492. package/lib/tui-transcript-index.js +1 -132
  493. package/lib/user-knowledge-service.js +23 -1
  494. package/lib/users-auth.js +38 -3
  495. package/lib/users-contextual-clay-preferences.js +31 -0
  496. package/lib/users-create.js +97 -0
  497. package/lib/users-permissions.js +2 -8
  498. package/lib/users-server-pin.js +37 -0
  499. package/lib/users.js +18 -84
  500. package/lib/vendor-login-browser.js +1 -11
  501. package/lib/workspace-assignment-service.js +25 -0
  502. package/lib/workspace-query-access.js +4 -1
  503. package/lib/workspace-query-mcp-server.js +1 -1
  504. package/lib/workspace-query-service.js +13 -2
  505. package/lib/ws-request.js +1 -0
  506. package/lib/ws-schema.js +18 -2
  507. package/lib/yoke/acp-agent-profiles.js +7 -5
  508. package/lib/yoke/adapters/antigravity.js +3 -14
  509. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  510. package/lib/yoke/adapters/claude.js +54 -50
  511. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  512. package/lib/yoke/adapters/codex.js +53 -111
  513. package/lib/yoke/adapters/kiro.js +3 -1
  514. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  515. package/lib/yoke/adapters/muse.js +122 -0
  516. package/lib/yoke/auth-events.js +17 -0
  517. package/lib/yoke/claude-hook-installer.js +271 -0
  518. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  519. package/lib/yoke/claude-maintenance.js +55 -0
  520. package/lib/yoke/claude-permission-patterns.js +53 -0
  521. package/lib/yoke/claude-response-recovery.js +155 -0
  522. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  523. package/lib/yoke/claude-worker-startup.js +28 -0
  524. package/lib/yoke/clay-skill-install.js +33 -0
  525. package/lib/yoke/cli-sessions.js +300 -0
  526. package/lib/yoke/codex-app-server.js +7 -12
  527. package/lib/yoke/codex-idle-recovery.js +81 -1
  528. package/lib/yoke/codex-recovery-admission.js +164 -0
  529. package/lib/yoke/configuration.js +13 -0
  530. package/lib/yoke/discovery.js +70 -0
  531. package/lib/yoke/errors.js +8 -0
  532. package/lib/yoke/host-environment.js +7 -0
  533. package/lib/yoke/index.js +9 -51
  534. package/lib/yoke/interface.js +116 -0
  535. package/lib/yoke/kiro-acp-server.js +5 -5
  536. package/lib/yoke/legacy-sessions.js +89 -0
  537. package/lib/yoke/login-protocol.js +25 -0
  538. package/lib/yoke/maintenance.js +12 -0
  539. package/lib/yoke/mcp-proxy.js +32 -0
  540. package/lib/yoke/mcp-source-adapters.js +91 -0
  541. package/lib/yoke/mcp-source-context.js +42 -0
  542. package/lib/yoke/mcp-source-discovery.js +169 -0
  543. package/lib/yoke/mcp-source-plugins.js +68 -0
  544. package/lib/yoke/mcp-source-restrictions.js +47 -0
  545. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  546. package/lib/yoke/model-preferences.js +6 -0
  547. package/lib/yoke/muse-artifacts.js +36 -0
  548. package/lib/yoke/muse-controls.js +50 -0
  549. package/lib/yoke/muse-input.js +64 -0
  550. package/lib/yoke/muse-items.js +157 -0
  551. package/lib/yoke/muse-policy.js +52 -0
  552. package/lib/yoke/muse-query.js +428 -0
  553. package/lib/yoke/muse-runtime.js +211 -0
  554. package/lib/yoke/muse-services.js +79 -0
  555. package/lib/yoke/muse-skills.js +79 -0
  556. package/lib/yoke/muse-turns.js +71 -0
  557. package/lib/yoke/options/acp.js +2 -0
  558. package/lib/yoke/options/antigravity.js +2 -0
  559. package/lib/yoke/options/claude.js +21 -0
  560. package/lib/yoke/options/codex-defaults.js +29 -0
  561. package/lib/yoke/options/codex-settings.js +21 -0
  562. package/lib/yoke/options/codex.js +6 -0
  563. package/lib/yoke/options/kiro-defaults.js +22 -0
  564. package/lib/yoke/options/kiro.js +5 -0
  565. package/lib/yoke/options/muse.js +5 -0
  566. package/lib/yoke/provider-contract.js +5 -0
  567. package/lib/yoke/providers/antigravity-executable.js +8 -0
  568. package/lib/yoke/providers/claude-executable.js +40 -0
  569. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  570. package/lib/yoke/providers/claude-process.js +97 -0
  571. package/lib/yoke/providers/claude-provision.js +75 -0
  572. package/lib/yoke/providers/codex-errors.js +8 -0
  573. package/lib/yoke/providers/muse-executable.js +17 -0
  574. package/lib/yoke/provisioning.js +6 -0
  575. package/lib/yoke/query-options.js +10 -0
  576. package/lib/yoke/response-recovery.js +41 -0
  577. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  578. package/lib/yoke/sdk-server-factory.js +7 -0
  579. package/lib/yoke/session-history.js +8 -0
  580. package/lib/yoke/session-tool-transport.js +34 -13
  581. package/lib/yoke/settings.js +23 -0
  582. package/lib/yoke/source-locations.js +4 -0
  583. package/lib/yoke/title-query.js +18 -7
  584. package/lib/yoke/tui-transcript-index.js +132 -0
  585. package/lib/yoke/usage.js +48 -0
  586. package/lib/yoke/user-input.js +13 -0
  587. package/lib/yoke/vendor-registry.js +81 -1
  588. package/package.json +11 -4
@@ -1,8 +1,14 @@
1
+ import { adoptDocumentSource } from './clay-studio-document.js';
2
+ import { trustedStudioFrame } from './clay-studio-render.js';
3
+ import { handlePaneBrowserMessage } from './pane-browser-bridge.js';
1
4
  import { openWireframe } from './wireframe-workbench.js';
2
5
  // Two-pane iframe shell for the split-view spike.
3
6
 
4
7
  import { store } from './store.js';
5
8
  import { getWs } from './ws-ref.js';
9
+ import { livePaneBinding } from './pane-binding.js';
10
+ import { showToast } from './utils.js';
11
+ import { checkComposerDeparture } from './session-rich-drafts.js';
6
12
  import { getCachedSessions } from './sidebar-sessions.js';
7
13
  import { refreshIcons } from './icons.js';
8
14
  import { detachTuiView } from './session-tui-view.js';
@@ -11,11 +17,12 @@ import { syncPairChrome } from './split-pair-ui.js';
11
17
  import { presentMarkdownEdit } from './filebrowser.js';
12
18
  import { autoStartLoginIfNeeded } from './vendor-login.js';
13
19
  import { isCurrentProjectSessionReady } from './split-session-boundary.js';
14
- import { splitPanesMatchProject, reconcileRestoredSplit } from './project-activation.js';
20
+ import { splitPanesMatchProject } from './project-activation.js';
15
21
  import { handlePaneIssueMessage } from './pane-issue-bridge.js';
16
22
  import { handlePaneFileMessage, revealFilesPanel } from './pane-file-bridge.js';
17
23
  import { openFile } from './filebrowser.js';
18
- import { reconcileSplitPanes } from './split-pane-reconciler.js';
24
+ import { restoreSplitGroup, reconcileSplitIdentity } from './split-group-restore.js';
25
+ import { reconcileSplitPanes, splitPaneForSession } from './split-pane-reconciler.js';
19
26
  import { createSplitPane, updateSplitPaneMetadata, updatePaneContextChip, updatePaneFullAccessButton } from './split-pane-renderer.js';
20
27
 
21
28
  var host = null;
@@ -51,12 +58,7 @@ function sessionById(sessionId) {
51
58
  }
52
59
 
53
60
  function paneForSession(sessionId) {
54
- var session = sessionById(sessionId);
55
- return {
56
- slug: store.get('currentSlug'),
57
- sessionId: sessionId,
58
- title: (session && session.title) || ("Session " + sessionId),
59
- };
61
+ return splitPaneForSession(sessionId, store.get('currentSlug'), getCachedSessions());
60
62
  }
61
63
 
62
64
  // Arc-style drop preview: hovering one half folds the live app into the
@@ -87,6 +89,7 @@ function showDropOverlay() {
87
89
  }
88
90
 
89
91
  function switchNativeSession(sessionId, expectedSlug) {
92
+ if (!canLeavePanes()) return;
90
93
  store.set({ splitPanes: null });
91
94
  var ws = getWs();
92
95
  var state = store.snap();
@@ -125,16 +128,16 @@ export function syncPaneTitles() {
125
128
  var split = store.get('splitPanes');
126
129
  if (!split || !split.panes || !host) return;
127
130
  var titleEls = host.querySelectorAll(".split-pane-title");
131
+ var paneEls = host.querySelectorAll('.split-pane');
128
132
  for (var i = 0; i < split.panes.length && i < titleEls.length; i++) {
129
- var session = sessionById(split.panes[i].sessionId);
133
+ var session = sessionById(paneEls[i] && Number(paneEls[i].dataset.sessionId) || split.panes[i].sessionId);
130
134
  if (!session || !session.title) continue;
131
- split.panes[i].title = session.title;
132
135
  if (titleEls[i].parentNode) titleEls[i].parentNode.title = session.title;
133
136
  if (titleEls[i].style.display !== "none") titleEls[i].textContent = session.title;
134
137
  }
135
138
  var accessBtns = host.querySelectorAll(".split-pane-full-access");
136
139
  for (var ai = 0; ai < split.panes.length && ai < accessBtns.length; ai++) {
137
- updatePaneFullAccessButton(accessBtns[ai], sessionById(split.panes[ai].sessionId));
140
+ updatePaneFullAccessButton(accessBtns[ai], sessionById(paneEls[ai] && Number(paneEls[ai].dataset.sessionId) || split.panes[ai].sessionId));
138
141
  }
139
142
  syncPairChrome(host, split);
140
143
  }
@@ -143,22 +146,13 @@ function handlePaneMessage(event) {
143
146
  if (event.origin !== window.location.origin) return;
144
147
  var msg = event.data;
145
148
  if (!msg || !host) return;
146
- if (msg.type === "clay-pane-present-wireframe") {
147
- var frames = host.querySelectorAll(".split-pane-frame");
148
- var split = store.get('splitPanes');
149
- var trusted = Array.prototype.some.call(frames, function (frame) {
150
- if (frame.contentWindow !== event.source || frame.dataset.projectSlug !== msg.projectSlug || String(frame.dataset.sessionId) !== String(msg.sessionId) || msg.projectSlug !== store.get('currentSlug')) return false;
151
- return split && split.panes.some(function (pane) {
152
- var expected = new URL('/p/' + encodeURIComponent(pane.slug) + '/?pane=1&session=' + encodeURIComponent(pane.sessionId), window.location.href).href;
153
- return pane.slug === msg.projectSlug && String(pane.sessionId) === String(msg.sessionId) && frame.src === expected;
154
- });
155
- });
156
- if (trusted && msg.message) openWireframe(msg.message);
157
- return;
158
- }
159
- if (msg.type === "clay-pane-present-markdown") {
160
- var present = msg.message;
161
- if (present) presentMarkdownEdit(present);
149
+ var reusable = Array.from(host.querySelectorAll('.split-pane-frame')).find(function (frame) { return frame.contentWindow === event.source && frame.clayPane; });
150
+ if (reusable && !livePaneBinding(reusable, msg)) return;
151
+ if (msg.type === "clay-pane-present-wireframe" || msg.type === "clay-pane-present-markdown") {
152
+ if (msg.message && !msg.message.controlPresentation && trustedStudioFrame(event, msg)) {
153
+ if (msg.type === "clay-pane-present-wireframe") openWireframe(msg.message);
154
+ else { adoptDocumentSource(event, msg, trustedStudioFrame(event, msg)); presentMarkdownEdit(msg.message); }
155
+ }
162
156
  return;
163
157
  }
164
158
  // Both panes can report auth_required for their own sessions. The shell runs
@@ -168,6 +162,7 @@ function handlePaneMessage(event) {
168
162
  return;
169
163
  }
170
164
  if (handlePaneIssueMessage(event, host)) return;
165
+ if (handlePaneBrowserMessage(event, host)) return;
171
166
  if (handlePaneFileMessage(event, host, openFile, revealFilesPanel)) return;
172
167
  if (msg.type !== "clay-pane-context") return;
173
168
  var frames = host.querySelectorAll(".split-pane-frame");
@@ -184,7 +179,10 @@ function renderSplit(split) {
184
179
  var panes = split && split.panes;
185
180
  if (!panes || panes.length < 2 || panes.length > 3) {
186
181
  placeStickyNotesOverlay(false);
187
- host.innerHTML = "";
182
+ var frames = host.querySelectorAll('.split-pane-frame');
183
+ var retain = frames.length > 0 && frames.length <= 3 && Array.from(frames).every(function (frame) { return frame.dataset.projectSlug === store.get('currentSlug') && frame.clayPane; });
184
+ if (retain) Array.from(frames).forEach(function (frame) { frame.clayPane.suspend(); });
185
+ else host.innerHTML = "";
188
186
  host.classList.remove("visible");
189
187
  nativeApp.classList.remove("split-native-hidden");
190
188
  return;
@@ -224,6 +222,7 @@ function openSplit(side, draggedId) {
224
222
  }
225
223
 
226
224
  export function openGroup(group) {
225
+ if (!canLeavePanes()) return false;
227
226
  if (!group || !Array.isArray(group.members) || group.members.length < 2 || group.members.length > 3) return false;
228
227
  var memberIds = splitGroupMemberIds(group);
229
228
  if (memberIds.length !== group.members.length) return false;
@@ -272,47 +271,9 @@ export function openWorkerWithDriver(worker) {
272
271
  return true;
273
272
  }
274
273
 
275
- // Reload survival: when the restored active session turns out to be a split
276
- // group member, reopen that group. Safe to call often -- no-ops unless a
277
- // group member is active natively with no split open.
274
+ // Keep the public entry shared by connection, sidebar and identity hydration.
278
275
  export function maybeRestoreSplitGroup() {
279
- var state = store.snap();
280
- if (!isCurrentProjectSessionReady(state, getWs())) return;
281
- var split = state.splitPanes;
282
- if (split && !splitPanesMatchProject(split, state.currentSlug)) {
283
- store.set({ splitPanes: null });
284
- return;
285
- }
286
- if (state.paneMode) return;
287
- if (split) {
288
- var reconciliation = reconcileRestoredSplit(split, state.splitGroups);
289
- if (reconciliation.action === "clear") {
290
- store.set({ splitPanes: null });
291
- return;
292
- }
293
- if (reconciliation.action === "rebuild") {
294
- var rebuilt = reconciliation.group;
295
- if (rebuilt.members.some(function (id) { return !sessionById(id); })) {
296
- store.set({ splitPanes: null });
297
- return;
298
- }
299
- store.set({ splitPanes: {
300
- groupId: rebuilt.id,
301
- panes: splitGroupMemberIds(rebuilt).map(function (id) { return paneForSession(id); }),
302
- } });
303
- }
304
- return;
305
- }
306
- var activeId = store.get('activeSessionId');
307
- if (!activeId) return;
308
- var groups = store.get('splitGroups') || [];
309
- for (var i = 0; i < groups.length; i++) {
310
- var members = groups[i].members || [];
311
- if (members.indexOf(activeId) !== -1) {
312
- openGroup(groups[i]);
313
- return;
314
- }
315
- }
276
+ restoreSplitGroup(openGroup);
316
277
  }
317
278
 
318
279
  export function separateGroup(group) {
@@ -376,6 +337,24 @@ function handleSessionDragStart(event) {
376
337
  if (draggedSessionId) showDropOverlay();
377
338
  }
378
339
 
340
+ function openDriverGroup(driver) {
341
+ var state = store.snap();
342
+ if (!driver || driver.sessionRole !== "driver" || !isCurrentProjectSessionReady(state, getWs())) return false;
343
+ var groups = state.splitGroups || [];
344
+ for (var i = 0; i < groups.length; i++) {
345
+ var group = groups[i];
346
+ var roles = splitGroupRoles(group);
347
+ if (!roles || roles.driverId !== driver.id || typeof group.id !== "string" || !group.id) continue;
348
+ var available = roles.workerIds.every(function (id) {
349
+ var worker = sessionById(id);
350
+ return worker && worker.sessionRole === "worker" && worker.parentAvailable === true && worker.parentSessionId === driver.id;
351
+ });
352
+ // Keep mounted conversations when selecting their Driver again.
353
+ if (available) return openGroup(group);
354
+ }
355
+ return false;
356
+ }
357
+
379
358
  function handleSidebarSessionClick(event) {
380
359
  if (!store.get('splitPanes') || event.button !== 0) return;
381
360
  // This document capture listener runs before a row's bubble handlers. Leave
@@ -388,11 +367,22 @@ function handleSidebarSessionClick(event) {
388
367
  if (!sessionId) return;
389
368
  event.preventDefault();
390
369
  event.stopImmediatePropagation();
370
+ if (!canLeavePanes()) return;
391
371
  var session = sessionById(sessionId);
392
372
  if (session && session.sessionRole === "worker" && openWorkerWithDriver(session)) return;
373
+ if (openDriverGroup(session)) return;
393
374
  switchNativeSession(sessionId);
394
375
  }
395
376
 
377
+ function canLeavePanes() {
378
+ if (!host) return true;
379
+ try {
380
+ if (!store.get('splitPanes')) checkComposerDeparture();
381
+ Array.from(host.querySelectorAll('.split-pane-frame')).forEach(function (frame) { if (frame.clayPane) frame.clayPane.checkDraft(); });
382
+ return true;
383
+ } catch (error) { showToast(error.message, 'warn'); return false; }
384
+ }
385
+
396
386
  export function initSplitView() {
397
387
  if (store.get('paneMode')) return;
398
388
  var mainPanels = document.getElementById("main-panels");
@@ -418,6 +408,8 @@ export function initSplitView() {
418
408
  });
419
409
  document.addEventListener("click", handleSidebarSessionClick, true);
420
410
  store.subscribe(function (state, prev) {
411
+ if (state.authIdentityLoaded && !prev.authIdentityLoaded) queueMicrotask(maybeRestoreSplitGroup);
412
+ if (reconcileSplitIdentity(state, prev, host)) { renderSplit(null); return; }
421
413
  if (state.splitPanes !== prev.splitPanes) renderSplit(state.splitPanes);
422
414
  if (state.permissionModePendingByTarget !== prev.permissionModePendingByTarget || state.connected !== prev.connected ||
423
415
  state.skipPermsEnabled !== prev.skipPermsEnabled) syncPaneTitles();
@@ -6,7 +6,32 @@ export function getTitle(text) {
6
6
  return idx === -1 ? text : text.substring(0, idx);
7
7
  }
8
8
 
9
- function formatInline(text) {
9
+ function checklistFence(line) {
10
+ var match = line.match(/^\s*(\x60{3,}|~{3,})/);
11
+ return match ? match[1].charAt(0) : null;
12
+ }
13
+
14
+ export function getChecklistItems(text) {
15
+ var lines = (text || "").split("\n").slice(1);
16
+ var items = [];
17
+ var fence = null;
18
+ var occurrences = Object.create(null);
19
+ for (var i = 0; i < lines.length; i++) {
20
+ var line = lines[i];
21
+ var nextFence = checklistFence(line);
22
+ if (nextFence) {
23
+ fence = fence === nextFence ? null : (fence || nextFence);
24
+ continue;
25
+ }
26
+ if (fence || !line.trim() || /^\s*#{1,6}\s/.test(line)) continue;
27
+ var occurrence = occurrences[line] || 0;
28
+ occurrences[line] = occurrence + 1;
29
+ items.push({ index: i, text: line, key: line + "\u0000" + occurrence });
30
+ }
31
+ return items;
32
+ }
33
+
34
+ function formatInline(text, preserveChecks) {
10
35
  var escaped = text
11
36
  .replace(/&/g, "&amp;")
12
37
  .replace(/</g, "&lt;")
@@ -17,18 +42,59 @@ function formatInline(text) {
17
42
  .replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<em>$1</em>")
18
43
  .replace(/`([^`]+)`/g, "<code>$1</code>")
19
44
  .replace(/~~(.+?)~~/g, "<del>$1</del>")
20
- .replace(/^(?:-\s*)?\[[xX]\]/gm, '<span class="sn-check checked" role="checkbox" aria-checked="true" tabindex="0" contenteditable="false">✓</span>')
21
- .replace(/^(?:-\s*)?\[ \]/gm, '<span class="sn-check" role="checkbox" aria-checked="false" tabindex="0" contenteditable="false">☐</span>')
45
+ .replace(preserveChecks ? /(?!x)x^/ : /^(?:-\s*)?\[[xX]\]/gm, '<span class="sn-check checked" role="checkbox" aria-checked="true" tabindex="0" contenteditable="false">✓</span>')
46
+ .replace(preserveChecks ? /(?!x)x^/ : /^(?:-\s*)?\[ \]/gm, '<span class="sn-check" role="checkbox" aria-checked="false" tabindex="0" contenteditable="false">☐</span>')
22
47
  .replace(/\n/g, "<br>");
23
48
  }
24
49
 
25
- export function renderMiniMarkdown(text) {
50
+ export function renderMiniMarkdown(text, options) {
26
51
  if (!text) return "";
52
+ options = options || {};
27
53
  var lines = text.split("\n");
28
54
  var title = lines[0];
29
55
  var body = lines.slice(1).join("\n");
30
- var html = '<div class="sn-title">' + formatInline(title) + "</div>";
31
- if (body.trim()) html += formatInline(body);
56
+ var html = '<div class="sn-title">' + formatInline(title, options.checklistMode) + "</div>";
57
+ if (body.trim()) {
58
+ if (options.checklistMode) {
59
+ var checklistLines = body.split("\n");
60
+ var checklistHtml = [];
61
+ var inCode = false;
62
+ var fenceChar = null;
63
+ var occurrences = Object.create(null);
64
+ for (var i = 0; i < checklistLines.length; i++) {
65
+ var line = checklistLines[i];
66
+ var lineFence = checklistFence(line);
67
+ if (lineFence) {
68
+ fenceChar = fenceChar === lineFence ? null : (fenceChar || lineFence);
69
+ inCode = !!fenceChar;
70
+ checklistHtml.push(formatInline(line, true));
71
+ if (i < checklistLines.length - 1) checklistHtml.push("<br>");
72
+ continue;
73
+ }
74
+ var task = !inCode && line.trim() && !/^\s*#{1,6}\s/.test(line);
75
+ if (task) {
76
+ var markerMatch = line.match(/^\s*(?:[-*+]\s+)?\[([ xX])\]\s*(.*)$/);
77
+ var checked = markerMatch ? markerMatch[1].toLowerCase() === "x" : false;
78
+ var content = markerMatch ? markerMatch[2] : line;
79
+ var occurrence = occurrences[line] || 0;
80
+ occurrences[line] = occurrence + 1;
81
+ var checklistKey = line + "\u0000" + occurrence;
82
+ var stored = options.checklistState && options.checklistState[checklistKey];
83
+ if (stored === undefined && Array.isArray(options.checklistState)) stored = options.checklistState[i];
84
+ if (stored !== undefined) {
85
+ checked = stored === true;
86
+ }
87
+ checklistHtml.push('<span class="sn-check' + (checked ? ' checked' : '') + '" data-checklist-index="' + i + '" data-checklist-key="' + encodeURIComponent(checklistKey) + '" role="checkbox" aria-checked="' + (checked ? 'true' : 'false') + '" tabindex="0" contenteditable="false">' + (checked ? "✓" : "☐") + "</span>" + formatInline(content));
88
+ } else {
89
+ checklistHtml.push(formatInline(line, !!inCode));
90
+ }
91
+ if (i < checklistLines.length - 1) checklistHtml.push("<br>");
92
+ }
93
+ html += checklistHtml.join("");
94
+ } else {
95
+ html += formatInline(body);
96
+ }
97
+ }
32
98
  return html;
33
99
  }
34
100
 
@@ -0,0 +1,30 @@
1
+ import { getNoteUiState, clearNoteTextTimer, setNoteUiState } from './sticky-notes-shared.js';
2
+ import { checklistDraftText } from './sticky-notes-checklist.js';
3
+ import { mutateChecklist } from './sticky-notes-state.js';
4
+ import { confirmSettingsAction } from './server-settings-state.js';
5
+
6
+ export function requestChecklistMode(id) {
7
+ var ui = getNoteUiState(id);
8
+ if (ui.pending.length) return;
9
+ if (ui.checklistMode) { mutateChecklist(id, { checklistMode: false }); return; }
10
+ var text = ui.text;
11
+ var canonical = ui.canonical;
12
+ function convert() {
13
+ var current = getNoteUiState(id);
14
+ if (current.text !== text || current.canonical.text !== canonical.text || current.canonical.updatedAt !== canonical.updatedAt) {
15
+ setNoteUiState(id, { error: 'The note changed. Review its contents and try again.' }); return;
16
+ }
17
+ clearNoteTextTimer(id);
18
+ mutateChecklist(id, { checklistConvert: true, checklistSource: canonical.text, checklistVersion: canonical.updatedAt });
19
+ }
20
+ if (text.trim() || (canonical.text || '').trim()) {
21
+ confirmSettingsAction('Switching to a checklist will delete all existing contents and completion marks. Continue with an empty checklist?', 'Delete contents and create checklist', convert);
22
+ } else convert();
23
+ }
24
+
25
+ export function closeHumanNote(id, fallback) {
26
+ var ui = getNoteUiState(id, fallback);
27
+ if (ui.pending.length) { setNoteUiState(id, { error: 'Wait for the current save before closing.' }); return; }
28
+ clearNoteTextTimer(id);
29
+ mutateChecklist(id, { humanClose: true, expectedText: ui.canonical.text, expectedVersion: ui.canonical.updatedAt, draftText: ui.checklistMode ? checklistDraftText(ui) : ui.text });
30
+ }
@@ -11,7 +11,8 @@ import { store } from './store.js';
11
11
  import { iconHtml, refreshIcons } from './icons.js';
12
12
  import { renderMiniMarkdown, getTitle } from './sticky-note-markdown.js';
13
13
  import { enhanceClayLogLinks } from './clay-log-links.js';
14
- import { send } from './sticky-notes-shared.js';
14
+ import { closeHumanNote } from './sticky-notes-actions.js';
15
+ import { send, getNoteUiState } from './sticky-notes-shared.js';
15
16
  import { listNoteData, focusNoteOnCanvas, hideNotes, showNotes } from './sticky-notes.js';
16
17
  import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
17
18
 
@@ -215,7 +216,7 @@ function buildCard(data) {
215
216
  action.setAttribute("aria-label", "Close note: " + title.textContent);
216
217
  action.addEventListener("click", function (e) {
217
218
  e.stopPropagation();
218
- send({ type: "note_close", id: data.id });
219
+ closeHumanNote(data.id, data);
219
220
  });
220
221
  }
221
222
  header.appendChild(action);
@@ -229,6 +230,11 @@ function buildCard(data) {
229
230
  enhanceClayLogLinks(body);
230
231
  }
231
232
  card.appendChild(body);
233
+ var ui = getNoteUiState(data.id, data);
234
+ if (ui.error || ui.pending.length) {
235
+ var status = document.createElement('p'); status.className = 'settings-status'; status.setAttribute('role', 'status');
236
+ status.textContent = ui.error || 'Saving…'; card.appendChild(status);
237
+ }
232
238
 
233
239
  if (closed) {
234
240
  var deleteAction = document.createElement("button");
@@ -427,6 +433,7 @@ export function initNotesBrowser() {
427
433
  closeNotesBrowser();
428
434
  });
429
435
  store.subscribe(function (state, previous) {
436
+ if (state.notesBrowserOpen && state.stickyNoteUiState !== previous.stickyNoteUiState) renderNotesBrowser();
430
437
  if (state.connected !== previous.connected || state.myUserId !== previous.myUserId ||
431
438
  state.isMultiUserMode !== previous.isMultiUserMode) closeDeleteDialog(true);
432
439
  if (state.currentSlug === previous.currentSlug) return;
@@ -17,6 +17,7 @@ import {
17
17
  clampSize,
18
18
  debouncedUpdate,
19
19
  } from './sticky-notes-shared.js';
20
+ import { closeHumanNote } from './sticky-notes-actions.js';
20
21
  import { setupTextEdit } from './sticky-notes-editor.js';
21
22
 
22
23
  var colorPickerEl = null;
@@ -74,7 +75,7 @@ export function renderNote(data) {
74
75
  addBtn.innerHTML = iconHtml("plus");
75
76
  addBtn.addEventListener("click", function (e) {
76
77
  e.stopPropagation();
77
- createNote();
78
+ send({ type: "note_create", x: 60, y: 60, color: "purple", opacity: 0.64 });
78
79
  });
79
80
  header.appendChild(addBtn);
80
81
 
@@ -90,6 +91,21 @@ export function renderNote(data) {
90
91
  mdBtn.innerHTML = "<span class='sn-md-label'>MD</span>";
91
92
  header.appendChild(mdBtn);
92
93
 
94
+ var checklistBtn = document.createElement("button");
95
+ checklistBtn.className = "sticky-note-btn sticky-note-checklist-btn";
96
+ checklistBtn.title = data.checklistMode ? "Show note" : "Show checklist";
97
+ checklistBtn.setAttribute("aria-label", checklistBtn.title);
98
+ checklistBtn.setAttribute("aria-pressed", data.checklistMode === true ? "true" : "false");
99
+ checklistBtn.innerHTML = iconHtml("list-check");
100
+ if (data.checklistMode) checklistBtn.classList.add("active");
101
+ header.appendChild(checklistBtn);
102
+
103
+ var saveStatus = document.createElement("span");
104
+ saveStatus.className = "sticky-note-save-status";
105
+ saveStatus.setAttribute("role", "status");
106
+ saveStatus.setAttribute("aria-live", "polite");
107
+ header.appendChild(saveStatus);
108
+
93
109
  var opacityWrap = document.createElement("div");
94
110
  opacityWrap.className = "sticky-note-opacity";
95
111
  var opacitySlider = document.createElement("input");
@@ -139,11 +155,12 @@ export function renderNote(data) {
139
155
  rendered.contentEditable = "true";
140
156
  rendered.spellcheck = true;
141
157
  if (data.text && data.text.trim()) {
142
- rendered.innerHTML = renderMiniMarkdown(data.text);
158
+ rendered.innerHTML = renderMiniMarkdown(data.text, { checklistMode: data.checklistMode === true, checklistState: data.checklistState || [] });
143
159
  enhanceClayLogLinks(rendered);
144
160
  } else {
145
161
  rendered.classList.add("is-empty");
146
162
  }
163
+ rendered.contentEditable = data.checklistMode === true ? "false" : "true";
147
164
  body.appendChild(rendered);
148
165
 
149
166
  el.appendChild(body);
@@ -156,7 +173,7 @@ export function renderNote(data) {
156
173
  // --- Event handlers ---
157
174
  setupDrag(el, spacer, data.id);
158
175
  setupResize(el, resizeHandle, data.id);
159
- setupTextEdit(textarea, rendered, data.id, mdBtn);
176
+ setupTextEdit(textarea, rendered, data.id, mdBtn, checklistBtn, data);
160
177
  setupColorPicker(colorBtn, el, data.id);
161
178
  setupMinimize(minBtn, el, data.id);
162
179
  setupClose(closeBtn, el, data.id);
@@ -336,14 +353,13 @@ function setupMinimize(btn, noteEl, noteId) {
336
353
 
337
354
  // --- Close note ---
338
355
  //
339
- // Completing a note closes it. The record is kept and stays reachable in the
340
- // browser's Closed tab; nothing is ever deleted from this control.
356
+ // The human close transaction retains nonempty notes in Closed and removes
357
+ // truly empty notes after checking the canonical source and visible draft.
341
358
 
342
359
  function setupClose(btn, noteEl, noteId) {
343
360
  btn.addEventListener("click", function (e) {
344
361
  e.stopPropagation();
345
- noteEl.classList.add("hidden");
346
- send({ type: "note_close", id: noteId });
362
+ closeHumanNote(noteId);
347
363
  });
348
364
  }
349
365
 
@@ -0,0 +1,116 @@
1
+ // Plain task controls use Markdown only as the internal persistence format.
2
+ import { iconHtml, refreshIcons } from './icons.js';
3
+ import { getChecklistItems } from './sticky-note-markdown.js';
4
+ import { getNoteUiState, setNoteUiState } from './sticky-notes-shared.js';
5
+ import { mutateChecklist } from './sticky-notes-state.js';
6
+
7
+ export function checklistDraftText(ui) {
8
+ var fields = ui.checklistInputs || {};
9
+ var lines = (ui.text || '').split('\n');
10
+ if (fields.title !== undefined) lines[0] = fields.title;
11
+ getChecklistItems(ui.text).forEach(function (item) {
12
+ if (fields[item.key] !== undefined) {
13
+ var marker = item.text.match(/^\s*(?:[-*+]\s+)?\[([ xX])\]/);
14
+ var checked = ui.checklistState[item.key];
15
+ if (checked === undefined) checked = marker && marker[1].toLowerCase() === 'x';
16
+ lines[item.index + 1] = '- [' + (checked ? 'x' : ' ') + '] ' + fields[item.key];
17
+ }
18
+ });
19
+ if (fields.entry && fields.entry.trim()) {
20
+ if (!lines[0].trim()) lines[0] = 'Checklist';
21
+ lines.push('- [ ] ' + fields.entry.trim());
22
+ }
23
+ return lines.join('\n');
24
+ }
25
+
26
+ export function renderTaskControls(root, id) {
27
+ var ui = getNoteUiState(id);
28
+ var fields = ui.checklistInputs || {};
29
+ var busy = ui.pending.length > 0;
30
+ var active = document.activeElement;
31
+ var focusField = active && root.contains(active) ? active.dataset.taskField : undefined;
32
+ var selection = focusField !== undefined ? [active.selectionStart, active.selectionEnd] : null;
33
+ root.replaceChildren();
34
+ var form = document.createElement('form'); form.className = 'sn-task-form';
35
+ form.setAttribute('aria-label', 'Checklist');
36
+ form.setAttribute('aria-busy', busy ? 'true' : 'false');
37
+ var feedback = document.createElement('span'); feedback.className = 'sn-task-feedback';
38
+ feedback.setAttribute('role', 'status');
39
+ var saveButton = document.createElement('button');
40
+ function updateFeedback() {
41
+ var current = getNoteUiState(id);
42
+ var dirty = checklistDraftText(current) !== current.text;
43
+ feedback.textContent = busy ? 'Saving…' : current.error ? (dirty ? 'Draft kept. ' : 'Not saved. ') + current.error : dirty ? 'Unsaved changes' : 'All changes saved';
44
+ saveButton.disabled = busy || !dirty;
45
+ }
46
+ function input(label, value, key) {
47
+ var control = document.createElement('textarea'); control.rows = 1; control.value = fields[key] !== undefined ? fields[key] : value;
48
+ control.setAttribute('aria-label', label); control.placeholder = label; control.maxLength = 400;
49
+ control.readOnly = busy;
50
+ control.dataset.taskField = key;
51
+ control.onkeydown = function (event) {
52
+ if (event.key === 'Enter' && !event.isComposing) { event.preventDefault(); form.requestSubmit(); }
53
+ };
54
+ control.oninput = function () {
55
+ var current = getNoteUiState(id);
56
+ // A task remains one persisted line; visual wrapping does not split tasks.
57
+ control.value = control.value.replace(/[\r\n]+/g, ' ');
58
+ var draft = Object.assign({}, current.checklistInputs || {}); draft[key] = control.value;
59
+ setNoteUiState(id, { checklistInputs: draft });
60
+ updateFeedback();
61
+ };
62
+ return control;
63
+ }
64
+ var title = input('Checklist title', (ui.text || '').split('\n')[0], 'title'); title.className = 'sn-task-title'; form.appendChild(title);
65
+ var items = getChecklistItems(ui.text);
66
+ var completed = 0;
67
+ var summary = document.createElement('div'); summary.className = 'sn-task-summary';
68
+ form.appendChild(summary);
69
+ items.forEach(function (item, position) {
70
+ var row = document.createElement('div'); row.className = 'sn-task-row';
71
+ var marker = item.text.match(/^\s*(?:[-*+]\s+)?\[([ xX])\]\s*(.*)$/);
72
+ var check = document.createElement('button'); check.type = 'button'; check.className = 'sn-check';
73
+ var checked = ui.checklistState[item.key];
74
+ if (checked === undefined) checked = marker && marker[1].toLowerCase() === 'x';
75
+ check.classList.toggle('checked', !!checked);
76
+ check.innerHTML = '<span class="sn-task-box" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><path d="m3.5 8 3 3 6-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>';
77
+ row.classList.toggle('is-complete', !!checked);
78
+ if (checked) completed++;
79
+ check.setAttribute('role', 'checkbox'); check.setAttribute('aria-checked', checked ? 'true' : 'false'); check.setAttribute('aria-label', 'Complete task ' + (position + 1));
80
+ check.dataset.checklistIndex = item.index; check.dataset.checklistKey = encodeURIComponent(item.key);
81
+ check.disabled = busy;
82
+ var label = input('Task ' + (position + 1), marker ? marker[2] : item.text, item.key);
83
+ var remove = document.createElement('button'); remove.type = 'button'; remove.className = 'sn-task-remove'; remove.innerHTML = iconHtml('x'); remove.setAttribute('aria-label', 'Remove task ' + (position + 1)); remove.disabled = busy;
84
+ remove.onclick = function () {
85
+ var current = getNoteUiState(id); var lines = checklistDraftText(current).split('\n'); lines.splice(item.index + 1, 1);
86
+ save(lines.join('\n'));
87
+ };
88
+ row.append(check, label, remove); form.appendChild(row);
89
+ });
90
+ summary.textContent = items.length ? completed + ' of ' + items.length + ' complete' : 'A little space for what’s next';
91
+ var addRow = document.createElement('div'); addRow.className = 'sn-task-add';
92
+ var plus = document.createElement('span'); plus.className = 'sn-task-plus'; plus.innerHTML = iconHtml('plus'); plus.setAttribute('aria-hidden', 'true');
93
+ var entry = input('New task', '', 'entry'); entry.className = 'sn-task-entry'; entry.placeholder = 'Add a task…';
94
+ addRow.append(plus, entry); form.appendChild(addRow);
95
+ var footer = document.createElement('div'); footer.className = 'sn-task-footer';
96
+ saveButton.type = 'submit'; saveButton.className = 'sn-task-save'; saveButton.textContent = 'Save tasks';
97
+ footer.append(feedback, saveButton); form.appendChild(footer);
98
+ updateFeedback();
99
+ function save(text) {
100
+ var current = getNoteUiState(id);
101
+ if (current.pending.length) return;
102
+ mutateChecklist(id, { checklistEdit: true, checklistSource: current.canonical.text, checklistVersion: current.canonical.updatedAt, text: text });
103
+ }
104
+ form.onsubmit = function (event) { event.preventDefault(); save(checklistDraftText(getNoteUiState(id))); };
105
+ root.appendChild(form); refreshIcons(root);
106
+ if (focusField !== undefined) {
107
+ var controls = form.querySelectorAll('[data-task-field]');
108
+ for (var i = 0; i < controls.length; i++) {
109
+ if (controls[i].dataset.taskField === focusField) {
110
+ controls[i].focus({ preventScroll: true });
111
+ controls[i].setSelectionRange(selection[0], selection[1]);
112
+ break;
113
+ }
114
+ }
115
+ }
116
+ }