clay-server 3.8.1 → 4.0.0-beta.2

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 (189) hide show
  1. package/lib/ask-user-mcp-server.js +5 -119
  2. package/lib/builtin-mates.js +6 -6
  3. package/lib/claude-hook-installer.js +15 -0
  4. package/lib/clay-history-mcp-server.js +62 -297
  5. package/lib/daemon.js +1 -1
  6. package/lib/debate-model-selection.js +119 -0
  7. package/lib/home-debate-tool-policy.js +164 -0
  8. package/lib/home-response-notifications.js +26 -0
  9. package/lib/mate-creation-mcp-server.js +55 -0
  10. package/lib/mate-ready-creation.js +95 -0
  11. package/lib/mates.js +2 -0
  12. package/lib/notes.js +2 -1
  13. package/lib/project-ask-user.js +64 -0
  14. package/lib/project-capsule-catalog.js +101 -0
  15. package/lib/project-connection.js +4 -0
  16. package/lib/project-debate-proposal.js +133 -17
  17. package/lib/project-debate.js +214 -110
  18. package/lib/project-delegated-follow-up.js +84 -0
  19. package/lib/project-delegated-session.js +53 -0
  20. package/lib/project-filesystem.js +7 -9
  21. package/lib/project-knowledge.js +1 -0
  22. package/lib/project-mate-creation-proposal.js +120 -0
  23. package/lib/project-memory.js +14 -7
  24. package/lib/project-models.js +157 -32
  25. package/lib/project-session-notes.js +2 -2
  26. package/lib/project-session-pair.js +8 -8
  27. package/lib/project-sessions.js +66 -51
  28. package/lib/project-vendor-login.js +397 -0
  29. package/lib/project-worker-proposal.js +25 -25
  30. package/lib/project-workspace-query.js +144 -0
  31. package/lib/project.js +349 -102
  32. package/lib/public/app.js +85 -42
  33. package/lib/public/css/avatar-imprints.css +0 -1
  34. package/lib/public/css/base.css +4 -0
  35. package/lib/public/css/capsule-ui.css +389 -0
  36. package/lib/public/css/command-palette.css +306 -6
  37. package/lib/public/css/home-capsule-library.css +243 -0
  38. package/lib/public/css/home-capsule-source.css +192 -0
  39. package/lib/public/css/home-debate-live.css +146 -0
  40. package/lib/public/css/home-debate-planning.css +125 -0
  41. package/lib/public/css/home-debates-archive.css +281 -0
  42. package/lib/public/css/home-hub.css +896 -405
  43. package/lib/public/css/home-mate-creation.css +34 -0
  44. package/lib/public/css/home-mate-model-picker.css +131 -0
  45. package/lib/public/css/home-mate-settings.css +344 -0
  46. package/lib/public/css/home-session-actions.css +265 -0
  47. package/lib/public/css/home-sidebar.css +667 -0
  48. package/lib/public/css/icon-strip.css +1 -2
  49. package/lib/public/css/mates.css +7 -34
  50. package/lib/public/css/pane.css +1 -1
  51. package/lib/public/css/playbook.css +0 -80
  52. package/lib/public/css/sticky-notes.css +53 -117
  53. package/lib/public/css/tui-attention.css +0 -44
  54. package/lib/public/css/workspace-assignment.css +45 -0
  55. package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
  56. package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
  57. package/lib/public/index.html +93 -74
  58. package/lib/public/modules/app-connection.js +10 -1
  59. package/lib/public/modules/app-dm.js +43 -160
  60. package/lib/public/modules/app-home-hub.js +328 -585
  61. package/lib/public/modules/app-message-cards.js +242 -0
  62. package/lib/public/modules/app-message-router.js +84 -0
  63. package/lib/public/modules/app-messages.js +102 -37
  64. package/lib/public/modules/app-notifications.js +8 -119
  65. package/lib/public/modules/app-projects.js +9 -1
  66. package/lib/public/modules/app-rendering.js +21 -602
  67. package/lib/public/modules/avatar-imprint.js +11 -8
  68. package/lib/public/modules/chat-bubble-renderer.js +152 -0
  69. package/lib/public/modules/chat-render-runtime.js +198 -0
  70. package/lib/public/modules/command-palette.js +225 -436
  71. package/lib/public/modules/dm-render.js +82 -0
  72. package/lib/public/modules/home-capsule-creation-intent.js +31 -0
  73. package/lib/public/modules/home-capsule-library.js +146 -0
  74. package/lib/public/modules/home-capsule-source.js +383 -0
  75. package/lib/public/modules/home-chat-identity.js +35 -0
  76. package/lib/public/modules/home-chat-scroll.js +77 -0
  77. package/lib/public/modules/home-chat-stream-state.js +34 -0
  78. package/lib/public/modules/home-composer-focus.js +25 -0
  79. package/lib/public/modules/home-conversations-sheet.js +179 -0
  80. package/lib/public/modules/home-debate-activity.js +48 -0
  81. package/lib/public/modules/home-debate-controls.js +295 -0
  82. package/lib/public/modules/home-debate-launch.js +41 -0
  83. package/lib/public/modules/home-debate-live.js +284 -0
  84. package/lib/public/modules/home-debate-models.js +73 -0
  85. package/lib/public/modules/home-debate-planning.js +335 -0
  86. package/lib/public/modules/home-debates-archive.js +279 -0
  87. package/lib/public/modules/home-dock-resize.js +74 -0
  88. package/lib/public/modules/home-dock.js +446 -0
  89. package/lib/public/modules/home-mate-chat.js +496 -0
  90. package/lib/public/modules/home-mate-creation.js +109 -0
  91. package/lib/public/modules/home-mate-model-picker.js +281 -0
  92. package/lib/public/modules/home-mate-selection.js +38 -0
  93. package/lib/public/modules/home-mate-settings-menu.js +131 -0
  94. package/lib/public/modules/home-mate-settings.js +383 -0
  95. package/lib/public/modules/home-session-actions.js +373 -0
  96. package/lib/public/modules/home-session-model-confirmation.js +13 -0
  97. package/lib/public/modules/home-shell.js +9 -0
  98. package/lib/public/modules/home-sidebar-chat-list.js +63 -0
  99. package/lib/public/modules/home-sidebar.js +158 -0
  100. package/lib/public/modules/home-sub-surface.js +19 -0
  101. package/lib/public/modules/home-surface-boot.js +68 -0
  102. package/lib/public/modules/home-surface.js +141 -0
  103. package/lib/public/modules/home-tools.js +271 -0
  104. package/lib/public/modules/markdown.js +50 -2
  105. package/lib/public/modules/mate-management.js +86 -0
  106. package/lib/public/modules/mate-wizard.js +0 -7
  107. package/lib/public/modules/mention.js +17 -19
  108. package/lib/public/modules/pane-bridge.js +9 -0
  109. package/lib/public/modules/profile.js +4 -5
  110. package/lib/public/modules/project-settings.js +34 -28
  111. package/lib/public/modules/project-switcher.js +11 -5
  112. package/lib/public/modules/project-workspace-assignment.js +23 -0
  113. package/lib/public/modules/search-clay-chat.js +402 -0
  114. package/lib/public/modules/server-settings.js +14 -12
  115. package/lib/public/modules/session-actions.js +1 -1
  116. package/lib/public/modules/sidebar-mates.js +56 -552
  117. package/lib/public/modules/sidebar-mobile.js +7 -64
  118. package/lib/public/modules/sidebar-presence.js +37 -0
  119. package/lib/public/modules/split-pair-ui.js +13 -13
  120. package/lib/public/modules/split-view.js +7 -0
  121. package/lib/public/modules/sticky-notes.js +7 -6
  122. package/lib/public/modules/tool-input-composition.js +48 -0
  123. package/lib/public/modules/tool-llm-status.js +167 -0
  124. package/lib/public/modules/tool-renderer-advanced.js +285 -0
  125. package/lib/public/modules/tool-renderer-chart.js +158 -0
  126. package/lib/public/modules/tool-renderer-semantics.js +35 -0
  127. package/lib/public/modules/tool-renderer.js +464 -0
  128. package/lib/public/modules/tool-runtime.js +309 -0
  129. package/lib/public/modules/tool-ui-evaluator.js +97 -0
  130. package/lib/public/modules/tool-ui-tree.js +21 -0
  131. package/lib/public/modules/tui-attention.js +10 -0
  132. package/lib/public/modules/user-settings.js +16 -23
  133. package/lib/public/modules/vendor-login.js +287 -0
  134. package/lib/public/modules/worker-proposal.js +2 -2
  135. package/lib/public/modules/workspace-assignment-card.js +149 -0
  136. package/lib/public/modules/workspace-assignment-routing.js +4 -0
  137. package/lib/public/style.css +13 -2
  138. package/lib/runtime-env.js +65 -0
  139. package/lib/sdk-bridge.js +120 -32
  140. package/lib/sdk-message-processor.js +10 -6
  141. package/lib/server-home-capsule-creation.js +36 -0
  142. package/lib/server-home-chat-events.js +287 -0
  143. package/lib/server-home-chat.js +518 -0
  144. package/lib/server-home-clay-entry.js +65 -0
  145. package/lib/server-home-clay-session-links.js +26 -0
  146. package/lib/server-home-debate-planning.js +214 -0
  147. package/lib/server-home-debates.js +137 -0
  148. package/lib/server-home-mate-creation.js +261 -0
  149. package/lib/server-home-models.js +241 -0
  150. package/lib/server-home-preferences.js +61 -0
  151. package/lib/server-mates.js +37 -0
  152. package/lib/server-tools.js +377 -0
  153. package/lib/server.js +111 -59
  154. package/lib/session-pair-mcp-server.js +6 -6
  155. package/lib/sessions.js +18 -3
  156. package/lib/tool-capsule-source.js +142 -0
  157. package/lib/tool-control-mcp-server.js +126 -0
  158. package/lib/tool-llm.js +48 -0
  159. package/lib/tool-storage.js +77 -0
  160. package/lib/tool-ui-spec-advanced.js +82 -0
  161. package/lib/tool-ui-spec.js +261 -0
  162. package/lib/tools-registry.js +286 -0
  163. package/lib/users-home-dock-preferences.js +77 -0
  164. package/lib/users-home-surface-preferences.js +99 -0
  165. package/lib/users-preferences.js +4 -7
  166. package/lib/users.js +12 -0
  167. package/lib/whats-new-content.js +3 -3
  168. package/lib/workspace-assignment-service.js +420 -0
  169. package/lib/workspace-query-mcp-server.js +154 -0
  170. package/lib/workspace-query-service.js +492 -0
  171. package/lib/ws-schema.js +93 -12
  172. package/lib/yoke/adapters/acp.js +2 -1
  173. package/lib/yoke/adapters/antigravity.js +2 -1
  174. package/lib/yoke/adapters/claude-worker.js +11 -4
  175. package/lib/yoke/adapters/claude.js +73 -43
  176. package/lib/yoke/adapters/codex.js +40 -10
  177. package/lib/yoke/adapters/kiro.js +2 -1
  178. package/lib/yoke/claude-user-input.js +38 -0
  179. package/lib/yoke/codex-app-server.js +20 -2
  180. package/lib/yoke/codex-user-input.js +64 -0
  181. package/lib/yoke/complete-once.js +164 -0
  182. package/lib/yoke/index.js +5 -1
  183. package/lib/yoke/interface.js +19 -0
  184. package/lib/yoke/mcp-bridge-server.js +2 -6
  185. package/lib/yoke/user-input.js +254 -0
  186. package/package.json +3 -2
  187. package/lib/public/css/home-chat.css +0 -380
  188. package/lib/public/modules/home-chat.js +0 -438
  189. 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,92 @@
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-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>
141
+ </nav>
142
+ <section class="home-sidebar-section home-sidebar-mate-section" aria-labelledby="home-sidebar-mate-label">
143
+ <div id="home-sidebar-mate-label" class="home-sidebar-label">Mates</div>
144
+ <div id="home-mate-list" class="home-mate-list" role="list" aria-label="Mates"></div>
145
+ </section>
146
+ <section class="home-sidebar-section home-sidebar-recents" aria-labelledby="home-sidebar-recent-label">
147
+ <div class="home-sidebar-recents-heading">
148
+ <div id="home-sidebar-recent-label" class="home-sidebar-label">Chats</div>
149
+ <div class="home-chat-scope" role="group" aria-label="Chat scope">
150
+ <button class="home-chat-scope-option" type="button" data-home-chat-scope="current" aria-pressed="false" aria-controls="home-sidebar-recent-list">Current</button>
151
+ <button class="home-chat-scope-option" type="button" data-home-chat-scope="all" aria-pressed="true" aria-controls="home-sidebar-recent-list">All</button>
152
+ </div>
153
+ </div>
154
+ <div id="home-sidebar-recent-list" class="home-sidebar-recent-list"></div>
155
+ </section>
156
+ </aside>
157
+ <div id="home-workspace" class="home-workspace">
158
+ <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>
159
+ <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>
160
+ <div id="home-conversation-region" class="home-conversation-region">
161
+ <div id="home-mate-chat" class="home-mate-chat">
162
+ <div class="home-mate-chat-stage">
163
+ <section id="home-debates-archive" class="home-debates-archive" aria-labelledby="home-debates-title" hidden>
164
+ <header class="home-debates-header">
165
+ <div>
166
+ <p class="home-debates-eyebrow">Home archive</p>
167
+ <h1 id="home-debates-title" tabindex="-1">Debates</h1>
168
+ <p id="home-debates-summary" class="home-debates-summary" role="status" aria-live="polite">Loading debates…</p>
169
+ </div>
170
+ <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>
171
+ </header>
172
+ <form id="home-debates-topic-form" class="home-debates-topic-form" hidden>
173
+ <label for="home-debates-topic">What should the debate be about?</label>
174
+ <textarea id="home-debates-topic" rows="2" maxlength="1000" required placeholder="Enter a question or topic"></textarea>
175
+ <div class="home-debates-topic-actions">
176
+ <p id="home-debates-topic-status" role="status" aria-live="polite">Press Ctrl or Command + Enter to start.</p>
177
+ <button id="home-debates-topic-cancel" type="button">Cancel</button>
178
+ <button id="home-debates-topic-submit" type="submit">Start debate</button>
179
+ </div>
180
+ </form>
181
+ <div id="home-debates-list" class="home-debates-list" aria-label="Debate archive"></div>
182
+ </section>
183
+ <div class="home-mate-chat-messages" id="home-mate-chat-messages"></div>
184
+ <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>
185
+ <div class="home-mate-chat-composer-frame">
186
+ <div id="home-mate-chat-composer" class="home-mate-chat-composer">
187
+ <textarea id="home-mate-chat-input" rows="1" placeholder="Message"></textarea>
188
+ <button id="home-mate-chat-send" aria-label="Send message"><i data-lucide="arrow-up"></i></button>
189
+ </div>
190
+ <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…">
191
+ <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>
192
+ </div>
193
+ <div id="home-debate-controls-slot" class="home-debate-controls-slot" hidden></div>
194
+ </div>
195
+ <div id="home-mate-chat-suggestions" class="home-mate-chat-suggestions"></div>
196
+ </div>
148
197
  </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
198
  </div>
199
+ <div id="home-dock-backdrop" class="home-dock-backdrop"></div>
200
+ <div id="home-dock-divider" class="home-dock-divider" role="separator" aria-label="Resize Capsules Workbench" aria-orientation="vertical" tabindex="0"></div>
201
+ <section id="home-tool-workbench" class="home-tool-workbench" aria-label="Capsules Workbench">
202
+ <div class="home-dock-header">
203
+ <button id="home-dock-return" class="home-dock-return" type="button"><i data-lucide="arrow-left"></i><span>Return to conversation</span></button>
204
+ <div class="home-dock-switcher" id="home-dock-switcher"></div>
205
+ <div class="home-dock-context" id="home-dock-context" aria-label="Active Capsule actions" hidden></div>
206
+ <div class="home-dock-actions">
207
+ <button id="home-dock-focus" type="button" title="Focus Capsules Workbench" aria-label="Focus Capsules Workbench"><i data-lucide="maximize-2"></i></button>
208
+ <button id="home-dock-collapse" type="button" title="Collapse Capsules Workbench" aria-label="Collapse Capsules Workbench"><i data-lucide="panel-right-close"></i></button>
209
+ </div>
210
+ </div>
211
+ <div class="home-dock-content" id="home-dock-content"></div>
212
+ </section>
189
213
  </div>
190
214
  </div>
191
215
  </div>
@@ -389,7 +413,7 @@
389
413
  <div id="debate-sticky" class="hidden"></div>
390
414
  <div class="status">
391
415
  <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>
416
+ <i data-lucide="bot"></i><span>Add Split Worker</span><i class="session-actions-trigger-chevron" data-lucide="chevron-down"></i>
393
417
  </button>
394
418
  <button type="button" id="header-tui-font-btn" class="header-tui-font-btn hidden" title="Terminal font" aria-label="Terminal font">
395
419
  <i data-lucide="type"></i>
@@ -843,10 +867,7 @@
843
867
  <!-- Environment -->
844
868
  <div class="ps-section" data-section="environment">
845
869
  <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>
870
+ <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
871
  <div class="ps-env-tabs">
851
872
  <button class="ps-env-tab active" data-tab="project">Project</button>
852
873
  <button class="ps-env-tab" data-tab="shared">Shared</button>
@@ -861,7 +882,7 @@
861
882
  </div>
862
883
  </div>
863
884
  <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>
885
+ <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
886
  <div class="ps-env-header">
866
887
  <button class="settings-btn-sm" id="ps-shared-env-add-btn"><i data-lucide="plus"></i> Add Variable</button>
867
888
  <span class="ps-save-status" id="ps-shared-env-save-status"></span>
@@ -1128,8 +1149,8 @@
1128
1149
  <div class="settings-card">
1129
1150
  <label class="settings-toggle-row">
1130
1151
  <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>
1152
+ <span class="settings-label">Mate DMs in projects</span>
1153
+ <div class="settings-hint">Show Mate DM shortcuts in project workspaces. Home, Debates, mentions, and Mate memory stay available.</div>
1133
1154
  </div>
1134
1155
  <input type="checkbox" id="us-mates-enabled">
1135
1156
  <span class="toggle-track"><span class="toggle-thumb"></span></span>
@@ -1372,7 +1393,7 @@
1372
1393
  </div>
1373
1394
  <div class="server-settings-section" data-section="environment">
1374
1395
  <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>
1396
+ <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
1397
  <div class="ps-env-header">
1377
1398
  <button class="settings-btn-sm" id="ss-env-add-btn"><i data-lucide="plus"></i> Add Variable</button>
1378
1399
  <span class="ps-save-status" id="ss-env-save-status"></span>
@@ -1877,7 +1898,7 @@
1877
1898
  <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
1899
  <div class="mate-intro-step"><span class="mate-intro-step-num">3</span> Start talking</div>
1879
1900
  </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>
1901
+ <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
1902
  </div>
1882
1903
  </div>
1883
1904
  <!-- Step 1: Relationship -->
@@ -2282,7 +2303,7 @@
2282
2303
  <script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"></script>
2283
2304
  <script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0/lib/addon-web-links.min.js"></script>
2284
2305
  <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>
2306
+ <script type="module" src="app.js?v=20260902-markdown-boundary1"></script>
2286
2307
  <div id="pwa-install-modal" class="pwa-modal hidden">
2287
2308
  <div class="pwa-modal-backdrop"></div>
2288
2309
  <div class="pwa-modal-card">
@@ -2301,7 +2322,5 @@
2301
2322
  </div>
2302
2323
  </div>
2303
2324
 
2304
- <!-- Clay FAB + popover disabled. Markup intentionally removed; assets
2305
- (home-chat.js / home-chat.css) remain in repo for future re-enable. -->
2306
2325
  </body>
2307
2326
  </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;
@@ -98,6 +103,10 @@ function onConnected() {
98
103
  try {
99
104
  ws.send(JSON.stringify({ type: "mate_list" }));
100
105
  } catch(e) {}
106
+ requestTools();
107
+ requestHomeDockPreference();
108
+ requestHomeSurfacePreference();
109
+ if (store.get('homeSurfaceLoaded') && !isHomeDebatesSurface()) resumeHomeChat();
101
110
 
102
111
  // If connecting to a mate project, request knowledge list for badge
103
112
  if (store.get('mateProjectSlug')) {
@@ -5,13 +5,15 @@ import { store } from './store.js';
5
5
  import { getWs } from './ws-ref.js';
6
6
  import { getMessagesEl, getInputEl } from './dom-refs.js';
7
7
  import { userAvatarUrl, mateAvatarUrl } from './avatar.js';
8
+ import { buildDmMessage, buildDmTypingIndicator } from './dm-render.js';
8
9
  import { connect } from './app-connection.js';
9
10
  import { resetClientState, renderProjectList, getCachedProjects } from './app-projects.js';
10
11
  import { scrollToBottom } from './app-rendering.js';
11
12
  import { autoResize } from './input.js';
12
13
  import { showDebateSticky } from './app-debate-ui.js';
13
14
  import { updateDmBadge, setCurrentDmUser, closeDmUserPicker } from './sidebar-mates.js';
14
- import { hideHomeHub } from './app-home-hub.js';
15
+ import { hideHomeHub, showHomeHub } from './app-home-hub.js';
16
+ import { openHomeChat } from './home-mate-chat.js';
15
17
  import { hideNotes } from './sticky-notes.js';
16
18
  import { showMateSidebar, hideMateSidebar } from './mate-sidebar.js';
17
19
  import { hideKnowledge } from './mate-knowledge.js';
@@ -72,6 +74,17 @@ export function initDm() {
72
74
  }
73
75
 
74
76
  export function openDm(targetUserId, opts) {
77
+ var mates = store.get('cachedMatesList') || [];
78
+ var isMateTarget = typeof targetUserId === "string" && targetUserId.indexOf("mate_") === 0;
79
+ for (var i = 0; i < mates.length && !isMateTarget; i++) {
80
+ if (mates[i] && mates[i].id === targetUserId) isMateTarget = true;
81
+ }
82
+ if (isMateTarget) {
83
+ if (store.get('projectMateDmsEnabled') === false) return;
84
+ showHomeHub();
85
+ openHomeChat(targetUserId);
86
+ return;
87
+ }
75
88
  var ws = getWs();
76
89
  if (!ws || ws.readyState !== 1) return;
77
90
  // Persist DM state for refresh recovery
@@ -138,6 +151,12 @@ function showMateOnboarding(callback) {
138
151
 
139
152
  export function enterDmMode(key, targetUser, messages) {
140
153
  console.log("[DEBUG enterDmMode] key=" + key, "isMate=" + (targetUser && targetUser.isMate), "messages=" + (messages ? messages.length : 0));
154
+ if (targetUser && targetUser.isMate) {
155
+ if (store.get('projectMateDmsEnabled') === false) return;
156
+ showHomeHub();
157
+ openHomeChat(targetUser.id);
158
+ return;
159
+ }
141
160
  var s = store.snap();
142
161
  // Clean up previous DM/mate state before entering new one
143
162
  if (s.dmMode) {
@@ -163,20 +182,6 @@ export function enterDmMode(key, targetUser, messages) {
163
182
 
164
183
  store.set({ dmMode: true, dmKey: key, dmTargetUser: targetUser });
165
184
 
166
- // Notify server of active mate DM (server-side presence tracking)
167
- // IMPORTANT: set_mate_dm must go to the MAIN project, not a mate project WS.
168
- // When switching between mates, ws points to the current mate project,
169
- // so we defer sending set_mate_dm until we reconnect to the main project's context.
170
- // The server will also receive it via the mate project's onDmMessage handler,
171
- // but the presence should only be stored on the main project slug.
172
- if (targetUser && targetUser.isMate) {
173
- var ws = getWs();
174
- // Send to the current WS only if it's the main project (not another mate)
175
- if (!store.get('mateProjectSlug') && ws && ws.readyState === 1) {
176
- try { ws.send(JSON.stringify({ type: "set_mate_dm", mateId: targetUser.id })); } catch(e) {}
177
- }
178
- }
179
-
180
185
  // Clear unread for this user
181
186
  if (targetUser) {
182
187
  store.get('dmUnread')[targetUser.id] = 0;
@@ -380,76 +385,23 @@ export function exitDmMode(skipProjectSwitch) {
380
385
 
381
386
  export function handleMateCreatedInApp(mate, msg) {
382
387
  if (!mate) return;
383
- var newMates = store.get('cachedMatesList').concat([mate]);
388
+ var newMates = (store.get('cachedMatesList') || []).filter(function (existing) { return existing && existing.id !== mate.id; }).concat([mate]);
384
389
  var updates = { cachedMatesList: newMates };
385
390
  if (msg && msg.availableBuiltins) updates.cachedAvailableBuiltins = msg.availableBuiltins;
386
391
  if (msg && msg.dmFavorites) updates.cachedDmFavorites = msg.dmFavorites;
387
392
  store.set(updates);
388
393
  // renderUserStrip is handled by the store subscriber
389
394
  // Built-in mates handle their own onboarding via CLAUDE.md, skip auto-interview
390
- if (!mate.builtinKey) {
395
+ if (!mate.builtinKey && !(msg && msg.interviewComplete === true)) {
391
396
  store.set({ pendingMateInterview: mate });
392
397
  }
393
- openDm(mate.id);
394
- }
395
-
396
- export function renderAvailableBuiltins(builtins) {
397
- // Append deleted built-in mates to the mates list in the picker
398
- var matesList = document.querySelector(".dm-mates-list");
399
- if (!matesList) return;
400
- if (!builtins || builtins.length === 0) return;
401
-
402
- for (var i = 0; i < builtins.length; i++) {
403
- (function (b) {
404
- var item = document.createElement("div");
405
- item.className = "dm-user-picker-item dm-user-picker-builtin-item";
406
- item.style.opacity = "0.5";
407
-
408
- var av = document.createElement("img");
409
- av.className = "dm-user-picker-avatar";
410
- av.src = b.avatarCustom || "";
411
- av.alt = b.displayName;
412
- item.appendChild(av);
413
-
414
- var nameWrap = document.createElement("div");
415
- nameWrap.style.cssText = "flex:1;min-width:0;";
416
- var nameEl = document.createElement("span");
417
- nameEl.className = "dm-user-picker-name";
418
- nameEl.textContent = b.displayName;
419
- nameWrap.appendChild(nameEl);
420
- var bioEl = document.createElement("div");
421
- bioEl.style.cssText = "font-size:11px;color:var(--text-dimmer);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;";
422
- bioEl.textContent = "Deleted";
423
- nameWrap.appendChild(bioEl);
424
- item.appendChild(nameWrap);
425
-
426
- var addBtn = document.createElement("button");
427
- addBtn.style.cssText = "border:none;background:none;cursor:pointer;padding:2px 6px;color:var(--accent, #6366f1);font-size:12px;font-weight:600;";
428
- addBtn.textContent = "+ Add";
429
- addBtn.title = "Re-add " + b.displayName;
430
- addBtn.addEventListener("click", function (e) {
431
- e.stopPropagation();
432
- var ws = getWs();
433
- if (ws && ws.readyState === 1) {
434
- ws.send(JSON.stringify({ type: "mate_readd_builtin", builtinKey: b.key }));
435
- }
436
- closeDmUserPicker();
437
- });
438
- item.appendChild(addBtn);
439
-
440
- item.addEventListener("click", function () {
441
- var ws = getWs();
442
- if (ws && ws.readyState === 1) {
443
- ws.send(JSON.stringify({ type: "mate_readd_builtin", builtinKey: b.key }));
444
- }
445
- closeDmUserPicker();
446
- });
447
-
448
- matesList.appendChild(item);
449
- })(builtins[i]);
398
+ if (!(msg && msg.interviewComplete === true)) {
399
+ showHomeHub();
400
+ openHomeChat(mate.id);
450
401
  }
451
402
  }
452
403
 
404
+
453
405
  export function buildMateInterviewPrompt(mate) {
454
406
  var sd = mate.seedData || {};
455
407
  var parts = [];
@@ -536,78 +488,20 @@ export function appendDmMessage(msg) {
536
488
  var s = store.snap();
537
489
  if (s.dmMode) s.dmMessageCache.push(msg);
538
490
  var isMe = msg.from === s.myUserId;
539
- var d = new Date(msg.ts);
540
- var timeStr = d.getHours().toString().padStart(2, "0") + ":" + d.getMinutes().toString().padStart(2, "0");
541
-
542
491
  var messagesEl = getMessagesEl();
543
- // Check if we can compact (same sender as previous, within 5 min)
544
- var prev = messagesEl.lastElementChild;
545
- var compact = false;
546
- if (prev && prev.dataset.from === msg.from) {
547
- var prevTs = parseInt(prev.dataset.ts || "0", 10);
548
- if (msg.ts - prevTs < 300000) compact = true;
549
- }
550
-
551
- var div = document.createElement("div");
552
- div.className = "dm-msg" + (compact ? " dm-msg-compact" : "");
553
- div.dataset.from = msg.from;
554
- div.dataset.ts = msg.ts;
555
-
556
- if (compact) {
557
- // Compact: just hover-time + text, no avatar/name
558
- var hoverTime = document.createElement("span");
559
- hoverTime.className = "dm-msg-hover-time";
560
- hoverTime.textContent = timeStr;
561
- div.appendChild(hoverTime);
562
-
563
- var body = document.createElement("div");
564
- body.className = "dm-msg-body";
565
- body.textContent = msg.text;
566
- div.appendChild(body);
567
- } else {
568
- // Full: avatar + header(name, time) + text
569
- var avatar = document.createElement("img");
570
- avatar.className = "dm-msg-avatar";
571
- if (isMe) {
572
- var myUser = s.cachedAllUsers.find(function (u) { return u.id === s.myUserId; });
573
- avatar.src = userAvatarUrl(myUser || { id: s.myUserId }, 36);
574
- } else if (s.dmTargetUser) {
575
- avatar.src = userAvatarUrl(s.dmTargetUser, 36);
576
- }
577
- div.appendChild(avatar);
578
-
579
- var content = document.createElement("div");
580
- content.className = "dm-msg-content";
581
-
582
- var header = document.createElement("div");
583
- header.className = "dm-msg-header";
584
-
585
- var name = document.createElement("span");
586
- name.className = "dm-msg-name";
587
- if (isMe) {
588
- var mu = s.cachedAllUsers.find(function (u) { return u.id === s.myUserId; });
589
- name.textContent = mu ? mu.displayName : "Me";
590
- } else {
591
- name.textContent = s.dmTargetUser ? s.dmTargetUser.displayName : "User";
592
- }
593
- header.appendChild(name);
594
-
595
- var time = document.createElement("span");
596
- time.className = "dm-msg-time";
597
- time.textContent = timeStr;
598
- header.appendChild(time);
599
-
600
- content.appendChild(header);
601
-
602
- var body = document.createElement("div");
603
- body.className = "dm-msg-body";
604
- body.textContent = msg.text;
605
- content.appendChild(body);
606
-
607
- div.appendChild(content);
608
- }
609
-
610
- messagesEl.appendChild(div);
492
+ var myUser = s.cachedAllUsers.find(function (user) { return user.id === s.myUserId; });
493
+ var avatarUrl = isMe
494
+ ? userAvatarUrl(myUser || { id: s.myUserId }, 36)
495
+ : (s.dmTargetUser ? userAvatarUrl(s.dmTargetUser, 36) : "");
496
+ var displayName = isMe
497
+ ? (myUser ? myUser.displayName : "Me")
498
+ : (s.dmTargetUser ? s.dmTargetUser.displayName : "User");
499
+ messagesEl.appendChild(buildDmMessage(msg, {
500
+ container: messagesEl,
501
+ isMe: isMe,
502
+ avatarUrl: avatarUrl,
503
+ displayName: displayName,
504
+ }));
611
505
  }
612
506
 
613
507
  export function showDmTypingIndicator(typing) {
@@ -620,22 +514,11 @@ export function showDmTypingIndicator(typing) {
620
514
  var dmTargetUser = store.get('dmTargetUser');
621
515
  if (!dmTargetUser) return;
622
516
 
623
- var div = document.createElement("div");
624
- div.id = "dm-typing-indicator";
625
- div.className = "dm-msg dm-typing-indicator";
626
-
627
- var avatar = document.createElement("img");
628
- avatar.className = "dm-msg-avatar";
629
- avatar.src = userAvatarUrl(dmTargetUser, 36);
630
- div.appendChild(avatar);
631
-
632
- var dots = document.createElement("div");
633
- dots.className = "dm-typing-dots";
634
- dots.innerHTML = "<span></span><span></span><span></span>";
635
- div.appendChild(dots);
636
-
637
517
  var messagesEl = getMessagesEl();
638
- messagesEl.appendChild(div);
518
+ messagesEl.appendChild(buildDmTypingIndicator({
519
+ id: "dm-typing-indicator",
520
+ avatarUrl: userAvatarUrl(dmTargetUser, 36),
521
+ }));
639
522
  scrollToBottom();
640
523
 
641
524
  // Auto-hide after 5s in case stop signal is missed