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
@@ -0,0 +1,120 @@
1
+ import { store } from './store.js';
2
+
3
+ function describe(value) {
4
+ if (!value || value === 'Earlier session') return 'Unknown device';
5
+ var browser = /Edg(?:e|A|iOS)?\//.test(value) ? 'Edge' : /Firefox\/|FxiOS\//.test(value) ? 'Firefox' : /Chrome\/|CriOS\//.test(value) ? 'Chrome' : /Safari\//.test(value) ? 'Safari' : 'Browser';
6
+ var system = /Android/.test(value) ? 'Android' : /iPhone|iPad/.test(value) ? 'iOS' : /Windows/.test(value) ? 'Windows' : /Macintosh/.test(value) ? 'macOS' : /Linux/.test(value) ? 'Linux' : '';
7
+ return browser + (system ? ' on ' + system : '');
8
+ }
9
+ function state() { return store.get('accountSessionsPanel') || { epoch: 0, open: false, entries: [] }; }
10
+ function update(values) { store.set({ accountSessionsPanel: Object.assign({}, state(), values) }); render(); }
11
+ function render() {
12
+ var panel = document.getElementById('us-sessions-panel'); if (!panel) return;
13
+ var scroll = []; var ancestor = panel.parentElement;
14
+ while (ancestor) { scroll.push({ element: ancestor, top: ancestor.scrollTop }); ancestor = ancestor.parentElement; }
15
+ var current = state(); var toggle = document.getElementById('us-sessions-toggle');
16
+ panel.hidden = !current.open; toggle.setAttribute('aria-expanded', String(!!current.open));
17
+ toggle.textContent = current.open ? 'Hide sessions' : 'Manage sessions'; toggle.disabled = !!current.saving;
18
+ var list = panel.querySelector('[data-list]'); list.replaceChildren();
19
+ var previousGroup = panel.querySelector('[data-earlier]'); if (previousGroup) previousGroup.remove();
20
+ var unknown = current.entries.filter(function (entry) { return entry.unknownDevice && !entry.current; });
21
+ var older = document.createElement('details'); older.dataset.earlier = ''; var summary = document.createElement('summary');
22
+ summary.className = 'settings-label'; summary.textContent = 'Earlier sessions without device details (' + unknown.length + ')'; older.append(summary);
23
+ var explanation = document.createElement('p'); explanation.className = 'settings-hint';
24
+ explanation.textContent = 'These sessions predate device tracking. Their browser and previous activity are unknown; matching labels do not mean they are the same device.';
25
+ older.append(explanation); older.open = !!current.showEarlier;
26
+ older.ontoggle = function () { if (older.isConnected) store.set({ accountSessionsPanel: Object.assign({}, state(), { showEarlier: older.open }) }); };
27
+ var olderList = document.createElement('div'); olderList.setAttribute('role', 'list'); older.append(olderList);
28
+ current.entries.forEach(function (entry) {
29
+ var row = document.createElement('div'); row.className = 'settings-field-row'; row.setAttribute('role', 'listitem');
30
+ var detail = document.createElement('div'); var title = document.createElement('span'); title.className = 'settings-label';
31
+ title.textContent = describe(entry.userAgent) + (entry.current ? ' · This session' : '');
32
+ var hint = document.createElement('p'); hint.className = 'settings-hint';
33
+ hint.textContent = entry.method + (entry.lastSeenAt ? ' · Last active ' + new Date(entry.lastSeenAt).toLocaleString() : ' · Previous activity unknown') +
34
+ (entry.address ? ' · Last observed IP ' + entry.address : '') +
35
+ (entry.expiresAt ? ' · Expires ' + new Date(entry.expiresAt).toLocaleDateString() : ' · Compatibility session');
36
+ detail.append(title, hint);
37
+ var button = document.createElement('button'); button.type = 'button'; button.className = 'settings-btn-sm'; button.textContent = 'Sign out';
38
+ button.dataset.sessionId = entry.id; button.setAttribute('aria-label', 'Sign out ' + describe(entry.userAgent) + (entry.current ? ' current session' : ''));
39
+ button.disabled = !!current.pending;
40
+ button.onclick = function () { choose(entry.id); };
41
+ if (current.target === entry.id) {
42
+ var confirmation = document.createElement('div'); confirmation.className = 'us-session-row-confirm';
43
+ confirmation.setAttribute('role', 'group'); confirmation.setAttribute('aria-label', 'Confirm session sign-out');
44
+ var question = document.createElement('p'); question.className = 'settings-hint';
45
+ question.textContent = entry.current ? 'Sign out this browser? You will need to sign in again.' : 'Sign out this session?';
46
+ var actions = document.createElement('div'); actions.className = 'settings-form-actions';
47
+ var confirm = document.createElement('button'); confirm.type = 'button'; confirm.className = 'settings-btn-sm settings-btn-danger';
48
+ confirm.dataset.rowConfirm = ''; confirm.textContent = current.saving ? 'Signing out…' : 'Sign out'; confirm.disabled = !!current.pending;
49
+ confirm.onclick = function () { request(entry.id); };
50
+ var cancel = document.createElement('button'); cancel.type = 'button'; cancel.className = 'settings-btn-sm';
51
+ cancel.dataset.rowCancel = ''; cancel.textContent = 'Cancel'; cancel.disabled = !!current.pending;
52
+ cancel.onclick = function () { update({ target: null, error: '' }); restoreFocus(entry.id); };
53
+ actions.append(confirm, cancel); confirmation.append(question, actions);
54
+ if (current.error) { var error = document.createElement('p'); error.className = 'settings-status'; error.setAttribute('role', 'alert'); error.textContent = current.error; confirmation.append(error); }
55
+ row.append(detail, confirmation);
56
+ } else row.append(detail, button);
57
+ (entry.unknownDevice && !entry.current ? olderList : list).append(row);
58
+ });
59
+ if (unknown.length) list.after(older);
60
+ panel.querySelector('[data-status]').textContent = current.target && current.target !== 'others' ? '' : current.error || (current.pending ? current.saving ? 'Signing out…' : 'Loading sessions…' : current.message || '');
61
+ panel.querySelector('[data-retry]').hidden = !current.error || !!current.target;
62
+ panel.querySelector('[data-others]').disabled = !!current.pending || !current.entries.some(function (entry) { return !entry.current; });
63
+ panel.querySelector('[data-confirmation]').hidden = current.target !== 'others';
64
+ var selected = current.entries.find(function (entry) { return entry.id === current.target; });
65
+ panel.querySelector('[data-question]').textContent = selected && selected.current ? 'Sign out this browser? Your settings will close and you will need to sign in again.' : 'Sign out the selected sessions? Their open connections will close.';
66
+ panel.querySelector('[data-confirm]').disabled = !!current.pending;
67
+ panel.querySelector('[data-cancel]').disabled = !!current.pending;
68
+ scroll.forEach(function (position) { position.element.scrollTop = position.top; });
69
+ }
70
+ function choose(id) {
71
+ update({ target: id, error: '', message: '' });
72
+ document.querySelector(id === 'others' ? '#us-sessions-panel [data-confirm]' : '#us-sessions-panel [data-row-confirm]').focus({ preventScroll: true });
73
+ }
74
+ function restoreFocus(id) {
75
+ var panel = document.getElementById('us-sessions-panel');
76
+ var button = Array.from(panel.querySelectorAll('[data-session-id]')).find(function (item) { return item.dataset.sessionId === id; });
77
+ (button || (id === 'others' ? panel.querySelector('[data-others]') : document.getElementById('us-sessions-toggle'))).focus({ preventScroll: true });
78
+ }
79
+ async function request(id) {
80
+ var entries = state().entries; var index = entries.findIndex(function (entry) { return entry.id === id; });
81
+ var neighbor = entries[index + 1] || entries[index - 1];
82
+ var epoch = state().epoch + 1;
83
+ update({ epoch: epoch, pending: true, saving: !!id, error: '', message: '' });
84
+ try {
85
+ var response = await fetch('/api/account-sessions', id ? { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) } : {});
86
+ var data = await response.json();
87
+ if (epoch !== state().epoch) return;
88
+ if (!response.ok) {
89
+ if (response.status === 401 || response.status === 403) update({ entries: [], target: null });
90
+ throw new Error(data.error || 'Could not manage sessions.');
91
+ }
92
+ if (data.signedOut) { window.location.href = '/'; return; }
93
+ update({ entries: data.sessions, target: null, pending: false, saving: false, message: id ? 'Selected sessions signed out.' : '' });
94
+ if (id) restoreFocus(id === 'others' ? id : neighbor && neighbor.id);
95
+ } catch (error) {
96
+ if (epoch === state().epoch) update({ pending: false, saving: false, error: error.message });
97
+ var retry = document.querySelector('#us-sessions-panel [data-row-confirm]');
98
+ if (epoch === state().epoch && id && retry) retry.focus({ preventScroll: true });
99
+ }
100
+ }
101
+ export function resetAccountSessions() {
102
+ update({ epoch: state().epoch + 1, open: false, entries: [], target: null, pending: false, saving: false, error: '', message: '', showEarlier: false });
103
+ }
104
+ export function initAccountSessions() {
105
+ var toggle = document.getElementById('us-sessions-toggle'); if (!toggle || document.getElementById('us-sessions-panel')) return;
106
+ var panel = document.createElement('div'); panel.id = 'us-sessions-panel'; panel.hidden = true;
107
+ panel.innerHTML = '<p class="settings-hint">Each entry represents a browser session. Account sessions expire after 30 days, or after 7 days without use.</p>' +
108
+ '<div data-list role="list" aria-label="Signed-in sessions"></div><div class="settings-form-actions"><button type="button" class="settings-btn-sm" data-others>Sign out other sessions</button></div>' +
109
+ '<div data-confirmation role="group" aria-label="Confirm sign-out" hidden><p class="settings-hint" data-question></p><div class="settings-form-actions"><button type="button" class="settings-btn-sm settings-btn-danger" data-confirm>Sign out</button><button type="button" class="settings-btn-sm" data-cancel>Cancel</button></div></div>' +
110
+ '<p class="settings-status" role="status" data-status></p><button type="button" class="settings-btn-sm" data-retry hidden>Retry</button>';
111
+ toggle.closest('.settings-field-row').after(panel);
112
+ toggle.onclick = function () {
113
+ if (state().open) { resetAccountSessions(); toggle.focus(); }
114
+ else { update({ open: true }); request(); }
115
+ };
116
+ panel.querySelector('[data-others]').onclick = function () { choose('others'); };
117
+ panel.querySelector('[data-retry]').onclick = function () { request(); };
118
+ panel.querySelector('[data-confirm]').onclick = function () { request(state().target); };
119
+ panel.querySelector('[data-cancel]').onclick = function () { var id = state().target; update({ target: null, error: '' }); restoreFocus(id); };
120
+ }
@@ -1,4 +1,5 @@
1
1
  import { initPersonalAppearance } from './user-settings-appearance.js';
2
+ import { initAccountSessions, resetAccountSessions } from './user-settings-sessions.js';
2
3
  import { initPersonalVoice } from './user-settings-voice.js';
3
4
  import { isolateSettingsDialog } from './server-settings-state.js';
4
5
  import { initPersonalProfile } from './user-settings-profile.js';
@@ -29,6 +30,7 @@ var pinCancelBtn = null;
29
30
 
30
31
  export function initUserSettings() {
31
32
  buildUserSettingsLayout();
33
+ initAccountSessions();
32
34
  settingsEl = document.getElementById('user-settings');
33
35
  openBtn = document.getElementById('user-settings-btn');
34
36
  closeBtn = document.getElementById('user-settings-close');
@@ -73,7 +75,7 @@ export function initUserSettings() {
73
75
  for (var i = 0; i < navItems.length; i++) {
74
76
  navItems[i].addEventListener('click', function () {
75
77
  var section = this.dataset.section;
76
- guardUserSettingsLeave(function () { switchSection(section); });
78
+ guardUserSettingsLeave(function () { switchSection(section); }, section);
77
79
  });
78
80
  }
79
81
 
@@ -81,7 +83,8 @@ export function initUserSettings() {
81
83
  var navDropdown = document.getElementById('user-settings-nav-dropdown');
82
84
  if (navDropdown) {
83
85
  navDropdown.addEventListener('change', function () {
84
- var value = this.value; guardUserSettingsLeave(function () {switchSection(value);});
86
+ var value = this.value; guardUserSettingsLeave(function () {switchSection(value);}, value);
87
+ this.value = settingsEl.querySelector('.us-section.active').dataset.section;
85
88
  });
86
89
  }
87
90
 
@@ -204,6 +207,7 @@ export function openUserSettings(initialSection) {
204
207
 
205
208
  export function closeUserSettings() {
206
209
  guardUserSettingsLeave(function () {
210
+ resetAccountSessions();
207
211
  finishUserSettingsExtras();
208
212
  settingsEl.classList.add('hidden');
209
213
  var restore=store.get('userSettingsRestore');if(restore)restore();store.set({userSettingsRestore:null});
@@ -1,3 +1,4 @@
1
+ import { escapeHtml } from './utils.js';
1
2
  import { store } from './store.js';
2
3
  import { getWs } from './ws-ref.js';
3
4
  import { iconHtml, refreshIcons } from './icons.js';
@@ -33,7 +34,8 @@ export function openLoginBrowser(msg) {
33
34
  }
34
35
  closeLoginBrowser();
35
36
  var isMcp = msg.kind === 'mcp';
36
- var title = isMcp ? 'Sign in to ' + (msg.label || 'MCP server') : (msg.vendor === "codex" ? "Sign in to Codex" : "Sign in to Claude");
37
+ var provider = (store.get('vendorInfo') || {})[msg.vendor] || {};
38
+ var title = 'Sign in to ' + (isMcp ? msg.label || 'MCP server' : provider.displayName || msg.vendor || 'Provider');
37
39
  store.set({ vendorLoginBrowser: {
38
40
  browserId: msg.browserId, vendor: msg.vendor, kind: msg.kind, connectionId: msg.connectionId, slug: msg.slug || store.get('currentSlug'),
39
41
  previousFocus: document.activeElement, decoding: false, pointerY: null, pointerId: null, mouseDown: false, moveTimer: null, pendingMove: null, resizeObserver: null, requestedSize: null, phase: "loading",
@@ -43,7 +45,7 @@ export function openLoginBrowser(msg) {
43
45
  dialog.className = "login-browser";
44
46
  dialog.setAttribute("aria-labelledby", "login-browser-title");
45
47
  dialog.innerHTML = '<header class="login-browser-header">' +
46
- '<img class="login-browser-vendor" src="/' + (msg.vendor === "codex" ? 'codex-avatar.png' : 'claude-code-avatar.png') + '" alt="">' +
48
+ '<img class="login-browser-vendor" src="' + escapeHtml(provider.avatar || '') + '" alt="">' +
47
49
  '<div class="login-browser-heading"><h2 id="login-browser-title"></h2>' +
48
50
  '<span class="login-browser-origin">Opening sign-in page…</span></div>' +
49
51
  '<div class="login-browser-actions">' +
@@ -56,7 +58,7 @@ export function openLoginBrowser(msg) {
56
58
  '<div class="login-browser-loading"><span class="login-browser-spinner" aria-hidden="true"></span><strong>Opening your sign-in page</strong><span>This may take a moment.</span></div>' +
57
59
  '<textarea class="login-browser-keyboard" aria-label="Type into the remote sign-in page" autocomplete="off" autocapitalize="off" spellcheck="false"></textarea></div>' +
58
60
  '<footer class="login-browser-footer"><div class="login-browser-info"><div class="login-browser-status"><span class="login-browser-status-dot" aria-hidden="true"></span><p role="status">Preparing sign-in…</p></div>' +
59
- '<p class="login-browser-privacy">Browser cookies are discarded when this session ends. You stay signed in to ' + (msg.vendor === "codex" ? 'Codex' : 'Claude') + ' after this browser closes.</p></div>' +
61
+ '<p class="login-browser-privacy">Browser cookies are discarded when this session ends. You stay signed in to ' + escapeHtml(provider.displayName || msg.vendor || 'the provider') + ' after this browser closes.</p></div>' +
60
62
  '<button type="button" data-action="terminal" class="login-browser-terminal">' + iconHtml("terminal") + '<span>Use terminal sign-in</span>' + iconHtml("arrow-up-right") + '</button></footer>';
61
63
  dialog.querySelector("h2").textContent = title;
62
64
  document.body.appendChild(dialog);
@@ -31,7 +31,7 @@ function vendorDisplayName(vendor) {
31
31
  var vendors = store.get('vendorInfo') || {};
32
32
  var info = vendors[vendor];
33
33
  if (info && info.displayName) return info.displayName;
34
- return vendor === "codex" ? "Codex" : "Claude Code";
34
+ return vendor || "Provider";
35
35
  }
36
36
 
37
37
  function currentProjectSlug() {
@@ -170,7 +170,7 @@ export function requestVendorLogin(vendor, opts) {
170
170
  vendor: target,
171
171
  auto: !!options.auto,
172
172
  sessionId: options.sessionId || store.get('activeSessionId') || null,
173
- mode: options.mode || ((target === "claude" || target === "codex") ? "browser" : "terminal"),
173
+ mode: options.mode || ((((store.get("vendorInfo") || {})[target] || {}).browserLoginSupported === true) ? "browser" : "terminal"),
174
174
  }));
175
175
  showLoginStartedBanner(target);
176
176
  return true;
@@ -1,4 +1,18 @@
1
- export var VENDOR_ORDER = ["claude", "codex", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
1
+ export var VENDOR_ORDER = ["claude", "codex", "muse", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
2
+
3
+ // Availability comes from the caller's server catalog. Unknown providers keep
4
+ // their catalog order within each availability group.
5
+ export function sortVendorEntries(entries) {
6
+ return entries.map(function (entry, index) { return { entry: entry, index: index }; }).sort(function (a, b) {
7
+ var installed = Number(!!b.entry.installed) - Number(!!a.entry.installed);
8
+ if (installed) return installed;
9
+ var aRank = VENDOR_ORDER.indexOf(a.entry.id);
10
+ var bRank = VENDOR_ORDER.indexOf(b.entry.id);
11
+ if (aRank === -1) aRank = VENDOR_ORDER.length;
12
+ if (bRank === -1) bRank = VENDOR_ORDER.length;
13
+ return aRank - bRank || a.index - b.index;
14
+ }).map(function (item) { return item.entry; });
15
+ }
2
16
  export var EXPERIMENTAL_VENDORS = ["grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode"];
3
17
 
4
18
  export function isExperimentalVendor(vendor) {
@@ -1,3 +1,4 @@
1
+ import { forwardStudioPresentation, registerStudioPaint } from './clay-studio-render.js';
1
2
  import { sketchBrand, sketchCredit } from './wireframe-style.js';
2
3
  import { store } from './store.js';
3
4
  import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
@@ -80,7 +81,7 @@ function createPanel() {
80
81
  export function openWireframe(message) {
81
82
  if (!message || typeof message.source !== 'string' || new TextEncoder().encode(message.source).length > 100000) return;
82
83
  if (store.get('paneMode') && window.parent !== window) {
83
- window.parent.postMessage({ type: 'clay-pane-present-wireframe', message: message, projectSlug: store.get('currentSlug'), sessionId: store.get('activeSessionId') }, window.location.origin);
84
+ forwardStudioPresentation(message, 'clay-pane-present-wireframe');
84
85
  return;
85
86
  }
86
87
  claimRightWorkbench('wireframe');
@@ -92,7 +93,8 @@ export function openWireframe(message) {
92
93
  el.querySelector('header strong').textContent = draft.title;
93
94
  el.querySelector('.wireframe-save-status').textContent = '';
94
95
  el.querySelector('form').hidden = true;
95
- draw(draft, el).catch(function () {});
96
+ var painted = draw(draft, el); registerStudioPaint(Object.assign({}, message, { source: draft.source }), el.querySelector("header"), painted, el.querySelector(".wireframe-workbench-canvas"));
97
+ painted.catch(function () {});
96
98
  }
97
99
  function draw(draft, el) {
98
100
  var canvas = el.querySelector('.wireframe-workbench-canvas');
@@ -104,6 +106,7 @@ function draw(draft, el) {
104
106
  var image = wireframeImage(svg, draft.title);
105
107
  canvas.replaceChildren(image);
106
108
  mountWireframeViewport(canvas, image, el.querySelector('.wireframe-zoom'));
109
+ return image.decode ? image.decode() : undefined;
107
110
  }).catch(function (error) {
108
111
  if (store.get('wireframeDraft') !== active) throw error;
109
112
  status.textContent = error.name === 'AbortError' ? 'Rendering was interrupted. Reopen the wireframe to retry.' : error.message;
@@ -7,6 +7,7 @@ function state() { return store.get('youActivity') || {}; }
7
7
  function put(values) { store.set({ youActivity: Object.assign({}, state(), values) }); }
8
8
  function el(id) { return document.getElementById(id); }
9
9
  function describe(item) {
10
+ if (item.action === 'delete') return 'You deleted a memory from Me.';
10
11
  if (item.action === 'archive') return 'Clay stopped using a memory about you.';
11
12
  return (item.action === 'update' ? 'Clay updated: ' : 'Clay remembered: ') + (item.summary || item.title);
12
13
  }
@@ -67,7 +68,7 @@ function render() {
67
68
  var text = document.createElement('span'); text.textContent = describe(item);
68
69
  var time = document.createElement('small'); time.textContent = relativeTime(item.at);
69
70
  button.append(text, time);
70
- button.addEventListener('click', function () { close(); openYou(item.action === 'archive' ? null : item.ref); });
71
+ button.addEventListener('click', function () { close(); openYou(item.action === 'archive' || item.action === 'delete' ? null : item.ref); });
71
72
  list.appendChild(button);
72
73
  });
73
74
  el('you-activity-more').classList.toggle('hidden', state().nextOffset == null);
@@ -76,6 +77,7 @@ export function handleYouActivity(msg) {
76
77
  if (!el('you-activity') || (msg.activity && msg.activity.seen)) return;
77
78
  if (msg.type === 'you_reviewed') { put({ error: '' }); render(); return; }
78
79
  if (msg.type === 'you_changed') {
80
+ if (msg.activity && msg.activity.deleted) { request(); return; }
79
81
  if (msg.activity && msg.activity.error) { put({ error: msg.activity.error }); announce(msg.activity.error); return; }
80
82
  put({ error: '' });
81
83
  if (msg.activity && msg.activity.id && (state().seen || []).indexOf(msg.activity.id) === -1) {
@@ -5,6 +5,8 @@ import { refreshIcons } from './icons.js';
5
5
  import { renderList, renderDetail, categoryLabel } from './project-logs-render.js';
6
6
  import { registerRightWorkbench, claimRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
7
7
 
8
+ var deleteDialog = null;
9
+ var deleteDialogFocus = null;
8
10
  function state() { return store.get('you') || {}; }
9
11
  function put(values) { store.set({ you: Object.assign({}, state(), values) }); }
10
12
  function element(id) { return document.getElementById(id); }
@@ -70,6 +72,37 @@ function requestEntry(ref) {
70
72
  put({ readId: sendYou('you_read', { ref: ref }), selected: ref, scroll: element('you-list').scrollTop });
71
73
  status(state().readId ? 'Loading…' : 'Reconnect to read this memory.');
72
74
  }
75
+ function closeDeleteDialog(force) {
76
+ if (!deleteDialog) return;
77
+ if (!force && state().deleteId) return;
78
+ deleteDialog.classList.add('hidden');
79
+ put({ deleteId: null, deleteEntry: null });
80
+ if (deleteDialogFocus && deleteDialogFocus.isConnected) deleteDialogFocus.focus();
81
+ deleteDialogFocus = null;
82
+ }
83
+ function sendDelete() {
84
+ var entry = state().deleteEntry;
85
+ if (!entry || state().deleteId) return;
86
+ var requestId = sendYou('you_delete', { ref: entry.ref, expectedRevision: entry.revisions });
87
+ put({ deleteId: requestId });
88
+ var confirm = deleteDialog.querySelector('[data-action="delete"]');
89
+ var cancel = deleteDialog.querySelector('[data-action="cancel"]');
90
+ confirm.disabled = true; cancel.disabled = true;
91
+ deleteDialog.querySelector('.you-delete-dialog-status').textContent = requestId ? 'Deleting memory… Stored audit history remains.' : 'Reconnect to delete this memory.';
92
+ if (requestId) { deleteDialog.tabIndex = -1; deleteDialog.focus(); }
93
+ if (!requestId) { put({ deleteId: null }); confirm.disabled = false; cancel.disabled = false; }
94
+ }
95
+ function deleteEntry(entry) {
96
+ if (!entry || state().deleteId || !deleteDialog) return;
97
+ put({ deleteEntry: entry });
98
+ deleteDialogFocus = document.activeElement;
99
+ deleteDialog.querySelector('.you-delete-dialog-title').textContent = entry.title || 'Untitled memory';
100
+ deleteDialog.querySelector('.you-delete-dialog-status').textContent = '';
101
+ deleteDialog.querySelector('[data-action="delete"]').disabled = false;
102
+ deleteDialog.querySelector('[data-action="cancel"]').disabled = false;
103
+ deleteDialog.classList.remove('hidden');
104
+ deleteDialog.querySelector('[data-action="cancel"]').focus();
105
+ }
73
106
  function windowState(wide, fullscreen) {
74
107
  put({ wide: wide, fullscreen: fullscreen });
75
108
  element('you-panel').classList.toggle('project-logs-wide', wide && !fullscreen);
@@ -117,6 +150,25 @@ function ensurePanel() {
117
150
  '<div id="you-list" class="project-logs-list" role="list"></div><main id="you-detail" class="project-logs-detail hidden"></main>' +
118
151
  '<button id="you-more" type="button" class="you-more hidden">Load more</button>';
119
152
  document.getElementById('main-panels').appendChild(panel);
153
+ var dialog = document.createElement('div');
154
+ dialog.className = 'project-log-delete-dialog you-delete-dialog hidden';
155
+ dialog.setAttribute('role', 'dialog'); dialog.setAttribute('aria-modal', 'true'); dialog.setAttribute('aria-labelledby', 'you-delete-heading'); dialog.tabIndex = -1;
156
+ dialog.innerHTML = '<div class="project-log-delete-dialog-card"><h2 id="you-delete-heading">Delete this memory?</h2><p>This removes the memory from Me immediately. Clay’s audit history will retain that it was deleted.</p><p class="project-log-delete-dialog-title you-delete-dialog-title"></p><p class="project-log-delete-dialog-status you-delete-dialog-status" role="status"></p><div class="project-log-delete-dialog-actions"><button type="button" data-action="cancel">Cancel</button><button type="button" class="danger" data-action="delete">Delete memory</button></div></div>';
157
+ panel.appendChild(dialog); deleteDialog = dialog;
158
+ dialog.querySelector('[data-action="cancel"]').addEventListener('click', function () { closeDeleteDialog(false); });
159
+ dialog.querySelector('[data-action="delete"]').addEventListener('click', sendDelete);
160
+ dialog.addEventListener('keydown', function (event) {
161
+ event.stopPropagation();
162
+ if (event.key === 'Escape') { event.preventDefault(); closeDeleteDialog(false); return; }
163
+ if (event.key === 'Tab') {
164
+ var buttons = Array.from(dialog.querySelectorAll('button:not(:disabled)'));
165
+ if (!buttons.length) { event.preventDefault(); dialog.focus(); return; }
166
+ var first = buttons[0]; var last = buttons[buttons.length - 1];
167
+ if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }
168
+ else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }
169
+ }
170
+ });
171
+ dialog.addEventListener('click', function (event) { if (event.target === dialog) closeDeleteDialog(false); });
120
172
  element('you-close').addEventListener('click', closeYou);
121
173
  element('you-back').addEventListener('click', showList);
122
174
  element('you-wide').addEventListener('click', function () { windowState(!state().wide, false); });
@@ -159,6 +211,7 @@ export function openYou(ref) {
159
211
  if (ref) element('you-close').focus(); else element('you-search').focus();
160
212
  }
161
213
  export function closeYou() {
214
+ closeDeleteDialog(true);
162
215
  releaseRightWorkbench('you');
163
216
  if (!state().open) return;
164
217
  element('you-panel').classList.add('hidden');
@@ -172,6 +225,17 @@ export function closeYou() {
172
225
  export function handleYouMessage(msg) {
173
226
  if (msg.type === 'you_reviewed') { if (state().open) { requestList(); if (state().selected) requestEntry(state().selected); } return; }
174
227
  if (msg.type === 'you_changed') {
228
+ if (msg.activity && msg.activity.deleted) {
229
+ requestAttention();
230
+ if (state().selected === msg.activity.ref) {
231
+ if (state().deleteEntry && state().deleteEntry.ref === msg.activity.ref) closeDeleteDialog(true);
232
+ put({ readId: null, renderedRef: null, renderedRevision: null });
233
+ showList();
234
+ element('you-search').focus();
235
+ status('This memory was deleted and is no longer available.');
236
+ } else if (state().open) requestList();
237
+ return;
238
+ }
175
239
  requestAttention();
176
240
  if (msg.activity && msg.activity.seen) { if (state().open && !state().selected) requestList(); return; }
177
241
  if (msg.activity && msg.activity.error) { status(msg.activity.error); return; }
@@ -179,7 +243,7 @@ export function handleYouMessage(msg) {
179
243
  return;
180
244
  }
181
245
  var s = state();
182
- var key = { you_attention: 'attentionId', you_seen: 'seenId', you_list: 'listId', you_read: 'readId', you_comment: 'commentId', you_retry: 'retryId' }[msg.operation];
246
+ var key = { you_attention: 'attentionId', you_seen: 'seenId', you_list: 'listId', you_read: 'readId', you_comment: 'commentId', you_retry: 'retryId', you_delete: 'deleteId' }[msg.operation];
183
247
  if (!key || !s[key] || s[key] !== msg.requestId) return;
184
248
  var cleared = {}; cleared[key] = null; put(cleared);
185
249
  if (msg.operation === 'you_comment' && element('you-comment-input')) element('you-comment-input').form.querySelector('button').disabled = false;
@@ -189,10 +253,25 @@ export function handleYouMessage(msg) {
189
253
  return;
190
254
  }
191
255
  if (!state().open && msg.operation === 'you_read') return;
192
- if (!msg.ok) { if (msg.operation === 'you_read') showList(); status(msg.error || 'Clay could not complete this request.'); return; }
256
+ if (!msg.ok) {
257
+ if (msg.operation === 'you_read') showList();
258
+ if (msg.operation === 'you_delete' && deleteDialog) {
259
+ deleteDialog.querySelector('[data-action="delete"]').disabled = false;
260
+ deleteDialog.querySelector('[data-action="cancel"]').disabled = false;
261
+ deleteDialog.querySelector('.you-delete-dialog-status').textContent = msg.error || 'The memory could not be deleted. Try again.';
262
+ }
263
+ status(msg.error || 'Clay could not complete this request.'); return;
264
+ }
193
265
  status('');
194
266
  var result = msg.result;
195
- if (msg.operation === 'you_list') {
267
+ if (msg.operation === 'you_delete') {
268
+ closeDeleteDialog(true);
269
+ put({ deleteEntry: null });
270
+ showList();
271
+ element('you-search').focus();
272
+ requestAttention();
273
+ status('Memory deleted. Stored audit history remains.');
274
+ } else if (msg.operation === 'you_list') {
196
275
  var entries = s.append ? (s.entries || []).concat(result.items) : result.items;
197
276
  put({ entries: entries, nextOffset: result.nextOffset });
198
277
  var emptyMessage = state().query || state().category
@@ -210,7 +289,7 @@ export function handleYouMessage(msg) {
210
289
  element('you-detail').classList.remove('hidden'); element('you-back').classList.remove('hidden');
211
290
  var previousInput = element('you-comment-input');
212
291
  var draft = previousInput && previousInput.dataset.ref === result.ref ? previousInput.value : '';
213
- renderDetail(element('you-detail'), result, { commentPrefix: 'you', commentReviewer: 'Clay', onComment: function (ref, body, feedback, input) {
292
+ renderDetail(element('you-detail'), result, { commentPrefix: 'you', commentReviewer: 'Clay', canDelete: !result.deleted, deleteLabel: 'Delete memory', onDelete: deleteEntry, onComment: function (ref, body, feedback, input) {
214
293
  if (state().commentId) return;
215
294
  put({ commentId: sendYou('you_comment', { ref: ref, body: body }), commentRef: ref });
216
295
  input.form.querySelector('button').disabled = !!state().commentId;
@@ -236,13 +315,19 @@ export function initYou() {
236
315
  element('you-button').addEventListener('click', function () { openYou(); });
237
316
  store.subscribe(function (next, previous) {
238
317
  if (next.currentSlug !== previous.currentSlug || next.myUserId !== previous.myUserId) {
239
- closeYou(); clearTimeout(state().searchTimer);
318
+ closeDeleteDialog(true); closeYou(); clearTimeout(state().searchTimer);
240
319
  if (next.myUserId !== previous.myUserId) { if (element('you-panel')) element('you-panel').remove(); put({ entries: [], query: '', category: '', attentionVersion: 0, acknowledged: null, attentionId: null, seenId: null }); showAttention({ unread: 0, version: 0 }); }
241
- put({ listId: null, readId: null, commentId: null, retryId: null, seenId: null });
320
+ put({ listId: null, readId: null, commentId: null, retryId: null, seenId: null, deleteId: null, deleteEntry: null });
242
321
  if (element('you-comment-input')) element('you-comment-input').form.querySelector('button').disabled = false;
243
322
  }
244
323
  if (previous.connected && !next.connected) {
245
324
  put({ commentId: null, seenId: null, attentionId: null });
325
+ if (state().deleteId && deleteDialog) {
326
+ put({ deleteId: null });
327
+ deleteDialog.querySelector('[data-action="delete"]').disabled = false;
328
+ deleteDialog.querySelector('[data-action="cancel"]').disabled = false;
329
+ deleteDialog.querySelector('.you-delete-dialog-status').textContent = 'Disconnected. Reconnect before deleting. Stored audit history remains.';
330
+ }
246
331
  if (element('you-comment-input')) element('you-comment-input').form.querySelector('button').disabled = false;
247
332
  if (state().open) status('Disconnected. Reconnect before sending or refreshing.');
248
333
  }
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Muse Code">
2
+ <rect width="64" height="64" rx="14" fill="#111827"/>
3
+ <path d="M14 45V19h7l11 14 10-14h8v26h-7V30L32 45 21 30v15z" fill="#f8fafc"/>
4
+ </svg>
@@ -47,6 +47,7 @@
47
47
  @import url("css/stt.css");
48
48
  @import url("css/profile.css");
49
49
  @import url("css/user-settings.css?v=20260828-type1");
50
+ @import url("css/user-settings-sessions.css");
50
51
  @import url("css/settings-ui.css");
51
52
  @import url("css/admin.css");
52
53
  @import url("css/session-search.css");
@@ -58,6 +59,7 @@
58
59
  @import url("css/home-debate-planning.css");
59
60
  @import url("css/home-mate-creation.css");
60
61
  @import url("css/home-mate-settings.css");
62
+ @import url("css/mate-avatar-gallery.css");
61
63
  @import url("css/home-mate-model-picker.css");
62
64
  @import url("css/project-mate-creation.css");
63
65
  @import url("css/home-debate-live.css");
@@ -86,3 +88,7 @@
86
88
  @import url("css/server-settings-system.css");
87
89
 
88
90
  @import url("css/project-settings-modal.css");
91
+
92
+ @import url("css/clay-tool-activity.css");
93
+
94
+ @import url("css/contextual-clay.css");
package/lib/public/sw.js CHANGED
@@ -1,4 +1,4 @@
1
- var CACHE_NAME = "clay-offline-v4";
1
+ var CACHE_NAME = "clay-offline-v5";
2
2
 
3
3
  self.addEventListener("install", function (event) {
4
4
  event.waitUntil(self.skipWaiting());
@@ -23,6 +23,8 @@ self.addEventListener("activate", function (event) {
23
23
  function shouldCache(request, response) {
24
24
  if (request.method !== "GET") return false;
25
25
  if (!response || !response.ok) return false;
26
+ var cacheControl = response.headers && response.headers.get("Cache-Control") || "";
27
+ if (/(^|,)\s*(private|no-store)(?:\s*=\s*[^,]*)?(?=\s*(?:,|$))/i.test(cacheControl)) return false;
26
28
  // Cache same-origin static assets and CDN resources (jsdelivr, fonts)
27
29
  var url = new URL(request.url);
28
30
  if (url.origin === self.location.origin) return true;
@@ -115,51 +115,9 @@ function isSafeBashSegment(seg) {
115
115
  // Emit the `Bash(...)` permission patterns for ~/.claude/settings.json. Each
116
116
  // standalone command gets a bare form (zero-arg) and a space-wildcard form
117
117
  // (claude 2.x prefix matching); subcommands and exact commands likewise.
118
- function buildClayBashAllowPatterns() {
119
- var patterns = [];
120
- for (var i = 0; i < STANDALONE.length; i++) {
121
- patterns.push("Bash(" + STANDALONE[i] + ")");
122
- patterns.push("Bash(" + STANDALONE[i] + " *)");
123
- }
124
- var bins = Object.keys(SUBCOMMAND);
125
- for (var b = 0; b < bins.length; b++) {
126
- var subs = SUBCOMMAND[bins[b]];
127
- for (var s = 0; s < subs.length; s++) {
128
- var base = bins[b] + " " + subs[s];
129
- patterns.push("Bash(" + base + ")");
130
- patterns.push("Bash(" + base + " *)");
131
- }
132
- }
133
- for (var e = 0; e < EXACT.length; e++) {
134
- patterns.push("Bash(" + EXACT[e] + ")");
135
- patterns.push("Bash(" + EXACT[e] + " *)");
136
- }
137
- return patterns;
138
- }
139
-
140
- var GENERATED_SET = {};
141
- (function () {
142
- var p = buildClayBashAllowPatterns();
143
- for (var i = 0; i < p.length; i++) GENERATED_SET[p[i]] = true;
144
- })();
145
-
146
- // Recognize a `permissions.allow` entry that Clay owns, so the installer can
147
- // strip stale variants on upgrade (including shapes a previous version wrote)
148
- // WITHOUT clobbering user-authored patterns. Rules:
149
- // - Standalone commands: own every shape of `Bash(ls ...)` (any args), since
150
- // a user pattern for a command we manage is redundant with our broad one.
151
- // - Subcommand binaries (git, npm, ...) and exact commands: only strip the
152
- // precise patterns we generate, so a user's `Bash(git push)` survives.
153
- // Legacy colon shapes are handled separately by the installer.
154
- function isClayManagedBashPattern(p) {
155
- if (typeof p !== "string") return false;
156
- if (p.indexOf("Bash(") !== 0 || p.charAt(p.length - 1) !== ")") return false;
157
- if (GENERATED_SET[p]) return true;
158
- var inner = p.slice(5, -1).trim();
159
- if (!inner) return false;
160
- var word = inner.split(/[\s:]/)[0];
161
- return STANDALONE_SET[word] === true;
162
- }
118
+ var patternCodec = require("./yoke/claude-permission-patterns").attachPatterns({ STANDALONE: STANDALONE, SUBCOMMAND: SUBCOMMAND, EXACT: EXACT });
119
+ function buildClayBashAllowPatterns() { return patternCodec.build(); }
120
+ function isClayManagedBashPattern(pattern) { return patternCodec.isManaged(pattern); }
163
121
 
164
122
  module.exports = {
165
123
  STANDALONE: STANDALONE,
@@ -18,6 +18,7 @@ function createScheduledTaskRecords(ctx) {
18
18
  var runs = Array.isArray(record.runs) ? record.runs : [];
19
19
  var readiness = ctx.runtimeStatus ? ctx.runtimeStatus(record) : null;
20
20
  return {
21
+ createdBy: record.createdBy || null, updatedBy: record.updatedBy || null,
21
22
  id: record.id, revision: Number(record.updatedAt || 0), name: record.name || "",
22
23
  instructions: record.task || record.prompt || record.instructions || "",
23
24
  cron: record.cron || null, date: record.date || null, time: record.time || null,
@@ -49,7 +50,7 @@ function createScheduledTaskRecords(ctx) {
49
50
  return { ok: true, record: publicRecord(record) };
50
51
  }
51
52
 
52
- function update(session, id, revision, patch) {
53
+ function update(session, id, revision, patch, actor) {
53
54
  if (typeof id !== "string" || !ID_PATTERN.test(id)) return { ok: false, error: "Scheduled task id is invalid." };
54
55
  var record = ctx.registry.getById(id);
55
56
  if (!record) return { ok: false, error: "Scheduled task not found." };
@@ -94,6 +95,7 @@ function createScheduledTaskRecords(ctx) {
94
95
  }
95
96
  try {
96
97
  var updateData = Object.assign({}, checked.value);
98
+ if (actor) updateData.updatedBy = actor;
97
99
  if (claimOwner) { updateData.ownerId = session.ownerId; updateData.enabled = true; }
98
100
  if (updateData.cron) {
99
101
  updateData.date = record.cron && !record.scheduleRule ? record.date || null : null;
package/lib/scheduler.js CHANGED
@@ -239,6 +239,7 @@ function createLoopRegistry(opts) {
239
239
 
240
240
  function register(data) {
241
241
  var rec = {
242
+ createdBy: data.createdBy || null, updatedBy: data.updatedBy || null, creationFingerprint: data.creationFingerprint || null,
242
243
  id: data.id || ("loop_" + Date.now() + "_" + require("crypto").randomBytes(3).toString("hex")),
243
244
  name: data.name || "Untitled",
244
245
  task: data.task || "",
@@ -297,6 +298,7 @@ function createLoopRegistry(opts) {
297
298
  if (!rec) return null;
298
299
  var previous = Object.assign({}, rec);
299
300
 
301
+ if (data.updatedBy !== undefined) rec.updatedBy = data.updatedBy;
300
302
  if (data.name !== undefined) rec.name = data.name;
301
303
  if (data.cron !== undefined) rec.cron = data.cron;
302
304
  if (data.enabled !== undefined) rec.enabled = data.enabled;