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
@@ -0,0 +1,74 @@
1
+ // Pointer and keyboard resizing for the desktop home tool workbench.
2
+
3
+ var initialized = false;
4
+ var dragging = false;
5
+ var pointerOffset = 0;
6
+
7
+ export function clampHomeDockWidth(width) {
8
+ var workspace = document.getElementById("home-workspace");
9
+ var available = workspace ? workspace.getBoundingClientRect().width : window.innerWidth;
10
+ var maximum = Math.max(420, Math.min(window.innerWidth * 0.58, available - 504));
11
+ return Math.round(Math.max(420, Math.min(maximum, width)));
12
+ }
13
+
14
+ export function defaultHomeDockWidth() {
15
+ return clampHomeDockWidth(Math.max(520, Math.min(window.innerWidth * 0.46, 760)));
16
+ }
17
+
18
+ export function applyHomeDockWidth(width) {
19
+ var workspace = document.getElementById("home-workspace");
20
+ if (!workspace) return null;
21
+ var resolved = clampHomeDockWidth(typeof width === "number" ? width : defaultHomeDockWidth());
22
+ workspace.style.setProperty("--home-dock-width", resolved + "px");
23
+ return resolved;
24
+ }
25
+
26
+ function dispatchWidth(type, width) {
27
+ window.dispatchEvent(new CustomEvent(type, { detail: { width: applyHomeDockWidth(width) } }));
28
+ }
29
+
30
+ function handlePointerMove(event) {
31
+ if (!dragging) return;
32
+ var workbench = document.getElementById("home-tool-workbench");
33
+ if (!workbench) return;
34
+ var rect = workbench.getBoundingClientRect();
35
+ dispatchWidth("clay:home-dock-width-preview", rect.right - event.clientX - pointerOffset);
36
+ }
37
+
38
+ function finishPointerResize(event) {
39
+ if (!dragging) return;
40
+ handlePointerMove(event);
41
+ dragging = false;
42
+ pointerOffset = 0;
43
+ document.body.classList.remove("home-dock-resizing");
44
+ window.removeEventListener("pointermove", handlePointerMove);
45
+ window.removeEventListener("pointerup", finishPointerResize);
46
+ window.removeEventListener("pointercancel", finishPointerResize);
47
+ var workbench = document.getElementById("home-tool-workbench");
48
+ dispatchWidth("clay:home-dock-width-commit", workbench ? workbench.getBoundingClientRect().width : defaultHomeDockWidth());
49
+ }
50
+
51
+ export function initHomeDockResize() {
52
+ if (initialized) return;
53
+ initialized = true;
54
+ var divider = document.getElementById("home-dock-divider");
55
+ if (!divider) return;
56
+ divider.addEventListener("pointerdown", function (event) {
57
+ if (window.innerWidth < 1180 || event.button !== 0) return;
58
+ event.preventDefault();
59
+ var workbench = document.getElementById("home-tool-workbench");
60
+ pointerOffset = workbench ? workbench.getBoundingClientRect().left - event.clientX : 0;
61
+ dragging = true;
62
+ document.body.classList.add("home-dock-resizing");
63
+ window.addEventListener("pointermove", handlePointerMove);
64
+ window.addEventListener("pointerup", finishPointerResize);
65
+ window.addEventListener("pointercancel", finishPointerResize);
66
+ });
67
+ divider.addEventListener("keydown", function (event) {
68
+ if (window.innerWidth < 1180 || (event.key !== "ArrowLeft" && event.key !== "ArrowRight")) return;
69
+ event.preventDefault();
70
+ var workbench = document.getElementById("home-tool-workbench");
71
+ var current = workbench ? workbench.getBoundingClientRect().width : defaultHomeDockWidth();
72
+ dispatchWidth("clay:home-dock-width-commit", current + (event.key === "ArrowLeft" ? 24 : -24));
73
+ });
74
+ }
@@ -0,0 +1,446 @@
1
+ // Home dock registry, three-state navigation, and preference synchronization.
2
+
3
+ import { store } from './store.js';
4
+ import { getWs } from './ws-ref.js';
5
+ import { iconHtml, refreshIcons } from './icons.js';
6
+ import { escapeHtml } from './utils.js';
7
+ import { applyHomeDockWidth, initHomeDockResize } from './home-dock-resize.js';
8
+ import { renderHomeCapsuleLibrary } from './home-capsule-library.js';
9
+
10
+ var tools = [];
11
+ var toolsById = Object.create(null);
12
+ var mountedToolId = null;
13
+ var pulseTimers = Object.create(null);
14
+ var initialized = false;
15
+ var resizeSaveTimer = null;
16
+ var backstageView = null;
17
+ var backstageReturnTarget = null;
18
+
19
+ function clearBackstageView() {
20
+ var previous = backstageView;
21
+ backstageView = null;
22
+ backstageReturnTarget = null;
23
+ if (previous && typeof previous.onClose === "function") previous.onClose();
24
+ }
25
+
26
+ function send(message) {
27
+ var ws = getWs();
28
+ if (!ws || ws.readyState !== 1) return false;
29
+ ws.send(JSON.stringify(message));
30
+ return true;
31
+ }
32
+
33
+ function activeTool() {
34
+ var activeId = store.get('dockActiveToolId');
35
+ return activeId && toolsById[activeId] ? toolsById[activeId] : tools[0] || null;
36
+ }
37
+
38
+ function preference() {
39
+ return {
40
+ dockOpen: store.get('dockOpen') === true,
41
+ dockFocus: store.get('dockOpen') === true && store.get('dockFocus') === true,
42
+ dockWidth: store.get('dockWidth'),
43
+ activeToolId: store.get('dockActiveToolId') || null,
44
+ };
45
+ }
46
+
47
+ function persistDock() {
48
+ send({ type: "home_dock_set", preference: preference() });
49
+ }
50
+
51
+ function hasVisibleEscapeLayer() {
52
+ var selector = '[role="dialog"], [role="menu"], .profile-popover, .project-ctx-menu, .cmd-palette, [id$="-modal"], [id$="-overlay"], .panel-fullscreen';
53
+ var layers = document.querySelectorAll(selector);
54
+ for (var i = 0; i < layers.length; i++) {
55
+ if (!layers[i].classList.contains("hidden") && layers[i].getClientRects().length > 0) return true;
56
+ }
57
+ return false;
58
+ }
59
+
60
+ function hasEditableEscapeTarget(target) {
61
+ if (!target || typeof target.matches !== "function") return false;
62
+ if (target.matches('input, textarea, select, [contenteditable="true"]')) return true;
63
+ return typeof target.closest === "function" && Boolean(target.closest('[contenteditable="true"]'));
64
+ }
65
+
66
+ function renderToolIdentity(tool) {
67
+ return '<span class="home-dock-tab-icon">' + iconHtml(tool.lucideIcon || "box") + '</span>'
68
+ + '<span class="home-dock-tab-label">' + escapeHtml(tool.name) + '</span>';
69
+ }
70
+
71
+ function appendCapsuleHomeTab(switcherEl, active) {
72
+ var tab = document.createElement("button");
73
+ tab.type = "button";
74
+ tab.className = "home-dock-tool is-capsule-home" + (active ? " active" : "");
75
+ tab.dataset.dockHome = "true";
76
+ tab.setAttribute("aria-label", "Capsule Home");
77
+ if (active) tab.setAttribute("aria-current", "page");
78
+ tab.innerHTML = renderToolIdentity({ name: "Home", lucideIcon: "house" });
79
+ tab.addEventListener("click", openHomeCapsuleLibrary);
80
+ switcherEl.appendChild(tab);
81
+ }
82
+
83
+ function clearDockContext(contextEl) {
84
+ var mounted = mountedToolId ? toolsById[mountedToolId] : null;
85
+ if (mounted && typeof mounted.onChromeHide === "function") mounted.onChromeHide();
86
+ contextEl.innerHTML = "";
87
+ contextEl.hidden = true;
88
+ }
89
+
90
+ function syncDockTrigger() {
91
+ var button = document.getElementById("home-tools-btn");
92
+ var label = document.getElementById("home-tools-label");
93
+ var activity = document.getElementById("home-tools-activity");
94
+ var hasActivity = store.get('dockHasActivity') === true;
95
+ if (label) label.textContent = "Capsules";
96
+ if (activity) activity.classList.toggle("is-active", hasActivity);
97
+ if (button) {
98
+ button.setAttribute("aria-expanded", store.get('dockOpen') === true ? "true" : "false");
99
+ button.setAttribute("aria-label", hasActivity ? "Capsules, new activity" : "Capsules");
100
+ }
101
+ }
102
+
103
+ function syncDockState() {
104
+ var hub = document.getElementById("home-hub");
105
+ if (!hub) return;
106
+ var open = store.get('dockOpen') === true;
107
+ var focus = open && store.get('dockFocus') === true;
108
+ hub.classList.toggle("dock-open", open);
109
+ hub.classList.toggle("dock-split", open && !focus);
110
+ hub.classList.toggle("dock-focus", focus);
111
+ applyHomeDockWidth(store.get('dockWidth'));
112
+ syncDockTrigger();
113
+ }
114
+
115
+ function setDockState(patch, persist) {
116
+ store.set(patch);
117
+ syncDockState();
118
+ renderDock();
119
+ if (persist) persistDock();
120
+ }
121
+
122
+ function activateTool(toolId) {
123
+ clearBackstageView();
124
+ setDockState({
125
+ dockActiveToolId: toolId,
126
+ dockOpen: true,
127
+ dockFocus: store.get('dockFocus') === true,
128
+ dockLibraryOpen: false,
129
+ dockBackstageOpen: false,
130
+ dockHasActivity: false,
131
+ dockActivityToolId: null,
132
+ }, true);
133
+ }
134
+
135
+ export function openHomeDock(toolId) {
136
+ clearBackstageView();
137
+ var current = activeTool();
138
+ var requested = toolId && toolsById[toolId] ? toolId : (current ? current.id : null);
139
+ setDockState({ dockActiveToolId: requested, dockOpen: true, dockFocus: false, dockLibraryOpen: !requested, dockBackstageOpen: false, dockHasActivity: false, dockActivityToolId: null }, true);
140
+ }
141
+
142
+ function focusActiveCapsuleTab() {
143
+ var activeTab = document.querySelector("#home-dock-switcher .home-dock-tool.active");
144
+ if (activeTab) activeTab.focus();
145
+ }
146
+
147
+ function openLibraryCapsule(toolId) {
148
+ activateTool(toolId);
149
+ focusActiveCapsuleTab();
150
+ }
151
+
152
+ function openHomeCapsuleLibrary() {
153
+ clearBackstageView();
154
+ setDockState({
155
+ dockActiveToolId: null,
156
+ dockOpen: true,
157
+ dockFocus: false,
158
+ dockLibraryOpen: true,
159
+ dockBackstageOpen: false,
160
+ dockHasActivity: false,
161
+ dockActivityToolId: null,
162
+ }, true);
163
+ var title = document.getElementById("home-capsule-library-title");
164
+ if (title) title.focus();
165
+ }
166
+
167
+ export function openHomeCapsules() {
168
+ var lastActiveId = store.get('dockActiveToolId');
169
+ if (lastActiveId && toolsById[lastActiveId]) {
170
+ openHomeDock(lastActiveId);
171
+ focusActiveCapsuleTab();
172
+ return;
173
+ }
174
+ openHomeCapsuleLibrary();
175
+ }
176
+
177
+ export function toggleHomeCapsules() {
178
+ if (store.get('dockOpen')) closeHomeDock();
179
+ else openHomeCapsules();
180
+ }
181
+
182
+ export function openHomeBackstage(view) {
183
+ if (!view || typeof view.render !== "function") return;
184
+ clearBackstageView();
185
+ backstageView = view;
186
+ var activeId = store.get('dockActiveToolId');
187
+ backstageReturnTarget = activeId && toolsById[activeId]
188
+ ? { type: "capsule", toolId: activeId }
189
+ : { type: "library" };
190
+ setDockState({
191
+ dockOpen: true,
192
+ dockFocus: false,
193
+ dockLibraryOpen: backstageReturnTarget.type === "library",
194
+ dockBackstageOpen: true,
195
+ }, true);
196
+ var focusTarget = document.querySelector("#home-dock-content [data-home-backstage-focus]");
197
+ if (focusTarget) focusTarget.focus();
198
+ }
199
+
200
+ export function closeHomeBackstage() {
201
+ var returnTarget = backstageReturnTarget;
202
+ clearBackstageView();
203
+ var returnToCapsule = returnTarget && returnTarget.type === "capsule" && toolsById[returnTarget.toolId];
204
+ setDockState({
205
+ dockActiveToolId: returnToCapsule ? returnTarget.toolId : store.get('dockActiveToolId'),
206
+ dockLibraryOpen: !returnToCapsule,
207
+ dockBackstageOpen: false,
208
+ }, false);
209
+ if (!returnToCapsule) {
210
+ var libraryTitle = document.getElementById("home-capsule-library-title");
211
+ if (libraryTitle) libraryTitle.focus();
212
+ return;
213
+ }
214
+ focusActiveCapsuleTab();
215
+ }
216
+
217
+ export function closeHomeDock() {
218
+ clearBackstageView();
219
+ setDockState({ dockOpen: false, dockFocus: false, dockBackstageOpen: false }, true);
220
+ var homeControl = document.getElementById("home-tools-btn");
221
+ if (homeControl && homeControl.getClientRects().length) homeControl.focus({ preventScroll: true });
222
+ else {
223
+ var sidebarControl = document.getElementById("home-sidebar-expand");
224
+ if (sidebarControl && sidebarControl.getClientRects().length) sidebarControl.focus({ preventScroll: true });
225
+ }
226
+ }
227
+
228
+ export function focusHomeDock() {
229
+ if (!store.get('dockOpen')) return;
230
+ setDockState({ dockFocus: true }, true);
231
+ }
232
+
233
+ export function returnHomeDockToSplit() {
234
+ if (!store.get('dockOpen')) return;
235
+ setDockState({ dockFocus: false }, true);
236
+ }
237
+
238
+ function handleReturnHomeDock() {
239
+ if (window.innerWidth <= 768) {
240
+ closeHomeDock();
241
+ return;
242
+ }
243
+ returnHomeDockToSplit();
244
+ }
245
+
246
+ export function resetHomeDockFocus() {
247
+ if (!store.get('dockFocus')) return;
248
+ store.set({ dockFocus: false });
249
+ syncDockState();
250
+ }
251
+
252
+ export function requestHomeDockPreference() {
253
+ send({ type: "home_dock_get" });
254
+ }
255
+
256
+ export function handleHomeDockState(msg) {
257
+ if (!msg) return;
258
+ if (msg.error || !msg.preference) {
259
+ store.set({ homeDockPreferenceLoaded: true });
260
+ return;
261
+ }
262
+ var saved = msg.preference;
263
+ store.set({
264
+ dockOpen: saved.dockOpen === true,
265
+ homeDockPreferenceLoaded: true,
266
+ dockWidth: typeof saved.dockWidth === "number" ? saved.dockWidth : null,
267
+ dockActiveToolId: saved.activeToolId || null,
268
+ dockFocus: saved.dockOpen === true && saved.dockFocus === true,
269
+ dockLibraryOpen: saved.dockOpen === true && !saved.activeToolId,
270
+ });
271
+ syncDockState();
272
+ if (store.get('homeToolRegistryLoaded') && reconcileDockActiveTool()) return;
273
+ renderDock();
274
+ }
275
+
276
+ export function reconcileDockActiveTool() {
277
+ var activeToolId = store.get('dockActiveToolId');
278
+ if (!activeToolId || toolsById[activeToolId]) return false;
279
+ store.set({
280
+ dockActiveToolId: null,
281
+ dockLibraryOpen: store.get('dockOpen') === true,
282
+ });
283
+ syncDockState();
284
+ renderDock();
285
+ persistDock();
286
+ return true;
287
+ }
288
+
289
+ export function markDockToolChanged(toolId) {
290
+ if (store.get('dockOpen')) {
291
+ pulseDockTool(toolId);
292
+ return;
293
+ }
294
+ store.set({ dockHasActivity: true, dockActivityToolId: toolId || null });
295
+ syncDockTrigger();
296
+ }
297
+
298
+ export function registerDockTool(tool) {
299
+ if (!tool || !tool.id || !tool.name || typeof tool.render !== "function") return;
300
+ if (toolsById[tool.id]) {
301
+ var existingIndex = tools.indexOf(toolsById[tool.id]);
302
+ if (existingIndex !== -1) tools[existingIndex] = tool;
303
+ } else {
304
+ tools.push(tool);
305
+ }
306
+ toolsById[tool.id] = tool;
307
+ syncDockTrigger();
308
+ }
309
+
310
+ export function unregisterDockTool(toolId) {
311
+ var tool = toolsById[toolId];
312
+ if (!tool) return;
313
+ var wasMounted = mountedToolId === toolId;
314
+ if (wasMounted && typeof tool.onHide === "function") tool.onHide();
315
+ var index = tools.indexOf(tool);
316
+ if (index !== -1) tools.splice(index, 1);
317
+ delete toolsById[toolId];
318
+ if (store.get('dockActiveToolId') === toolId) {
319
+ store.set({
320
+ dockActiveToolId: null,
321
+ dockLibraryOpen: store.get('dockOpen') === true,
322
+ });
323
+ persistDock();
324
+ }
325
+ if (wasMounted) mountedToolId = null;
326
+ syncDockTrigger();
327
+ }
328
+
329
+ export function pulseDockTool(toolId) {
330
+ if (!store.get('dockOpen')) {
331
+ store.set({ dockHasActivity: true, dockActivityToolId: toolId || null });
332
+ syncDockTrigger();
333
+ return;
334
+ }
335
+ var tabs = document.querySelectorAll("[data-dock-tool-id]");
336
+ for (var i = 0; i < tabs.length; i++) {
337
+ if (tabs[i].dataset.dockToolId !== toolId) continue;
338
+ tabs[i].classList.remove("mate-acted");
339
+ void tabs[i].offsetWidth;
340
+ tabs[i].classList.add("mate-acted");
341
+ }
342
+ if (pulseTimers[toolId]) clearTimeout(pulseTimers[toolId]);
343
+ pulseTimers[toolId] = setTimeout(function () {
344
+ var current = document.querySelectorAll("[data-dock-tool-id]");
345
+ for (var j = 0; j < current.length; j++) {
346
+ if (current[j].dataset.dockToolId === toolId) current[j].classList.remove("mate-acted");
347
+ }
348
+ delete pulseTimers[toolId];
349
+ }, 1600);
350
+ }
351
+
352
+ export function renderDock() {
353
+ var switcherEl = document.getElementById("home-dock-switcher");
354
+ var contextEl = document.getElementById("home-dock-context");
355
+ var contentEl = document.getElementById("home-dock-content");
356
+ if (!switcherEl || !contextEl || !contentEl) return;
357
+ var backstageOpen = store.get('dockBackstageOpen') === true && !!backstageView;
358
+ var libraryOpen = store.get('dockLibraryOpen') === true;
359
+ var selected = backstageOpen || libraryOpen ? null : activeTool();
360
+ switcherEl.innerHTML = "";
361
+ clearDockContext(contextEl);
362
+ appendCapsuleHomeTab(switcherEl, libraryOpen && !backstageOpen);
363
+ for (var i = 0; i < tools.length; i++) {
364
+ (function (tool) {
365
+ var tab = document.createElement("button");
366
+ tab.type = "button";
367
+ tab.className = "home-dock-tool" + (selected && tool.id === selected.id ? " active" : "");
368
+ tab.dataset.dockToolId = tool.id;
369
+ if (selected && tool.id === selected.id) tab.setAttribute("aria-current", "page");
370
+ tab.innerHTML = renderToolIdentity(tool);
371
+ tab.addEventListener("click", function () { activateTool(tool.id); });
372
+ switcherEl.appendChild(tab);
373
+ })(tools[i]);
374
+ }
375
+ if (backstageOpen) {
376
+ contentEl.innerHTML = "";
377
+ backstageView.render(contentEl, closeHomeBackstage);
378
+ syncDockTrigger();
379
+ refreshIcons();
380
+ return;
381
+ }
382
+ if (libraryOpen) {
383
+ if (mountedToolId) {
384
+ var mounted = toolsById[mountedToolId];
385
+ if (mounted && typeof mounted.onHide === "function") mounted.onHide();
386
+ }
387
+ mountedToolId = null;
388
+ contentEl.innerHTML = "";
389
+ renderHomeCapsuleLibrary(contentEl, store.get('installedTools') || [], openLibraryCapsule);
390
+ syncDockTrigger();
391
+ refreshIcons();
392
+ return;
393
+ }
394
+ if (!selected) {
395
+ contentEl.innerHTML = "";
396
+ syncDockTrigger();
397
+ return;
398
+ }
399
+ if (mountedToolId && mountedToolId !== selected.id) {
400
+ var previous = toolsById[mountedToolId];
401
+ if (previous && typeof previous.onHide === "function") previous.onHide();
402
+ }
403
+ mountedToolId = selected.id;
404
+ contentEl.innerHTML = "";
405
+ contextEl.hidden = false;
406
+ selected.render(contentEl, contextEl);
407
+ if (typeof selected.onShow === "function") selected.onShow();
408
+ syncDockTrigger();
409
+ refreshIcons();
410
+ }
411
+
412
+ export function initHomeDock() {
413
+ if (initialized) return;
414
+ initialized = true;
415
+ initHomeDockResize();
416
+ document.getElementById("home-dock-collapse").addEventListener("click", closeHomeDock);
417
+ document.getElementById("home-dock-focus").addEventListener("click", focusHomeDock);
418
+ document.getElementById("home-dock-return").addEventListener("click", handleReturnHomeDock);
419
+ document.getElementById("home-dock-backdrop").addEventListener("click", closeHomeDock);
420
+ window.addEventListener("clay:home-dock-width-preview", function (event) {
421
+ if (event.detail && typeof event.detail.width === "number") store.set({ dockWidth: event.detail.width });
422
+ });
423
+ window.addEventListener("clay:home-dock-width-commit", function (event) {
424
+ if (!event.detail || typeof event.detail.width !== "number") return;
425
+ store.set({ dockWidth: event.detail.width });
426
+ if (resizeSaveTimer) clearTimeout(resizeSaveTimer);
427
+ resizeSaveTimer = setTimeout(persistDock, 180);
428
+ });
429
+ window.addEventListener("resize", syncDockState);
430
+ document.addEventListener("keydown", function (event) {
431
+ if (event.key !== "Escape" || !document.body.classList.contains("home-active")) return;
432
+ if (hasVisibleEscapeLayer()) return;
433
+ if (store.get('dockOpen') && store.get('dockBackstageOpen') && backstageView) {
434
+ event.preventDefault();
435
+ event.stopPropagation();
436
+ closeHomeBackstage();
437
+ return;
438
+ }
439
+ if (hasEditableEscapeTarget(event.target)) return;
440
+ if (!store.get('dockFocus')) return;
441
+ event.preventDefault();
442
+ event.stopPropagation();
443
+ returnHomeDockToSplit();
444
+ }, true);
445
+ syncDockState();
446
+ }