clay-server 5.2.0-beta.5 → 5.2.0-beta.7

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 (246) hide show
  1. package/lib/claude-hook-installer.js +1 -267
  2. package/lib/claude-jsonl-watcher.js +1 -204
  3. package/lib/clay-control-presentation-binding.js +96 -0
  4. package/lib/clay-control-presentation.js +128 -0
  5. package/lib/clay-control-target-projection.js +26 -0
  6. package/lib/clay-mate-chat.js +1 -0
  7. package/lib/clay-mate-knowledge.js +1 -1
  8. package/lib/clay-product-control-tools.js +1 -1
  9. package/lib/clay-product-control.js +22 -12
  10. package/lib/clay-project-records.js +2 -1
  11. package/lib/clay-scheduling.js +1 -1
  12. package/lib/clay-screen-controls.js +13 -5
  13. package/lib/clay-skill-install.js +1 -33
  14. package/lib/clay-workspace-controls.js +2 -1
  15. package/lib/cli-sessions.js +1 -300
  16. package/lib/codex-defaults.js +1 -28
  17. package/lib/context-usage.js +3 -2
  18. package/lib/contextual-screen-snapshot.js +38 -0
  19. package/lib/daemon.js +5 -55
  20. package/lib/default-ai-runtime.js +4 -8
  21. package/lib/email-mcp-server.js +1 -1
  22. package/lib/kiro-defaults.js +1 -22
  23. package/lib/mate-context-service.js +138 -0
  24. package/lib/mate-context-tools.js +21 -0
  25. package/lib/mcp-proxy.js +2 -32
  26. package/lib/mcp-query-bridge.js +1 -1
  27. package/lib/mcp-source-adapters.js +1 -91
  28. package/lib/mcp-source-context.js +1 -42
  29. package/lib/mcp-source-discovery.js +1 -169
  30. package/lib/mcp-source-plugins.js +1 -68
  31. package/lib/mcp-source-restrictions.js +1 -47
  32. package/lib/mcp-tool-policy.js +1 -26
  33. package/lib/os-user-diagnostics.js +2 -4
  34. package/lib/os-users.js +4 -65
  35. package/lib/project-connection.js +14 -10
  36. package/lib/project-control-git-view.js +12 -0
  37. package/lib/project-filesystem.js +5 -1
  38. package/lib/project-http.js +7 -4
  39. package/lib/project-mcp.js +2 -2
  40. package/lib/project-notifications.js +5 -4
  41. package/lib/project-pair-result-delivery.js +2 -2
  42. package/lib/project-pair-usage.js +12 -13
  43. package/lib/project-pending-message-queue.js +3 -1
  44. package/lib/project-product-control.js +3 -1
  45. package/lib/project-scheduled-messages.js +4 -4
  46. package/lib/project-scheduled-task-control.js +1 -1
  47. package/lib/project-session-document.js +20 -5
  48. package/lib/project-session-history-actions.js +5 -3
  49. package/lib/project-session-pair.js +1 -1
  50. package/lib/project-session-runtime-actions.js +2 -1
  51. package/lib/project-session-spawn.js +2 -3
  52. package/lib/project-session-vendor.js +2 -1
  53. package/lib/project-sessions.js +18 -26
  54. package/lib/project-shared-browser.js +22 -5
  55. package/lib/project-studio-presentation.js +58 -0
  56. package/lib/project-user-message.js +37 -0
  57. package/lib/project-vendor-login.js +6 -36
  58. package/lib/project-workspace-query.js +11 -1
  59. package/lib/project.js +24 -7
  60. package/lib/public/app.js +25 -0
  61. package/lib/public/appearance-bootstrap.js +2 -0
  62. package/lib/public/css/contextual-clay.css +240 -0
  63. package/lib/public/css/messages.css +6 -2
  64. package/lib/public/modules/app-favicon.js +18 -9
  65. package/lib/public/modules/app-header.js +4 -2
  66. package/lib/public/modules/app-loop-ui.js +2 -0
  67. package/lib/public/modules/app-message-router.js +5 -1
  68. package/lib/public/modules/app-messages.js +50 -6
  69. package/lib/public/modules/app-notifications.js +11 -5
  70. package/lib/public/modules/app-panels.js +61 -123
  71. package/lib/public/modules/app-projects.js +3 -0
  72. package/lib/public/modules/app-rate-limit.js +7 -27
  73. package/lib/public/modules/chat-render-runtime.js +3 -0
  74. package/lib/public/modules/clay-control-activity.js +214 -0
  75. package/lib/public/modules/clay-control-copy.js +36 -0
  76. package/lib/public/modules/clay-control-detail-targets.js +44 -0
  77. package/lib/public/modules/clay-control-object-targets.js +52 -0
  78. package/lib/public/modules/clay-control-target-visibility.js +12 -0
  79. package/lib/public/modules/clay-control-targets.js +44 -0
  80. package/lib/public/modules/clay-navigation-render.js +52 -0
  81. package/lib/public/modules/clay-owner-navigation.js +11 -2
  82. package/lib/public/modules/clay-session-links.js +31 -0
  83. package/lib/public/modules/clay-studio-bridge.js +20 -0
  84. package/lib/public/modules/clay-studio-document.js +67 -0
  85. package/lib/public/modules/clay-studio-render.js +144 -0
  86. package/lib/public/modules/clay-tool-presentation.js +4 -0
  87. package/lib/public/modules/command-palette.js +26 -31
  88. package/lib/public/modules/contextual-ask-session.js +26 -0
  89. package/lib/public/modules/contextual-clay-geometry.js +155 -0
  90. package/lib/public/modules/contextual-clay-session.js +130 -0
  91. package/lib/public/modules/contextual-clay-workspace.js +157 -0
  92. package/lib/public/modules/contextual-clay.js +237 -0
  93. package/lib/public/modules/contextual-composer.js +91 -0
  94. package/lib/public/modules/contextual-mate-context.js +115 -0
  95. package/lib/public/modules/contextual-mate-hint.js +40 -0
  96. package/lib/public/modules/contextual-mate-identity.js +23 -0
  97. package/lib/public/modules/contextual-mate-sessions.js +134 -0
  98. package/lib/public/modules/contextual-search.js +137 -0
  99. package/lib/public/modules/contextual-session-citations.js +58 -0
  100. package/lib/public/modules/filebrowser.js +20 -1
  101. package/lib/public/modules/generation-stop.js +8 -5
  102. package/lib/public/modules/git-panel.js +3 -1
  103. package/lib/public/modules/icon-strip-tooltip.js +2 -1
  104. package/lib/public/modules/input.js +35 -1
  105. package/lib/public/modules/issues-render.js +3 -2
  106. package/lib/public/modules/knowledge-db-workbench.js +4 -4
  107. package/lib/public/modules/markdown.js +2 -34
  108. package/lib/public/modules/mate-knowledge-workbench.js +1 -1
  109. package/lib/public/modules/mcp-connection-view.js +1 -1
  110. package/lib/public/modules/message-delivery.js +10 -0
  111. package/lib/public/modules/pane-bridge.js +2 -2
  112. package/lib/public/modules/pending-message-queue.js +1 -0
  113. package/lib/public/modules/permission-control.js +5 -4
  114. package/lib/public/modules/product-review.js +26 -0
  115. package/lib/public/modules/project-chat-identity.js +13 -4
  116. package/lib/public/modules/project-logs-render.js +3 -0
  117. package/lib/public/modules/project-mate-navigation.js +58 -21
  118. package/lib/public/modules/scheduled-tasks.js +2 -0
  119. package/lib/public/modules/scheduler.js +2 -0
  120. package/lib/public/modules/search-clay-chat.js +5 -454
  121. package/lib/public/modules/session-create-form.js +10 -10
  122. package/lib/public/modules/settings-defaults.js +27 -28
  123. package/lib/public/modules/shared-browser.js +2 -0
  124. package/lib/public/modules/sidebar-mobile.js +4 -3
  125. package/lib/public/modules/sidebar-projects.js +1 -0
  126. package/lib/public/modules/sidebar-sessions.js +1 -0
  127. package/lib/public/modules/split-view.js +7 -16
  128. package/lib/public/modules/terminal.js +9 -0
  129. package/lib/public/modules/tools.js +6 -2
  130. package/lib/public/modules/tui-grab.js +1 -2
  131. package/lib/public/modules/vendor-login-browser.js +5 -3
  132. package/lib/public/modules/vendor-login.js +2 -2
  133. package/lib/public/modules/vendor-priority.js +15 -1
  134. package/lib/public/modules/wireframe-workbench.js +5 -2
  135. package/lib/public/muse-avatar.svg +4 -0
  136. package/lib/public/style.css +2 -0
  137. package/lib/safe-bash-commands.js +3 -45
  138. package/lib/sdk-bridge.js +131 -395
  139. package/lib/sdk-foreground-admission.js +16 -0
  140. package/lib/sdk-mcp-descriptors.js +2 -37
  141. package/lib/sdk-message-processor.js +50 -17
  142. package/lib/sdk-quota-snapshot.js +1 -1
  143. package/lib/sdk-response-recovery.js +1 -155
  144. package/lib/sdk-worker.js +2 -677
  145. package/lib/server-contextual-clay-settings.js +40 -0
  146. package/lib/server-contextual-mate-sessions.js +70 -0
  147. package/lib/server-home-chat.js +7 -1
  148. package/lib/server-home-clay-entry.js +23 -4
  149. package/lib/server-home-clay-session-links.js +12 -0
  150. package/lib/server-owner-ui.js +49 -8
  151. package/lib/server-settings.js +2 -0
  152. package/lib/server.js +18 -1
  153. package/lib/session-fork-history.js +21 -0
  154. package/lib/session-hygiene.js +3 -35
  155. package/lib/session-permission-mode.js +4 -3
  156. package/lib/session-skill-scope.js +11 -0
  157. package/lib/sessions.js +24 -89
  158. package/lib/terminal-manager.js +18 -11
  159. package/lib/tool-llm.js +1 -1
  160. package/lib/tui-transcript-index.js +1 -132
  161. package/lib/users-contextual-clay-preferences.js +31 -0
  162. package/lib/users.js +3 -0
  163. package/lib/vendor-login-browser.js +1 -11
  164. package/lib/workspace-assignment-service.js +25 -0
  165. package/lib/workspace-query-mcp-server.js +1 -1
  166. package/lib/ws-request.js +1 -0
  167. package/lib/ws-schema.js +10 -0
  168. package/lib/yoke/acp-agent-profiles.js +5 -3
  169. package/lib/yoke/adapters/antigravity.js +3 -14
  170. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  171. package/lib/yoke/adapters/claude.js +7 -42
  172. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  173. package/lib/yoke/adapters/codex.js +1 -0
  174. package/lib/yoke/adapters/kiro.js +3 -1
  175. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  176. package/lib/yoke/adapters/muse.js +122 -0
  177. package/lib/yoke/auth-events.js +17 -0
  178. package/lib/yoke/claude-hook-installer.js +271 -0
  179. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  180. package/lib/yoke/claude-maintenance.js +55 -0
  181. package/lib/yoke/claude-permission-patterns.js +53 -0
  182. package/lib/yoke/claude-response-recovery.js +155 -0
  183. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  184. package/lib/yoke/clay-skill-install.js +33 -0
  185. package/lib/yoke/cli-sessions.js +300 -0
  186. package/lib/yoke/codex-app-server.js +7 -12
  187. package/lib/yoke/configuration.js +13 -0
  188. package/lib/yoke/discovery.js +70 -0
  189. package/lib/yoke/errors.js +8 -0
  190. package/lib/yoke/host-environment.js +7 -0
  191. package/lib/yoke/index.js +9 -51
  192. package/lib/yoke/interface.js +116 -0
  193. package/lib/yoke/kiro-acp-server.js +5 -5
  194. package/lib/yoke/legacy-sessions.js +89 -0
  195. package/lib/yoke/login-protocol.js +25 -0
  196. package/lib/yoke/maintenance.js +12 -0
  197. package/lib/yoke/mcp-proxy.js +32 -0
  198. package/lib/yoke/mcp-source-adapters.js +91 -0
  199. package/lib/yoke/mcp-source-context.js +42 -0
  200. package/lib/yoke/mcp-source-discovery.js +169 -0
  201. package/lib/yoke/mcp-source-plugins.js +68 -0
  202. package/lib/yoke/mcp-source-restrictions.js +47 -0
  203. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  204. package/lib/yoke/model-preferences.js +6 -0
  205. package/lib/yoke/muse-artifacts.js +36 -0
  206. package/lib/yoke/muse-controls.js +50 -0
  207. package/lib/yoke/muse-input.js +64 -0
  208. package/lib/yoke/muse-items.js +157 -0
  209. package/lib/yoke/muse-policy.js +52 -0
  210. package/lib/yoke/muse-query.js +428 -0
  211. package/lib/yoke/muse-runtime.js +211 -0
  212. package/lib/yoke/muse-services.js +79 -0
  213. package/lib/yoke/muse-skills.js +79 -0
  214. package/lib/yoke/muse-turns.js +71 -0
  215. package/lib/yoke/options/acp.js +2 -0
  216. package/lib/yoke/options/antigravity.js +2 -0
  217. package/lib/yoke/options/claude.js +21 -0
  218. package/lib/yoke/options/codex-defaults.js +29 -0
  219. package/lib/yoke/options/codex-settings.js +21 -0
  220. package/lib/yoke/options/codex.js +6 -0
  221. package/lib/yoke/options/kiro-defaults.js +22 -0
  222. package/lib/yoke/options/kiro.js +5 -0
  223. package/lib/yoke/options/muse.js +5 -0
  224. package/lib/yoke/provider-contract.js +5 -0
  225. package/lib/yoke/providers/antigravity-executable.js +8 -0
  226. package/lib/yoke/providers/claude-executable.js +40 -0
  227. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  228. package/lib/yoke/providers/claude-process.js +97 -0
  229. package/lib/yoke/providers/claude-provision.js +75 -0
  230. package/lib/yoke/providers/codex-errors.js +8 -0
  231. package/lib/yoke/providers/muse-executable.js +17 -0
  232. package/lib/yoke/provisioning.js +6 -0
  233. package/lib/yoke/query-options.js +10 -0
  234. package/lib/yoke/response-recovery.js +41 -0
  235. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  236. package/lib/yoke/sdk-server-factory.js +7 -0
  237. package/lib/yoke/session-history.js +8 -0
  238. package/lib/yoke/session-tool-transport.js +31 -13
  239. package/lib/yoke/settings.js +23 -0
  240. package/lib/yoke/source-locations.js +4 -0
  241. package/lib/yoke/title-query.js +18 -7
  242. package/lib/yoke/tui-transcript-index.js +132 -0
  243. package/lib/yoke/usage.js +48 -0
  244. package/lib/yoke/user-input.js +13 -0
  245. package/lib/yoke/vendor-registry.js +81 -1
  246. package/package.json +3 -2
@@ -2,9 +2,9 @@
2
2
  // Used by both server-settings.js and project-settings.js
3
3
 
4
4
  export var MODE_OPTIONS = [
5
- { value: "default", label: "Default", desc: "Claude asks for permission before running tools and editing files." },
6
- { value: "plan", label: "Plan", desc: "Claude creates a plan first and asks for approval before making changes." },
7
- { value: "acceptEdits", label: "Auto-accept edits", desc: "File edits are applied automatically. Claude still asks before running commands." },
5
+ { value: "default", label: "Default", desc: "The agent asks for permission before running tools and editing files." },
6
+ { value: "plan", label: "Plan", desc: "The agent creates a plan first and asks for approval before making changes." },
7
+ { value: "acceptEdits", label: "Auto-accept edits", desc: "File edits are applied automatically. The agent still asks before running commands." },
8
8
  ];
9
9
 
10
10
  export var EFFORT_LEVELS = [
@@ -16,29 +16,17 @@ export var EFFORT_LEVELS = [
16
16
 
17
17
  export var THINKING_OPTIONS = [
18
18
  { value: "disabled", label: "Off", desc: "Disable extended thinking." },
19
- { value: "adaptive", label: "Adaptive", desc: "Claude decides when to use extended thinking." },
19
+ { value: "adaptive", label: "Adaptive", desc: "The agent decides when to use extended thinking." },
20
20
  { value: "budget", label: "Budget", desc: "Set a token budget for extended thinking." },
21
21
  ];
22
22
 
23
- export var MODEL_DESCRIPTIONS = {
24
- "default": "Automatically selects the best model for the task.",
25
- "sonnet": "Fast and capable. Great balance of speed and intelligence.",
26
- "haiku": "Fastest model. Best for quick tasks and simple questions.",
27
- "opus": "Most powerful model. Best for complex reasoning and analysis.",
28
- };
29
-
30
23
  export function getModelDesc(model) {
31
- if (!model) return "";
32
- var lower = (model.value || model).toLowerCase();
33
- for (var key in MODEL_DESCRIPTIONS) {
34
- if (lower.indexOf(key) !== -1) return MODEL_DESCRIPTIONS[key];
35
- }
36
- return "";
24
+ return model && typeof model === "object" && typeof model.description === "string" ? model.description : "";
37
25
  }
38
26
 
27
+ // Compatibility name for the retired beta control; model metadata owns support.
39
28
  export function isSonnetModel(model) {
40
- if (!model) return false;
41
- return model.toLowerCase().indexOf("sonnet") !== -1;
29
+ return !!(model && typeof model === "object" && model.supportsBetaContext === true);
42
30
  }
43
31
 
44
32
  // --- Render functions ---
@@ -75,7 +63,7 @@ export function renderModelList(prefix, opts) {
75
63
  nameSpan.textContent = label;
76
64
  item.appendChild(nameSpan);
77
65
 
78
- var desc = getModelDesc(value);
66
+ var desc = getModelDesc(m);
79
67
  if (desc) {
80
68
  var descSpan = document.createElement("span");
81
69
  descSpan.className = "settings-model-desc";
@@ -106,7 +94,9 @@ export function renderModeList(prefix, opts) {
106
94
  var currentMode = opts.currentMode || "default";
107
95
  listEl.innerHTML = "";
108
96
 
109
- for (var i = 0; i < MODE_OPTIONS.length; i++) {
97
+ var modes = (opts.configuration || {}).permissionModes || [];
98
+ if (listEl.parentElement) listEl.parentElement.style.display = modes.length ? "" : "none";
99
+ for (var i = 0; i < modes.length; i++) {
110
100
  (function (opt) {
111
101
  var item = document.createElement("div");
112
102
  item.className = "settings-model-item" + (opt.value === currentMode ? " active" : "");
@@ -129,7 +119,7 @@ export function renderModeList(prefix, opts) {
129
119
  });
130
120
 
131
121
  listEl.appendChild(item);
132
- })(MODE_OPTIONS[i]);
122
+ })(modes[i]);
133
123
  }
134
124
  }
135
125
 
@@ -143,7 +133,12 @@ export function renderEffortBar(prefix, opts) {
143
133
  var currentEffort = opts.currentEffort || "medium";
144
134
  bar.innerHTML = "";
145
135
 
146
- for (var i = 0; i < EFFORT_LEVELS.length; i++) {
136
+ var levels = opts.effortLevels || [];
137
+ var model = (opts.models || []).find(function (item) { return item.value === opts.currentModel; });
138
+ if (model && model.supportsEffort === false) levels = [];
139
+ else if (model && Array.isArray(model.supportedEffortLevels)) levels = model.supportedEffortLevels;
140
+ if (bar.parentElement) bar.parentElement.style.display = levels.length ? "" : "none";
141
+ for (var i = 0; i < levels.length; i++) {
147
142
  (function (lvl) {
148
143
  var btn = document.createElement("button");
149
144
  btn.className = "settings-btn-option" + (lvl.value === currentEffort ? " active" : "");
@@ -156,7 +151,7 @@ export function renderEffortBar(prefix, opts) {
156
151
  btn.classList.add("active");
157
152
  });
158
153
  bar.appendChild(btn);
159
- })(EFFORT_LEVELS[i]);
154
+ })({ value: levels[i], desc: (EFFORT_LEVELS.find(function (item) { return item.value === levels[i]; }) || {}).desc || "" });
160
155
  }
161
156
  }
162
157
 
@@ -173,7 +168,10 @@ export function renderThinkingBar(prefix, opts) {
173
168
  var budgetInput = document.getElementById(prefix + "-thinking-budget");
174
169
  bar.innerHTML = "";
175
170
 
176
- for (var i = 0; i < THINKING_OPTIONS.length; i++) {
171
+ var thinking = (opts.configuration || {}).thinking;
172
+ if (bar.parentElement) bar.parentElement.style.display = thinking ? "" : "none";
173
+ var thinkingOptions = thinking ? THINKING_OPTIONS.filter(function(opt) { return thinking.options.indexOf(opt.value) >= 0; }) : [];
174
+ for (var i = 0; i < thinkingOptions.length; i++) {
177
175
  (function (opt) {
178
176
  var btn = document.createElement("button");
179
177
  btn.className = "settings-btn-option" + (opt.value === currentThinking ? " active" : "");
@@ -191,10 +189,10 @@ export function renderThinkingBar(prefix, opts) {
191
189
  if (budgetRow) budgetRow.style.display = opt.value === "budget" ? "" : "none";
192
190
  });
193
191
  bar.appendChild(btn);
194
- })(THINKING_OPTIONS[i]);
192
+ })(thinkingOptions[i]);
195
193
  }
196
194
 
197
- if (budgetRow) budgetRow.style.display = currentThinking === "budget" ? "" : "none";
195
+ if (budgetRow) budgetRow.style.display = thinking && currentThinking === "budget" ? "" : "none";
198
196
  if (budgetInput) {
199
197
  budgetInput.value = currentBudget;
200
198
  budgetInput.addEventListener("change", function () {
@@ -212,7 +210,8 @@ export function renderBetaCard(prefix, opts) {
212
210
  var model = opts.overrideModel || opts.currentModel || "";
213
211
  var card = document.getElementById(prefix + "-beta-card");
214
212
  if (card) {
215
- card.style.display = isSonnetModel(model) ? "" : "none";
213
+ var descriptor = (opts.models || []).find(function(item) { return item.value === model; });
214
+ card.style.display = isSonnetModel(descriptor) ? "" : "none";
216
215
  }
217
216
 
218
217
  var toggle = document.getElementById(prefix + "-beta-1m");
@@ -1,3 +1,4 @@
1
+ import { registerStudioPaint } from './clay-studio-render.js';
1
2
  import { browserLinkTarget, initBrowserLinks } from './clay-browser-links.js';
2
3
  import { browserSettingsHtml, bindBrowserSettings, renderBrowserSettings, closeBrowserSettings, handleBrowserSettingsMessage } from './shared-browser-settings.js';
3
4
  import { renderBrowserTabs } from './shared-browser-tabs.js';
@@ -229,6 +230,7 @@ export function handleSharedBrowserMessage(msg) {
229
230
  var canvas = panel().querySelector('canvas'); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight;
230
231
  canvas.getContext('2d').drawImage(image, 0, 0);
231
232
  ui({ decoding: false, hasFrame: true }); render();
233
+ registerStudioPaint(msg, canvas, null, canvas);
232
234
  }
233
235
  };
234
236
  image.onerror = function () { if (store.get('activeSessionId') === sessionId) ui({ decoding: false }); };
@@ -1,4 +1,5 @@
1
- import { openMateWorkspace, isMateWorkspace } from './project-mate-navigation.js';
1
+ import { contextualMate } from './contextual-mate-identity.js';
2
+ import { activateContextualMate, isMateWorkspace } from './project-mate-navigation.js';
2
3
  import { appendGithubWork } from './session-github.js';
3
4
  // sidebar-mobile.js - Mobile sheet overlays, tab bar, and mobile-specific rendering
4
5
  // Extracted from sidebar.js (PR-38)
@@ -258,7 +259,7 @@ function renderSheetSessions(listEl) {
258
259
  }
259
260
 
260
261
  var visibleChipMates = getCachedMates().filter(function (m) {
261
- return m && !m.archived;
262
+ return m && !m.archived && contextualMate(m.id);
262
263
  });
263
264
  var sortedChipMates = visibleChipMates.sort(function (a, b) {
264
265
  var aBuiltin = a.builtinKey ? 1 : 0;
@@ -327,7 +328,7 @@ function renderSheetSessions(listEl) {
327
328
  renderMobileSessionsInto(sessionListEl);
328
329
  } else if (type === "mate") {
329
330
  closeMobileSheet();
330
- openMateWorkspace(mateId);
331
+ activateContextualMate(mateId);
331
332
  }
332
333
 
333
334
  refreshIcons();
@@ -822,6 +822,7 @@ function createIconItem(p, currentSlug) {
822
822
  var el = document.createElement("a");
823
823
  var isActive = p.slug === currentSlug && !currentDmUserId;
824
824
  el.className = "icon-strip-item" + (isActive ? " active" : "");
825
+ el.dataset.controlRuntime = p.controlRuntimeId || "";
825
826
  el.href = "/p/" + p.slug + "/";
826
827
  el.dataset.slug = p.slug;
827
828
 
@@ -826,6 +826,7 @@ function renderSessionItem(s, options) {
826
826
  el.className = "session-item" + (displaySession.active ? " active" : "") + (isMatch ? " search-match" : "");
827
827
  if (itemOptions.worker) el.classList.add("session-worker-item");
828
828
  el.dataset.sessionId = s.id;
829
+ el.dataset.controlSessionOrigin = s.sessionOriginId || '';
829
830
 
830
831
  var textSpan = document.createElement("span");
831
832
  textSpan.className = "session-item-text";
@@ -1,3 +1,5 @@
1
+ import { adoptDocumentSource } from './clay-studio-document.js';
2
+ import { trustedStudioFrame } from './clay-studio-render.js';
1
3
  import { handlePaneBrowserMessage } from './pane-browser-bridge.js';
2
4
  import { openWireframe } from './wireframe-workbench.js';
3
5
  // Two-pane iframe shell for the split-view spike.
@@ -144,22 +146,11 @@ function handlePaneMessage(event) {
144
146
  if (event.origin !== window.location.origin) return;
145
147
  var msg = event.data;
146
148
  if (!msg || !host) return;
147
- if (msg.type === "clay-pane-present-wireframe") {
148
- var frames = host.querySelectorAll(".split-pane-frame");
149
- var split = store.get('splitPanes');
150
- var trusted = Array.prototype.some.call(frames, function (frame) {
151
- if (frame.contentWindow !== event.source || frame.dataset.projectSlug !== msg.projectSlug || String(frame.dataset.sessionId) !== String(msg.sessionId) || msg.projectSlug !== store.get('currentSlug')) return false;
152
- return split && split.panes.some(function (pane) {
153
- var expected = new URL('/p/' + encodeURIComponent(pane.slug) + '/?pane=1&session=' + encodeURIComponent(pane.sessionId), window.location.href).href;
154
- return pane.slug === msg.projectSlug && String(pane.sessionId) === String(msg.sessionId) && frame.src === expected;
155
- });
156
- });
157
- if (trusted && msg.message) openWireframe(msg.message);
158
- return;
159
- }
160
- if (msg.type === "clay-pane-present-markdown") {
161
- var present = msg.message;
162
- if (present) presentMarkdownEdit(present);
149
+ if (msg.type === "clay-pane-present-wireframe" || msg.type === "clay-pane-present-markdown") {
150
+ if (msg.message && !msg.message.controlPresentation && trustedStudioFrame(event, msg)) {
151
+ if (msg.type === "clay-pane-present-wireframe") openWireframe(msg.message);
152
+ else { adoptDocumentSource(event, msg, trustedStudioFrame(event, msg)); presentMarkdownEdit(msg.message); }
153
+ }
163
154
  return;
164
155
  }
165
156
  // Both panes can report auth_required for their own sessions. The shell runs
@@ -1,3 +1,4 @@
1
+ import { store } from './store.js';
1
2
  import { iconHtml, refreshIcons } from './icons.js';
2
3
  import { closeSidebar } from './sidebar.js';
3
4
  import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
@@ -538,6 +539,8 @@ function renderTabBar() {
538
539
  (function (t) {
539
540
  var el = document.createElement("div");
540
541
  el.className = "terminal-tab";
542
+ el.dataset.controlTerminalId = String(t.id);
543
+ el.dataset.controlRuntime = store.get("controlRuntimeId") || "";
541
544
  if (t.id === activeTabId) el.classList.add("active");
542
545
  if (t.exited) el.classList.add("exited");
543
546
 
@@ -696,6 +699,7 @@ function updateTerminalBadge() {
696
699
  // --- Handle server messages ---
697
700
 
698
701
  export function handleTermList(msg) {
702
+ store.set({ clayControlTerminalViews: (msg.terminals || []).map(function (item) { return { id: item.id, identity: item.controlIdentity, revision: item.controlRevision, runtimeId: store.get('controlRuntimeId') }; }) });
699
703
  // TUI session terminals are owned by session-tui-view.js and must not
700
704
  // appear in the bottom terminal panel. Filter them out before any tab
701
705
  // bookkeeping so the panel never tries to render or auto-attach them.
@@ -762,7 +766,11 @@ export function handleTermCreated(msg) {
762
766
  }
763
767
  }
764
768
 
769
+ export function handleTerminalProjection(msg) {
770
+ if (msg.controlIdentity && msg.controlRevision) store.set({ clayControlTerminalViews: (store.get('clayControlTerminalViews') || []).map(function (item) { return item.id === msg.id && item.identity === msg.controlIdentity ? Object.assign({}, item, { revision: msg.controlRevision }) : item; }) });
771
+ }
765
772
  export function handleTermOutput(msg) {
773
+ handleTerminalProjection(msg);
766
774
  if (!msg.id) return;
767
775
  var tab = tabs.get(msg.id);
768
776
  if (tab && tab.xterm && msg.data) {
@@ -771,6 +779,7 @@ export function handleTermOutput(msg) {
771
779
  }
772
780
 
773
781
  export function handleTermResized(msg) {
782
+ handleTerminalProjection(msg);
774
783
  if (!msg.id) return;
775
784
  var tab = tabs.get(msg.id);
776
785
  if (tab && tab.xterm && msg.cols > 0 && msg.rows > 0) {
@@ -1,3 +1,4 @@
1
+ import { renderProductReview } from './product-review.js';
1
2
  import { clayToolGroupSummary } from './clay-tool-presentation.js';
2
3
  import { applyClayToolItem, applyClayToolResult, finishClayToolItem, findEndedClayTool, clayToolResultGroup, bindToolGroupDisclosure, syncToolGroupDisclosure, syncClayToolGroup } from './clay-tool-activity.js';
3
4
  import { escapeHtml, copyToClipboard } from './utils.js';
@@ -176,7 +177,8 @@ function updateToolGroupHeader(group) {
176
177
  }
177
178
 
178
179
  function isPlanFile(filePath) {
179
- return filePath && filePath.indexOf(".claude/plans/") !== -1;
180
+ var info = (store.get('vendorInfo') || {})[store.get('currentVendor')] || {};
181
+ return !!filePath && (info.planPathSegments || []).some(function (segment) { return filePath.indexOf(segment) !== -1; });
180
182
  }
181
183
 
182
184
  export function toolSummary(name, input) {
@@ -297,6 +299,7 @@ export function renderAskUserQuestion(toolId, input) {
297
299
  var qText = document.createElement("div");
298
300
  qText.className = "ask-user-question-text";
299
301
  qText.textContent = q.question || "";
302
+ if (renderProductReview(qText, q)) qDiv.dataset.answerLabel = q.review.action;
300
303
  qDiv.appendChild(qText);
301
304
 
302
305
  var optionsDiv = document.createElement("div");
@@ -475,7 +478,8 @@ function showAnswerSummary(container, questions, answers) {
475
478
  var row = document.createElement("div");
476
479
  row.className = "ask-user-answer-row";
477
480
  var qi = parseInt(key, 10);
478
- var label = (questions && questions[qi] && questions[qi].question) ? questions[qi].question : "Answer";
481
+ var questionNode = container.querySelectorAll(".ask-user-question")[qi];
482
+ var label = questionNode && questionNode.dataset.answerLabel || (questions && questions[qi] && (questions[qi].header || questions[qi].question)) || "Answer";
479
483
  row.innerHTML = '<span class="ask-user-answer-label">' + escapeHtml(label) + '</span>' +
480
484
  '<span class="ask-user-answer-value">' + escapeHtml(String(answers[key])) + '</span>';
481
485
  summary.appendChild(row);
@@ -635,10 +635,9 @@ export function attachTuiGrab(xterm, containerEl, localId, opts) {
635
635
  if (opts && opts.vendor) {
636
636
  var vendors = store.get('vendorInfo') || {};
637
637
  var info = vendors[opts.vendor];
638
- var legacyTuiVendors = ["claude"];
639
638
  var supportsTui = info
640
639
  ? Array.isArray(info.sessionModes) && info.sessionModes.indexOf("tui") !== -1
641
- : legacyTuiVendors.indexOf(opts.vendor) !== -1;
640
+ : false;
642
641
  if (!supportsTui) return;
643
642
  }
644
643
 
@@ -1,3 +1,4 @@
1
+ import { escapeHtml } from './utils.js';
1
2
  import { store } from './store.js';
2
3
  import { getWs } from './ws-ref.js';
3
4
  import { iconHtml, refreshIcons } from './icons.js';
@@ -33,7 +34,8 @@ export function openLoginBrowser(msg) {
33
34
  }
34
35
  closeLoginBrowser();
35
36
  var isMcp = msg.kind === 'mcp';
36
- var title = isMcp ? 'Sign in to ' + (msg.label || 'MCP server') : (msg.vendor === "codex" ? "Sign in to Codex" : "Sign in to Claude");
37
+ var provider = (store.get('vendorInfo') || {})[msg.vendor] || {};
38
+ var title = 'Sign in to ' + (isMcp ? msg.label || 'MCP server' : provider.displayName || msg.vendor || 'Provider');
37
39
  store.set({ vendorLoginBrowser: {
38
40
  browserId: msg.browserId, vendor: msg.vendor, kind: msg.kind, connectionId: msg.connectionId, slug: msg.slug || store.get('currentSlug'),
39
41
  previousFocus: document.activeElement, decoding: false, pointerY: null, pointerId: null, mouseDown: false, moveTimer: null, pendingMove: null, resizeObserver: null, requestedSize: null, phase: "loading",
@@ -43,7 +45,7 @@ export function openLoginBrowser(msg) {
43
45
  dialog.className = "login-browser";
44
46
  dialog.setAttribute("aria-labelledby", "login-browser-title");
45
47
  dialog.innerHTML = '<header class="login-browser-header">' +
46
- '<img class="login-browser-vendor" src="/' + (msg.vendor === "codex" ? 'codex-avatar.png' : 'claude-code-avatar.png') + '" alt="">' +
48
+ '<img class="login-browser-vendor" src="' + escapeHtml(provider.avatar || '') + '" alt="">' +
47
49
  '<div class="login-browser-heading"><h2 id="login-browser-title"></h2>' +
48
50
  '<span class="login-browser-origin">Opening sign-in page…</span></div>' +
49
51
  '<div class="login-browser-actions">' +
@@ -56,7 +58,7 @@ export function openLoginBrowser(msg) {
56
58
  '<div class="login-browser-loading"><span class="login-browser-spinner" aria-hidden="true"></span><strong>Opening your sign-in page</strong><span>This may take a moment.</span></div>' +
57
59
  '<textarea class="login-browser-keyboard" aria-label="Type into the remote sign-in page" autocomplete="off" autocapitalize="off" spellcheck="false"></textarea></div>' +
58
60
  '<footer class="login-browser-footer"><div class="login-browser-info"><div class="login-browser-status"><span class="login-browser-status-dot" aria-hidden="true"></span><p role="status">Preparing sign-in…</p></div>' +
59
- '<p class="login-browser-privacy">Browser cookies are discarded when this session ends. You stay signed in to ' + (msg.vendor === "codex" ? 'Codex' : 'Claude') + ' after this browser closes.</p></div>' +
61
+ '<p class="login-browser-privacy">Browser cookies are discarded when this session ends. You stay signed in to ' + escapeHtml(provider.displayName || msg.vendor || 'the provider') + ' after this browser closes.</p></div>' +
60
62
  '<button type="button" data-action="terminal" class="login-browser-terminal">' + iconHtml("terminal") + '<span>Use terminal sign-in</span>' + iconHtml("arrow-up-right") + '</button></footer>';
61
63
  dialog.querySelector("h2").textContent = title;
62
64
  document.body.appendChild(dialog);
@@ -31,7 +31,7 @@ function vendorDisplayName(vendor) {
31
31
  var vendors = store.get('vendorInfo') || {};
32
32
  var info = vendors[vendor];
33
33
  if (info && info.displayName) return info.displayName;
34
- return vendor === "codex" ? "Codex" : "Claude Code";
34
+ return vendor || "Provider";
35
35
  }
36
36
 
37
37
  function currentProjectSlug() {
@@ -170,7 +170,7 @@ export function requestVendorLogin(vendor, opts) {
170
170
  vendor: target,
171
171
  auto: !!options.auto,
172
172
  sessionId: options.sessionId || store.get('activeSessionId') || null,
173
- mode: options.mode || ((target === "claude" || target === "codex") ? "browser" : "terminal"),
173
+ mode: options.mode || ((((store.get("vendorInfo") || {})[target] || {}).browserLoginSupported === true) ? "browser" : "terminal"),
174
174
  }));
175
175
  showLoginStartedBanner(target);
176
176
  return true;
@@ -1,4 +1,18 @@
1
- export var VENDOR_ORDER = ["claude", "codex", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
1
+ export var VENDOR_ORDER = ["claude", "codex", "muse", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
2
+
3
+ // Availability comes from the caller's server catalog. Unknown providers keep
4
+ // their catalog order within each availability group.
5
+ export function sortVendorEntries(entries) {
6
+ return entries.map(function (entry, index) { return { entry: entry, index: index }; }).sort(function (a, b) {
7
+ var installed = Number(!!b.entry.installed) - Number(!!a.entry.installed);
8
+ if (installed) return installed;
9
+ var aRank = VENDOR_ORDER.indexOf(a.entry.id);
10
+ var bRank = VENDOR_ORDER.indexOf(b.entry.id);
11
+ if (aRank === -1) aRank = VENDOR_ORDER.length;
12
+ if (bRank === -1) bRank = VENDOR_ORDER.length;
13
+ return aRank - bRank || a.index - b.index;
14
+ }).map(function (item) { return item.entry; });
15
+ }
2
16
  export var EXPERIMENTAL_VENDORS = ["grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode"];
3
17
 
4
18
  export function isExperimentalVendor(vendor) {
@@ -1,3 +1,4 @@
1
+ import { forwardStudioPresentation, registerStudioPaint } from './clay-studio-render.js';
1
2
  import { sketchBrand, sketchCredit } from './wireframe-style.js';
2
3
  import { store } from './store.js';
3
4
  import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
@@ -80,7 +81,7 @@ function createPanel() {
80
81
  export function openWireframe(message) {
81
82
  if (!message || typeof message.source !== 'string' || new TextEncoder().encode(message.source).length > 100000) return;
82
83
  if (store.get('paneMode') && window.parent !== window) {
83
- window.parent.postMessage({ type: 'clay-pane-present-wireframe', message: message, projectSlug: store.get('currentSlug'), sessionId: store.get('activeSessionId') }, window.location.origin);
84
+ forwardStudioPresentation(message, 'clay-pane-present-wireframe');
84
85
  return;
85
86
  }
86
87
  claimRightWorkbench('wireframe');
@@ -92,7 +93,8 @@ export function openWireframe(message) {
92
93
  el.querySelector('header strong').textContent = draft.title;
93
94
  el.querySelector('.wireframe-save-status').textContent = '';
94
95
  el.querySelector('form').hidden = true;
95
- draw(draft, el).catch(function () {});
96
+ var painted = draw(draft, el); registerStudioPaint(Object.assign({}, message, { source: draft.source }), el.querySelector("header"), painted, el.querySelector(".wireframe-workbench-canvas"));
97
+ painted.catch(function () {});
96
98
  }
97
99
  function draw(draft, el) {
98
100
  var canvas = el.querySelector('.wireframe-workbench-canvas');
@@ -104,6 +106,7 @@ function draw(draft, el) {
104
106
  var image = wireframeImage(svg, draft.title);
105
107
  canvas.replaceChildren(image);
106
108
  mountWireframeViewport(canvas, image, el.querySelector('.wireframe-zoom'));
109
+ return image.decode ? image.decode() : undefined;
107
110
  }).catch(function (error) {
108
111
  if (store.get('wireframeDraft') !== active) throw error;
109
112
  status.textContent = error.name === 'AbortError' ? 'Rendering was interrupted. Reopen the wireframe to retry.' : error.message;
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Muse Code">
2
+ <rect width="64" height="64" rx="14" fill="#111827"/>
3
+ <path d="M14 45V19h7l11 14 10-14h8v26h-7V30L32 45 21 30v15z" fill="#f8fafc"/>
4
+ </svg>
@@ -90,3 +90,5 @@
90
90
  @import url("css/project-settings-modal.css");
91
91
 
92
92
  @import url("css/clay-tool-activity.css");
93
+
94
+ @import url("css/contextual-clay.css");
@@ -115,51 +115,9 @@ function isSafeBashSegment(seg) {
115
115
  // Emit the `Bash(...)` permission patterns for ~/.claude/settings.json. Each
116
116
  // standalone command gets a bare form (zero-arg) and a space-wildcard form
117
117
  // (claude 2.x prefix matching); subcommands and exact commands likewise.
118
- function buildClayBashAllowPatterns() {
119
- var patterns = [];
120
- for (var i = 0; i < STANDALONE.length; i++) {
121
- patterns.push("Bash(" + STANDALONE[i] + ")");
122
- patterns.push("Bash(" + STANDALONE[i] + " *)");
123
- }
124
- var bins = Object.keys(SUBCOMMAND);
125
- for (var b = 0; b < bins.length; b++) {
126
- var subs = SUBCOMMAND[bins[b]];
127
- for (var s = 0; s < subs.length; s++) {
128
- var base = bins[b] + " " + subs[s];
129
- patterns.push("Bash(" + base + ")");
130
- patterns.push("Bash(" + base + " *)");
131
- }
132
- }
133
- for (var e = 0; e < EXACT.length; e++) {
134
- patterns.push("Bash(" + EXACT[e] + ")");
135
- patterns.push("Bash(" + EXACT[e] + " *)");
136
- }
137
- return patterns;
138
- }
139
-
140
- var GENERATED_SET = {};
141
- (function () {
142
- var p = buildClayBashAllowPatterns();
143
- for (var i = 0; i < p.length; i++) GENERATED_SET[p[i]] = true;
144
- })();
145
-
146
- // Recognize a `permissions.allow` entry that Clay owns, so the installer can
147
- // strip stale variants on upgrade (including shapes a previous version wrote)
148
- // WITHOUT clobbering user-authored patterns. Rules:
149
- // - Standalone commands: own every shape of `Bash(ls ...)` (any args), since
150
- // a user pattern for a command we manage is redundant with our broad one.
151
- // - Subcommand binaries (git, npm, ...) and exact commands: only strip the
152
- // precise patterns we generate, so a user's `Bash(git push)` survives.
153
- // Legacy colon shapes are handled separately by the installer.
154
- function isClayManagedBashPattern(p) {
155
- if (typeof p !== "string") return false;
156
- if (p.indexOf("Bash(") !== 0 || p.charAt(p.length - 1) !== ")") return false;
157
- if (GENERATED_SET[p]) return true;
158
- var inner = p.slice(5, -1).trim();
159
- if (!inner) return false;
160
- var word = inner.split(/[\s:]/)[0];
161
- return STANDALONE_SET[word] === true;
162
- }
118
+ var patternCodec = require("./yoke/claude-permission-patterns").attachPatterns({ STANDALONE: STANDALONE, SUBCOMMAND: SUBCOMMAND, EXACT: EXACT });
119
+ function buildClayBashAllowPatterns() { return patternCodec.build(); }
120
+ function isClayManagedBashPattern(pattern) { return patternCodec.isManaged(pattern); }
163
121
 
164
122
  module.exports = {
165
123
  STANDALONE: STANDALONE,