clay-server 3.8.1 → 4.0.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 (222) hide show
  1. package/lib/ask-user-mcp-server.js +5 -119
  2. package/lib/background-task-timing.js +105 -0
  3. package/lib/builtin-mates.js +6 -6
  4. package/lib/claude-hook-installer.js +15 -0
  5. package/lib/clay-history-mcp-server.js +62 -297
  6. package/lib/daemon.js +23 -1
  7. package/lib/debate-model-selection.js +119 -0
  8. package/lib/home-debate-tool-policy.js +164 -0
  9. package/lib/home-response-notifications.js +26 -0
  10. package/lib/knowledge-import.js +436 -0
  11. package/lib/knowledge-record-store.js +188 -0
  12. package/lib/knowledge-search.js +224 -0
  13. package/lib/mate-creation-mcp-server.js +55 -0
  14. package/lib/mate-knowledge-mcp-server.js +151 -0
  15. package/lib/mate-knowledge-migration.js +283 -0
  16. package/lib/mate-knowledge-service.js +488 -0
  17. package/lib/mate-knowledge-sync.js +482 -0
  18. package/lib/mate-ready-creation.js +95 -0
  19. package/lib/mates.js +2 -0
  20. package/lib/notes.js +2 -1
  21. package/lib/project-ask-user.js +64 -0
  22. package/lib/project-capsule-catalog.js +101 -0
  23. package/lib/project-connection.js +17 -0
  24. package/lib/project-debate-proposal.js +133 -17
  25. package/lib/project-debate.js +214 -110
  26. package/lib/project-delegated-follow-up.js +84 -0
  27. package/lib/project-delegated-session.js +53 -0
  28. package/lib/project-filesystem.js +7 -9
  29. package/lib/project-knowledge.js +23 -0
  30. package/lib/project-logs-comments.js +137 -0
  31. package/lib/project-logs-mcp-server.js +290 -0
  32. package/lib/project-logs-query.js +167 -0
  33. package/lib/project-logs-root.js +67 -0
  34. package/lib/project-logs-schema.js +259 -0
  35. package/lib/project-logs-service.js +357 -0
  36. package/lib/project-logs-snapshot.js +202 -0
  37. package/lib/project-logs-store.js +498 -0
  38. package/lib/project-logs-versioning.js +128 -0
  39. package/lib/project-logs.js +347 -0
  40. package/lib/project-mate-creation-proposal.js +120 -0
  41. package/lib/project-mate-interaction.js +14 -0
  42. package/lib/project-mate-knowledge.js +110 -0
  43. package/lib/project-memory.js +36 -7
  44. package/lib/project-models.js +157 -32
  45. package/lib/project-session-notes.js +2 -2
  46. package/lib/project-session-pair.js +8 -8
  47. package/lib/project-sessions.js +66 -51
  48. package/lib/project-vendor-login.js +414 -0
  49. package/lib/project-worker-proposal.js +25 -25
  50. package/lib/project-workspace-query.js +144 -0
  51. package/lib/project.js +433 -102
  52. package/lib/public/app.js +109 -48
  53. package/lib/public/css/avatar-imprints.css +0 -1
  54. package/lib/public/css/base.css +4 -0
  55. package/lib/public/css/capsule-ui.css +389 -0
  56. package/lib/public/css/command-palette.css +306 -6
  57. package/lib/public/css/home-capsule-library.css +243 -0
  58. package/lib/public/css/home-capsule-source.css +192 -0
  59. package/lib/public/css/home-debate-live.css +146 -0
  60. package/lib/public/css/home-debate-planning.css +125 -0
  61. package/lib/public/css/home-debates-archive.css +281 -0
  62. package/lib/public/css/home-hub.css +896 -405
  63. package/lib/public/css/home-mate-creation.css +34 -0
  64. package/lib/public/css/home-mate-model-picker.css +131 -0
  65. package/lib/public/css/home-mate-settings.css +344 -0
  66. package/lib/public/css/home-session-actions.css +265 -0
  67. package/lib/public/css/home-sidebar.css +667 -0
  68. package/lib/public/css/icon-strip.css +1 -2
  69. package/lib/public/css/input.css +79 -25
  70. package/lib/public/css/mates.css +7 -34
  71. package/lib/public/css/pane.css +1 -1
  72. package/lib/public/css/playbook.css +0 -80
  73. package/lib/public/css/project-logs.css +234 -0
  74. package/lib/public/css/scheduler.css +1 -1
  75. package/lib/public/css/sticky-notes.css +53 -117
  76. package/lib/public/css/tui-attention.css +0 -44
  77. package/lib/public/css/workspace-assignment.css +45 -0
  78. package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
  79. package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
  80. package/lib/public/index.html +96 -74
  81. package/lib/public/modules/app-connection.js +100 -5
  82. package/lib/public/modules/app-dm.js +43 -160
  83. package/lib/public/modules/app-home-hub.js +328 -585
  84. package/lib/public/modules/app-message-cards.js +242 -0
  85. package/lib/public/modules/app-message-router.js +84 -0
  86. package/lib/public/modules/app-messages.js +124 -38
  87. package/lib/public/modules/app-notifications.js +8 -119
  88. package/lib/public/modules/app-panels.js +43 -2
  89. package/lib/public/modules/app-projects.js +9 -1
  90. package/lib/public/modules/app-rendering.js +21 -602
  91. package/lib/public/modules/avatar-imprint.js +11 -8
  92. package/lib/public/modules/background-tasks-ui.js +139 -16
  93. package/lib/public/modules/chat-bubble-renderer.js +152 -0
  94. package/lib/public/modules/chat-render-runtime.js +198 -0
  95. package/lib/public/modules/command-palette.js +225 -436
  96. package/lib/public/modules/dm-render.js +82 -0
  97. package/lib/public/modules/home-capsule-creation-intent.js +31 -0
  98. package/lib/public/modules/home-capsule-library.js +146 -0
  99. package/lib/public/modules/home-capsule-source.js +383 -0
  100. package/lib/public/modules/home-chat-identity.js +35 -0
  101. package/lib/public/modules/home-chat-scroll.js +77 -0
  102. package/lib/public/modules/home-chat-stream-state.js +34 -0
  103. package/lib/public/modules/home-composer-focus.js +25 -0
  104. package/lib/public/modules/home-conversations-sheet.js +179 -0
  105. package/lib/public/modules/home-debate-activity.js +48 -0
  106. package/lib/public/modules/home-debate-controls.js +295 -0
  107. package/lib/public/modules/home-debate-launch.js +41 -0
  108. package/lib/public/modules/home-debate-live.js +284 -0
  109. package/lib/public/modules/home-debate-models.js +73 -0
  110. package/lib/public/modules/home-debate-planning.js +335 -0
  111. package/lib/public/modules/home-debates-archive.js +279 -0
  112. package/lib/public/modules/home-dock-resize.js +74 -0
  113. package/lib/public/modules/home-dock.js +446 -0
  114. package/lib/public/modules/home-mate-chat.js +496 -0
  115. package/lib/public/modules/home-mate-creation.js +109 -0
  116. package/lib/public/modules/home-mate-model-picker.js +281 -0
  117. package/lib/public/modules/home-mate-selection.js +38 -0
  118. package/lib/public/modules/home-mate-settings-menu.js +131 -0
  119. package/lib/public/modules/home-mate-settings.js +383 -0
  120. package/lib/public/modules/home-session-actions.js +373 -0
  121. package/lib/public/modules/home-session-model-confirmation.js +13 -0
  122. package/lib/public/modules/home-shell.js +9 -0
  123. package/lib/public/modules/home-sidebar-chat-list.js +63 -0
  124. package/lib/public/modules/home-sidebar.js +165 -0
  125. package/lib/public/modules/home-sub-surface.js +19 -0
  126. package/lib/public/modules/home-surface-boot.js +68 -0
  127. package/lib/public/modules/home-surface.js +141 -0
  128. package/lib/public/modules/home-tools.js +271 -0
  129. package/lib/public/modules/markdown.js +50 -2
  130. package/lib/public/modules/mate-management.js +86 -0
  131. package/lib/public/modules/mate-sidebar.js +0 -8
  132. package/lib/public/modules/mate-wizard.js +0 -7
  133. package/lib/public/modules/mention.js +17 -19
  134. package/lib/public/modules/pane-bridge.js +9 -0
  135. package/lib/public/modules/profile.js +4 -5
  136. package/lib/public/modules/project-logs-ambient.js +238 -0
  137. package/lib/public/modules/project-logs-render.js +359 -0
  138. package/lib/public/modules/project-logs.js +328 -0
  139. package/lib/public/modules/project-settings.js +34 -28
  140. package/lib/public/modules/project-switcher.js +11 -5
  141. package/lib/public/modules/project-workspace-assignment.js +23 -0
  142. package/lib/public/modules/scheduler.js +17 -3
  143. package/lib/public/modules/search-clay-chat.js +402 -0
  144. package/lib/public/modules/server-settings.js +14 -12
  145. package/lib/public/modules/session-actions.js +1 -1
  146. package/lib/public/modules/sidebar-mates.js +56 -552
  147. package/lib/public/modules/sidebar-mobile.js +12 -73
  148. package/lib/public/modules/sidebar-presence.js +37 -0
  149. package/lib/public/modules/sidebar-sessions.js +25 -1
  150. package/lib/public/modules/split-pair-ui.js +13 -13
  151. package/lib/public/modules/split-view.js +7 -0
  152. package/lib/public/modules/sticky-notes.js +106 -53
  153. package/lib/public/modules/tool-input-composition.js +48 -0
  154. package/lib/public/modules/tool-llm-status.js +167 -0
  155. package/lib/public/modules/tool-palette.js +76 -4
  156. package/lib/public/modules/tool-renderer-advanced.js +285 -0
  157. package/lib/public/modules/tool-renderer-chart.js +158 -0
  158. package/lib/public/modules/tool-renderer-semantics.js +35 -0
  159. package/lib/public/modules/tool-renderer.js +464 -0
  160. package/lib/public/modules/tool-runtime.js +309 -0
  161. package/lib/public/modules/tool-ui-evaluator.js +97 -0
  162. package/lib/public/modules/tool-ui-tree.js +21 -0
  163. package/lib/public/modules/tui-attention.js +10 -0
  164. package/lib/public/modules/user-settings.js +16 -23
  165. package/lib/public/modules/vendor-login.js +287 -0
  166. package/lib/public/modules/worker-proposal.js +2 -2
  167. package/lib/public/modules/workspace-assignment-card.js +149 -0
  168. package/lib/public/modules/workspace-assignment-routing.js +4 -0
  169. package/lib/public/style.css +14 -2
  170. package/lib/runtime-env.js +65 -0
  171. package/lib/sdk-bridge.js +120 -32
  172. package/lib/sdk-message-processor.js +34 -13
  173. package/lib/server-home-capsule-creation.js +36 -0
  174. package/lib/server-home-chat-events.js +287 -0
  175. package/lib/server-home-chat.js +518 -0
  176. package/lib/server-home-clay-entry.js +65 -0
  177. package/lib/server-home-clay-session-links.js +26 -0
  178. package/lib/server-home-debate-planning.js +214 -0
  179. package/lib/server-home-debates.js +137 -0
  180. package/lib/server-home-mate-creation.js +261 -0
  181. package/lib/server-home-models.js +241 -0
  182. package/lib/server-home-preferences.js +61 -0
  183. package/lib/server-mates.js +37 -0
  184. package/lib/server-tools.js +377 -0
  185. package/lib/server.js +166 -59
  186. package/lib/session-pair-mcp-server.js +6 -6
  187. package/lib/sessions.js +22 -4
  188. package/lib/tool-capsule-source.js +142 -0
  189. package/lib/tool-control-mcp-server.js +126 -0
  190. package/lib/tool-llm.js +48 -0
  191. package/lib/tool-storage.js +77 -0
  192. package/lib/tool-ui-spec-advanced.js +82 -0
  193. package/lib/tool-ui-spec.js +261 -0
  194. package/lib/tools-registry.js +286 -0
  195. package/lib/users-home-dock-preferences.js +77 -0
  196. package/lib/users-home-surface-preferences.js +99 -0
  197. package/lib/users-preferences.js +4 -7
  198. package/lib/users.js +12 -0
  199. package/lib/whats-new-content.js +3 -3
  200. package/lib/workspace-assignment-service.js +420 -0
  201. package/lib/workspace-query-mcp-server.js +154 -0
  202. package/lib/workspace-query-service.js +492 -0
  203. package/lib/ws-schema.js +107 -12
  204. package/lib/yoke/adapters/acp.js +2 -1
  205. package/lib/yoke/adapters/antigravity.js +2 -1
  206. package/lib/yoke/adapters/claude-worker.js +11 -4
  207. package/lib/yoke/adapters/claude.js +141 -46
  208. package/lib/yoke/adapters/codex.js +79 -11
  209. package/lib/yoke/adapters/kiro.js +2 -1
  210. package/lib/yoke/claude-user-input.js +38 -0
  211. package/lib/yoke/codex-app-server.js +20 -2
  212. package/lib/yoke/codex-background-tasks.js +8 -2
  213. package/lib/yoke/codex-user-input.js +64 -0
  214. package/lib/yoke/complete-once.js +164 -0
  215. package/lib/yoke/index.js +5 -1
  216. package/lib/yoke/interface.js +19 -0
  217. package/lib/yoke/mcp-bridge-server.js +2 -6
  218. package/lib/yoke/user-input.js +254 -0
  219. package/package.json +4 -3
  220. package/lib/public/css/home-chat.css +0 -380
  221. package/lib/public/modules/home-chat.js +0 -438
  222. package/lib/server-clay-home.js +0 -245
@@ -15,6 +15,7 @@
15
15
  <link rel="icon" type="image/png" sizes="32x32" href="clay-studio-favicon-32.png">
16
16
  <link rel="apple-touch-icon" href="apple-touch-icon.png">
17
17
  <title>Clay Studio</title>
18
+ <link rel="preload" href="/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2" as="font" type="font/woff2" crossorigin>
18
19
  <link rel="preconnect" href="https://fonts.googleapis.com">
19
20
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
20
21
  <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500;700&family=Nunito:wght@700;800&display=swap" rel="stylesheet">
@@ -30,7 +31,7 @@
30
31
  (function(){try{var k="clay-theme-vars",v=localStorage.getItem(k),r=document.documentElement;if(v){var o=JSON.parse(v),p;for(p in o)r.style.setProperty(p,o[p]);var vt=localStorage.getItem(k.replace("-vars","-variant"));if(vt==="light"){r.classList.add("light-theme");r.classList.remove("dark-theme")}else{r.classList.add("dark-theme");r.classList.remove("light-theme")}var m=document.querySelector('meta[name="theme-color"]');if(m&&o["--bg"])m.setAttribute("content",o["--bg"])}else{var sl=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;if(sl){r.classList.add("light-theme");r.classList.remove("dark-theme")}}}catch(e){}})();
31
32
  </script>
32
33
  <script>if(window.navigator.standalone||window.matchMedia("(display-mode:standalone)").matches){document.documentElement.classList.add("pwa-standalone")}</script>
33
- <link rel="stylesheet" href="style.css?v=20260829-terminal-canvas1">
34
+ <link rel="stylesheet" href="style.css?v=20260901-clay-chat6">
34
35
  <style>
35
36
  @media(max-width:768px){
36
37
  /* User messages: vertical stack, avatar on top, right-aligned */
@@ -85,7 +86,7 @@
85
86
  </div>
86
87
  </div>
87
88
  </div>
88
- <button id="cmd-palette-btn" class="cmd-palette-searchbar" title="Command palette"><i data-lucide="search"></i><span class="cmd-palette-searchbar-text">Search sessions, projects, and commands</span><kbd class="cmd-palette-searchbar-kbd"></kbd></button>
89
+ <button id="cmd-palette-btn" class="cmd-palette-searchbar" title="Search or ask Clay" aria-label="Search or ask Clay"><i data-lucide="search" aria-hidden="true"></i><span class="cmd-palette-searchbar-text">Search or ask Clay</span><kbd class="cmd-palette-searchbar-kbd"></kbd></button>
89
90
  <div class="top-bar-actions">
90
91
  <!-- Pill badges -->
91
92
  <div id="skip-perms-pill" class="top-bar-pill pill-error hidden"><i data-lucide="shield-off"></i> <span>Skip perms</span></div>
@@ -104,6 +105,7 @@
104
105
  <div class="icon-strip-home" title="Clay Studio">
105
106
  <span class="icon-strip-pill"></span>
106
107
  <img class="icon-strip-logo" src="clay-studio-symbol.png" width="38" height="38" alt="Clay Studio">
108
+ <span class="icon-strip-home-badge" id="icon-strip-home-badge"></span>
107
109
  </div>
108
110
  <div class="icon-strip-separator"></div>
109
111
  <button type="button" class="icon-strip-hint" id="icon-strip-hint-project" data-switcher-mode="project" aria-label="Switch project"></button>
@@ -122,70 +124,93 @@
122
124
  <!-- === Main Area (sidebar + resize-handle + main-column) === -->
123
125
  <div id="main-area">
124
126
  <div id="home-hub" class="hidden">
125
- <button id="home-hub-close" class="home-hub-close-btn hidden">
126
- <i data-lucide="x"></i>
127
- <span>ESC</span>
128
- </button>
129
127
  <div class="home-hub-inner">
130
- <div class="hub-greeting">
131
- <h1 id="hub-greeting-text"></h1>
132
- <p id="hub-greeting-date"></p>
133
- </div>
134
-
135
- <div id="home-hub-mates" class="home-hub-mates hidden"></div>
136
-
137
- <div class="hub-columns">
138
- <div class="hub-card hub-upcoming">
139
- <div class="hub-card-header">
140
- <span class="hub-card-title">Upcoming</span>
141
- <span class="hub-card-count" id="hub-upcoming-count"></span>
128
+ <button id="home-sidebar-backdrop" class="home-sidebar-backdrop" type="button" aria-label="Close Home navigation"></button>
129
+ <aside id="home-sidebar" class="home-sidebar" aria-label="Home navigation">
130
+ <div class="home-sidebar-brand-row">
131
+ <div class="home-sidebar-brand"><img src="/clay-studio-symbol.png" alt=""><span class="home-sidebar-brand-wordmark">Clay Studio</span></div>
132
+ <div class="home-sidebar-brand-actions">
133
+ <button id="home-sidebar-all" class="home-sidebar-icon-btn" type="button" title="Search chats" aria-label="Search chats"><i data-lucide="search"></i></button>
134
+ <button id="home-sidebar-collapse" class="home-sidebar-icon-btn" type="button" title="Collapse sidebar" aria-label="Collapse Home sidebar"><i data-lucide="panel-left-close"></i></button>
142
135
  </div>
143
- <div class="hub-upcoming-list" id="hub-upcoming-list"></div>
144
136
  </div>
145
- <div class="hub-card hub-projects-summary">
146
- <div class="hub-card-header">
147
- <span class="hub-card-title">Projects</span>
137
+ <nav class="home-sidebar-primary-actions" aria-label="Home actions">
138
+ <button id="home-sidebar-new" class="home-sidebar-action home-sidebar-new" type="button" title="New Chat" aria-label="Start a new chat with the current Mate" disabled><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="message-square-plus"></i></span><span>New Chat</span></button>
139
+ <button id="home-sidebar-debate" class="home-sidebar-action" type="button" title="Browse debates" aria-label="Browse debates" aria-pressed="false"><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="messages-square"></i></span><span>Debates</span></button>
140
+ <button id="home-scheduler-btn" class="home-sidebar-action" type="button" title="Scheduled Tasks" aria-label="Scheduled Tasks"><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="calendar-clock"></i></span><span>Scheduled Tasks</span></button>
141
+ <button id="home-tools-btn" class="home-sidebar-action" type="button" title="Capsules" aria-label="Capsules" aria-expanded="false" aria-controls="home-tool-workbench"><span class="home-sidebar-action-icon" aria-hidden="true"><i data-lucide="box"></i></span><span id="home-tools-label">Capsules</span><span id="home-tools-activity" class="home-tools-activity" aria-hidden="true"></span></button>
142
+ </nav>
143
+ <section class="home-sidebar-section home-sidebar-mate-section" aria-labelledby="home-sidebar-mate-label">
144
+ <div id="home-sidebar-mate-label" class="home-sidebar-label">Mates</div>
145
+ <div id="home-mate-list" class="home-mate-list" role="list" aria-label="Mates"></div>
146
+ </section>
147
+ <section class="home-sidebar-section home-sidebar-recents" aria-labelledby="home-sidebar-recent-label">
148
+ <div class="home-sidebar-recents-heading">
149
+ <div id="home-sidebar-recent-label" class="home-sidebar-label">Chats</div>
150
+ <div class="home-chat-scope" role="group" aria-label="Chat scope">
151
+ <button class="home-chat-scope-option" type="button" data-home-chat-scope="current" aria-pressed="false" aria-controls="home-sidebar-recent-list">Current</button>
152
+ <button class="home-chat-scope-option" type="button" data-home-chat-scope="all" aria-pressed="true" aria-controls="home-sidebar-recent-list">All</button>
153
+ </div>
154
+ </div>
155
+ <div id="home-sidebar-recent-list" class="home-sidebar-recent-list"></div>
156
+ </section>
157
+ </aside>
158
+ <div id="home-workspace" class="home-workspace">
159
+ <button id="home-sidebar-expand" class="home-sidebar-expand" type="button" title="Show sidebar" aria-label="Show Home sidebar" aria-describedby="home-sidebar-expand-brand-label"><i data-lucide="panel-left-open"></i><span id="home-sidebar-expand-brand-label" class="home-sidebar-brand-wordmark home-sidebar-expand-wordmark">Clay Studio</span></button>
160
+ <button id="home-close-control" class="home-close-control hidden" type="button" title="Close Home" aria-label="Close Home"><i data-lucide="x" aria-hidden="true"></i><span>Close</span></button>
161
+ <div id="home-conversation-region" class="home-conversation-region">
162
+ <div id="home-mate-chat" class="home-mate-chat">
163
+ <div class="home-mate-chat-stage">
164
+ <section id="home-debates-archive" class="home-debates-archive" aria-labelledby="home-debates-title" hidden>
165
+ <header class="home-debates-header">
166
+ <div>
167
+ <p class="home-debates-eyebrow">Home archive</p>
168
+ <h1 id="home-debates-title" tabindex="-1">Debates</h1>
169
+ <p id="home-debates-summary" class="home-debates-summary" role="status" aria-live="polite">Loading debates…</p>
170
+ </div>
171
+ <button id="home-debates-new" class="home-debates-new" type="button"><i data-lucide="messages-square" aria-hidden="true"></i><span>New debate</span></button>
172
+ </header>
173
+ <form id="home-debates-topic-form" class="home-debates-topic-form" hidden>
174
+ <label for="home-debates-topic">What should the debate be about?</label>
175
+ <textarea id="home-debates-topic" rows="2" maxlength="1000" required placeholder="Enter a question or topic"></textarea>
176
+ <div class="home-debates-topic-actions">
177
+ <p id="home-debates-topic-status" role="status" aria-live="polite">Press Ctrl or Command + Enter to start.</p>
178
+ <button id="home-debates-topic-cancel" type="button">Cancel</button>
179
+ <button id="home-debates-topic-submit" type="submit">Start debate</button>
180
+ </div>
181
+ </form>
182
+ <div id="home-debates-list" class="home-debates-list" aria-label="Debate archive"></div>
183
+ </section>
184
+ <div class="home-mate-chat-messages" id="home-mate-chat-messages"></div>
185
+ <button id="home-chat-new-activity" class="home-chat-new-activity" type="button" hidden><i data-lucide="arrow-down" aria-hidden="true"></i><span>New activity</span></button>
186
+ <div class="home-mate-chat-composer-frame">
187
+ <div id="home-mate-chat-composer" class="home-mate-chat-composer">
188
+ <textarea id="home-mate-chat-input" rows="1" placeholder="Message"></textarea>
189
+ <button id="home-mate-chat-send" aria-label="Send message"><i data-lucide="arrow-up"></i></button>
190
+ </div>
191
+ <div id="home-mate-chat-session-model" class="home-mate-chat-session-model" role="status" aria-live="polite" title="Model for this conversation: Loading model…">
192
+ <i data-lucide="cpu" aria-hidden="true"></i><span>Conversation model</span><span aria-hidden="true">·</span><span id="home-mate-chat-session-model-value">Loading model…</span><button id="home-mate-chat-session-model-choose" class="hidden" type="button">Choose model</button>
193
+ </div>
194
+ <div id="home-debate-controls-slot" class="home-debate-controls-slot" hidden></div>
195
+ </div>
196
+ <div id="home-mate-chat-suggestions" class="home-mate-chat-suggestions"></div>
197
+ </div>
148
198
  </div>
149
- <div class="hub-projects-list" id="hub-projects-list"></div>
150
- </div>
151
- </div>
152
-
153
- <div class="hub-card hub-week">
154
- <div class="hub-card-header">
155
- <span class="hub-card-title">This Week</span>
156
- </div>
157
- <div class="hub-week-strip" id="hub-week-strip"></div>
158
- </div>
159
-
160
- <div class="hub-card hub-whats-new-card" id="hub-whats-new-card">
161
- <div class="hub-card-header">
162
- <span class="hub-card-title">What's New</span>
163
- </div>
164
- <div class="hub-whats-new" id="hub-whats-new"></div>
165
- </div>
166
-
167
- <div class="hub-card hub-playbooks" id="hub-playbooks">
168
- <div class="hub-card-header">
169
- <span class="hub-card-title">Quick Start</span>
170
- </div>
171
- <div class="hub-playbooks-grid" id="hub-playbooks-grid"></div>
172
- </div>
173
-
174
-
175
- <div class="hub-tip">
176
- <div class="hub-tip-icon">💡</div>
177
- <div class="hub-tip-body">
178
- <div class="hub-tip-label">Did you know?</div>
179
- <div class="hub-tip-text" id="hub-tip-text"></div>
180
- </div>
181
- <div class="hub-tip-nav">
182
- <button class="hub-tip-prev" id="hub-tip-prev" title="Previous tip">
183
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
184
- </button>
185
- <button class="hub-tip-next" id="hub-tip-next" title="Next tip">
186
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 6 15 12 9 18"/></svg>
187
- </button>
188
199
  </div>
200
+ <div id="home-dock-backdrop" class="home-dock-backdrop"></div>
201
+ <div id="home-dock-divider" class="home-dock-divider" role="separator" aria-label="Resize Capsules Workbench" aria-orientation="vertical" tabindex="0"></div>
202
+ <section id="home-tool-workbench" class="home-tool-workbench" aria-label="Capsules Workbench">
203
+ <div class="home-dock-header">
204
+ <button id="home-dock-return" class="home-dock-return" type="button"><i data-lucide="arrow-left"></i><span>Return to conversation</span></button>
205
+ <div class="home-dock-switcher" id="home-dock-switcher"></div>
206
+ <div class="home-dock-context" id="home-dock-context" aria-label="Active Capsule actions" hidden></div>
207
+ <div class="home-dock-actions">
208
+ <button id="home-dock-focus" type="button" title="Focus Capsules Workbench" aria-label="Focus Capsules Workbench"><i data-lucide="maximize-2"></i></button>
209
+ <button id="home-dock-collapse" type="button" title="Collapse Capsules Workbench" aria-label="Collapse Capsules Workbench"><i data-lucide="panel-right-close"></i></button>
210
+ </div>
211
+ </div>
212
+ <div class="home-dock-content" id="home-dock-content"></div>
213
+ </section>
189
214
  </div>
190
215
  </div>
191
216
  </div>
@@ -389,7 +414,7 @@
389
414
  <div id="debate-sticky" class="hidden"></div>
390
415
  <div class="status">
391
416
  <button id="header-session-actions-btn" type="button" aria-label="Session actions" aria-haspopup="menu" aria-expanded="false">
392
- <i data-lucide="bot"></i><span>Add AI worker</span><i class="session-actions-trigger-chevron" data-lucide="chevron-down"></i>
417
+ <i data-lucide="bot"></i><span>Add Split Worker</span><i class="session-actions-trigger-chevron" data-lucide="chevron-down"></i>
393
418
  </button>
394
419
  <button type="button" id="header-tui-font-btn" class="header-tui-font-btn hidden" title="Terminal font" aria-label="Terminal font">
395
420
  <i data-lucide="type"></i>
@@ -477,12 +502,14 @@
477
502
  <div class="usage-section-label">Session Tokens</div>
478
503
  <div class="usage-row"><span class="usage-label">Input</span><span id="context-input" class="usage-value">0</span></div>
479
504
  <div class="usage-row"><span class="usage-label">Output</span><span id="context-output" class="usage-value">0</span></div>
505
+ <div class="usage-row hidden" id="context-thinking-row" title="Extended thinking tokens, already counted inside Output"><span class="usage-label">Thinking</span><span id="context-thinking" class="usage-value">0</span></div>
480
506
  <div class="usage-row"><span class="usage-label">Cache read</span><span id="context-cache-read" class="usage-value">0</span></div>
481
507
  <div class="usage-row"><span class="usage-label">Cache write</span><span id="context-cache-write" class="usage-value">0</span></div>
482
508
  <div class="usage-divider"></div>
483
509
  <div class="usage-section-label">Model</div>
484
510
  <div class="usage-row"><span class="usage-label">Name</span><span id="context-model" class="usage-value">-</span></div>
485
511
  <div class="usage-row"><span class="usage-label">Cost</span><span id="context-cost" class="usage-value">$0.0000</span></div>
512
+ <div class="usage-row hidden" id="context-cost-basis-row" title="Which price table this cost was computed from"><span class="usage-label">Priced at</span><span id="context-cost-basis" class="usage-value">-</span></div>
486
513
  <div class="usage-row"><span class="usage-label">Turns</span><span id="context-turns" class="usage-value">0</span></div>
487
514
  </div>
488
515
  </div>
@@ -843,10 +870,7 @@
843
870
  <!-- Environment -->
844
871
  <div class="ps-section" data-section="environment">
845
872
  <h2>Environment</h2>
846
- <p class="ps-section-desc">Store API keys, tokens, and config for this project. Paste a <code>.env</code> file to import multiple variables at once.</p>
847
- <div class="settings-hint ps-env-notice hidden" id="ps-env-override-notice">
848
- <i data-lucide="info"></i> A <code>.envrc</code> file exists in the project directory and will take precedence over these settings.
849
- </div>
873
+ <p class="ps-section-desc">Store API keys, tokens, and config for coding-agent processes in this project. Changes apply to newly created processes; active processes, terminals, the daemon, and the browser keep their current environment.</p>
850
874
  <div class="ps-env-tabs">
851
875
  <button class="ps-env-tab active" data-tab="project">Project</button>
852
876
  <button class="ps-env-tab" data-tab="shared">Shared</button>
@@ -861,7 +885,7 @@
861
885
  </div>
862
886
  </div>
863
887
  <div class="ps-env-tab-content" data-tab="shared">
864
- <p class="settings-hint" style="margin-bottom: 12px;">Shared variables apply to all projects. Project-level variables take precedence.</p>
888
+ <p class="settings-hint" style="margin-bottom: 12px;">Shared variables apply to newly created coding-agent processes in all projects. Project-level variables take precedence.</p>
865
889
  <div class="ps-env-header">
866
890
  <button class="settings-btn-sm" id="ps-shared-env-add-btn"><i data-lucide="plus"></i> Add Variable</button>
867
891
  <span class="ps-save-status" id="ps-shared-env-save-status"></span>
@@ -1128,8 +1152,8 @@
1128
1152
  <div class="settings-card">
1129
1153
  <label class="settings-toggle-row">
1130
1154
  <div>
1131
- <span class="settings-label">Use Mates</span>
1132
- <div class="settings-hint">Off hides every Mates surface in Clay. Existing Mates and their memory are preserved.</div>
1155
+ <span class="settings-label">Mate DMs in projects</span>
1156
+ <div class="settings-hint">Show Mate DM shortcuts in project workspaces. Home, Debates, mentions, and Mate memory stay available.</div>
1133
1157
  </div>
1134
1158
  <input type="checkbox" id="us-mates-enabled">
1135
1159
  <span class="toggle-track"><span class="toggle-thumb"></span></span>
@@ -1372,7 +1396,7 @@
1372
1396
  </div>
1373
1397
  <div class="server-settings-section" data-section="environment">
1374
1398
  <h2>Environment</h2>
1375
- <p class="settings-hint" style="margin-bottom: 16px;">Define environment variables shared across all projects. Project-level variables take precedence over shared ones.</p>
1399
+ <p class="settings-hint" style="margin-bottom: 16px;">Define variables for newly created coding-agent processes across all projects. Project-level variables take precedence. Active processes, terminals, the daemon, and the browser keep their current environment.</p>
1376
1400
  <div class="ps-env-header">
1377
1401
  <button class="settings-btn-sm" id="ss-env-add-btn"><i data-lucide="plus"></i> Add Variable</button>
1378
1402
  <span class="ps-save-status" id="ss-env-save-status"></span>
@@ -1877,7 +1901,7 @@
1877
1901
  <div class="mate-intro-step"><span class="mate-intro-step-num">2</span> Have a short interview where your Mate gets to know you</div>
1878
1902
  <div class="mate-intro-step"><span class="mate-intro-step-num">3</span> Start talking</div>
1879
1903
  </div>
1880
- <p class="mate-intro-privacy">Mates run on Claude Code or ChatGPT Codex, your choice. No separate API keys or external services needed. Your conversations stay on your Clay server and are never stored elsewhere.</p>
1904
+ <p class="mate-intro-privacy">Mates run on Claude Code or ChatGPT Codex, your choice. Clay keeps your conversation history on your server, under your control.</p>
1881
1905
  </div>
1882
1906
  </div>
1883
1907
  <!-- Step 1: Relationship -->
@@ -2282,7 +2306,7 @@
2282
2306
  <script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"></script>
2283
2307
  <script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0/lib/addon-web-links.min.js"></script>
2284
2308
  <script src="https://cdn.jsdelivr.net/npm/@xterm/addon-webgl@0/lib/addon-webgl.min.js"></script>
2285
- <script type="module" src="app.js?v=20260829-image-save-details1"></script>
2309
+ <script type="module" src="app.js?v=20260902-markdown-boundary1"></script>
2286
2310
  <div id="pwa-install-modal" class="pwa-modal hidden">
2287
2311
  <div class="pwa-modal-backdrop"></div>
2288
2312
  <div class="pwa-modal-card">
@@ -2301,7 +2325,5 @@
2301
2325
  </div>
2302
2326
  </div>
2303
2327
 
2304
- <!-- Clay FAB + popover disabled. Markup intentionally removed; assets
2305
- (home-chat.js / home-chat.css) remain in repo for future re-enable. -->
2306
2328
  </body>
2307
2329
  </html>
@@ -6,11 +6,16 @@ import { getWs, setWs } from './ws-ref.js';
6
6
  import { getStatusDot, getSendBtn } from './dom-refs.js';
7
7
  import { setSendBtnMode, blinkIO, setActivity } from './app-favicon.js';
8
8
  import { hasSendableContent } from './input.js';
9
- import { processMessage } from './app-messages.js';
9
+ import { processMessage } from './app-message-router.js';
10
10
  import { flushPendingExtMessages } from './app-misc.js';
11
11
  import { resetTerminals } from './terminal.js';
12
12
  import { closeDmUserPicker } from './sidebar-mates.js';
13
13
  import { openDm } from './app-dm.js';
14
+ import { requestTools } from './home-tools.js';
15
+ import { requestHomeDockPreference } from './home-dock.js';
16
+ import { resumeHomeChat } from './home-mate-chat.js';
17
+ import { requestHomeSurfacePreference } from './home-surface.js';
18
+ import { isHomeDebatesSurface } from './home-sub-surface.js';
14
19
 
15
20
  var reconnectTimer = null;
16
21
  var reconnectDelay = 1000;
@@ -18,6 +23,64 @@ var connectTimeoutId = null;
18
23
  var connectOverlay = null;
19
24
  var hasConnectedOnce = false;
20
25
 
26
+ // The connect overlay is a full-viewport opaque panel. Revealing it for a
27
+ // reconnect that resolves in under a second reads as the whole screen
28
+ // blinking, so after the first successful connection it is only revealed once
29
+ // a disconnect has actually persisted. The status dot carries the state
30
+ // immediately and without covering anything.
31
+ var OVERLAY_GRACE_MS = 800;
32
+ var overlayGraceTimer = null;
33
+
34
+ // Keeps the socket from looking idle to an intermediary proxy. A proxy resets
35
+ // its upstream read timeout on data flowing back from the server, so this only
36
+ // protects the connection because the server answers with a pong: the project
37
+ // socket via project-connection.js and the slug-less socket via
38
+ // server-global-ws.js. Well under the common 60s proxy read timeout, and one
39
+ // timer per live socket.
40
+ var HEARTBEAT_MS = 25000;
41
+ var heartbeatTimer = null;
42
+ var disconnectedAt = 0;
43
+
44
+ function clearOverlayGrace() {
45
+ if (overlayGraceTimer) {
46
+ clearTimeout(overlayGraceTimer);
47
+ overlayGraceTimer = null;
48
+ }
49
+ }
50
+
51
+ function showOverlayNow() {
52
+ if (!connectOverlay) return;
53
+ if (hasConnectedOnce) {
54
+ var overlayMessage = document.getElementById("connect-overlay-msg");
55
+ if (overlayMessage) overlayMessage.textContent = "Reconnecting to server…";
56
+ }
57
+ connectOverlay.classList.remove("hidden");
58
+ }
59
+
60
+ export function stopHeartbeat() {
61
+ if (heartbeatTimer) {
62
+ clearInterval(heartbeatTimer);
63
+ heartbeatTimer = null;
64
+ }
65
+ }
66
+
67
+ // Started once per live socket. The socket it was started for is captured, so
68
+ // a timer that outlives its socket stops itself instead of writing to a stale
69
+ // connection. The pong the server sends back is what actually keeps a proxy's
70
+ // upstream read timeout from expiring, but a missing or late pong is never
71
+ // treated as a failure: only the socket's own close event drives reconnection.
72
+ export function startHeartbeat(socket) {
73
+ stopHeartbeat();
74
+ if (!socket) return;
75
+ heartbeatTimer = setInterval(function () {
76
+ if (!socket || socket.readyState !== 1 || getWs() !== socket) {
77
+ stopHeartbeat();
78
+ return;
79
+ }
80
+ try { socket.send(JSON.stringify({ type: "ping" })); } catch (e) {}
81
+ }, HEARTBEAT_MS);
82
+ }
83
+
21
84
  export function initConnection() {
22
85
  connectOverlay = document.getElementById("connect-overlay");
23
86
 
@@ -39,18 +102,30 @@ export function initConnection() {
39
102
  if (state.connected !== prev.connected) {
40
103
  var sendBtn = getSendBtn();
41
104
  if (state.connected) {
105
+ // Cancel a pending reveal and hide immediately: a reconnect that beat
106
+ // the grace delay must never flash the overlay at all.
107
+ clearOverlayGrace();
42
108
  hasConnectedOnce = true;
43
109
  if (sendBtn) sendBtn.disabled = false;
44
110
  if (connectOverlay) connectOverlay.classList.add("hidden");
45
111
  var updPill = document.getElementById("update-pill-wrap");
46
112
  if (updPill) updPill.classList.add("hidden");
47
113
  } else {
114
+ // The composer stays disabled while the socket is down because there
115
+ // is no outbound queue: every sender drops on readyState !== 1, so
116
+ // enabling it here would silently discard the message.
48
117
  if (sendBtn) sendBtn.disabled = true;
49
- if (hasConnectedOnce && connectOverlay) {
50
- var overlayMessage = document.getElementById("connect-overlay-msg");
51
- if (overlayMessage) overlayMessage.textContent = "Reconnecting to server…";
118
+ clearOverlayGrace();
119
+ if (!hasConnectedOnce) {
120
+ // First connection of the page: the startup overlay is the intended
121
+ // presentation and appears immediately.
122
+ showOverlayNow();
123
+ } else {
124
+ overlayGraceTimer = setTimeout(function () {
125
+ overlayGraceTimer = null;
126
+ if (!store.get('connected')) showOverlayNow();
127
+ }, OVERLAY_GRACE_MS);
52
128
  }
53
- if (connectOverlay) connectOverlay.classList.remove("hidden");
54
129
  }
55
130
  }
56
131
 
@@ -98,6 +173,10 @@ function onConnected() {
98
173
  try {
99
174
  ws.send(JSON.stringify({ type: "mate_list" }));
100
175
  } catch(e) {}
176
+ requestTools();
177
+ requestHomeDockPreference();
178
+ requestHomeSurfacePreference();
179
+ if (store.get('homeSurfaceLoaded') && !isHomeDebatesSurface()) resumeHomeChat();
101
180
 
102
181
  // If connecting to a mate project, request knowledge list for badge
103
182
  if (store.get('mateProjectSlug')) {
@@ -124,6 +203,9 @@ function onConnected() {
124
203
 
125
204
  export function connect() {
126
205
  var ws = getWs();
206
+ // Tear down the previous socket's heartbeat before a new socket exists, so
207
+ // two sockets can never both be pinging.
208
+ stopHeartbeat();
127
209
  if (ws) { ws.onclose = null; ws.close(); }
128
210
  if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
129
211
 
@@ -143,7 +225,12 @@ export function connect() {
143
225
 
144
226
  newWs.onopen = function () {
145
227
  if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
228
+ if (hasConnectedOnce && disconnectedAt) {
229
+ console.log("[clay] WebSocket reconnected after " + (Date.now() - disconnectedAt) + "ms");
230
+ }
231
+ disconnectedAt = 0;
146
232
  setStatus("connected");
233
+ startHeartbeat(newWs);
147
234
  reconnectDelay = 1000;
148
235
  if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
149
236
 
@@ -166,6 +253,14 @@ export function connect() {
166
253
 
167
254
  newWs.onclose = function (e) {
168
255
  if (connectTimeoutId) { clearTimeout(connectTimeoutId); connectTimeoutId = null; }
256
+ stopHeartbeat();
257
+ disconnectedAt = Date.now();
258
+ // Abnormal closes are the ones worth reporting: a clean close is either a
259
+ // deliberate navigation or a server shutdown the user already knows about.
260
+ if (e && !e.wasClean) {
261
+ console.warn("[clay] WebSocket closed abnormally: code=" + e.code +
262
+ " reason=" + (e.reason || "(none)") + " wasClean=false");
263
+ }
169
264
  closeDmUserPicker();
170
265
  setStatus("disconnected");
171
266
  setActivity(null);