clay-server 3.4.0-beta.2 → 3.4.0-beta.21

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 (82) hide show
  1. package/lib/daemon-projects.js +3 -3
  2. package/lib/daemon.js +59 -59
  3. package/lib/project-connection.js +35 -7
  4. package/lib/project-debate.js +4 -0
  5. package/lib/project-mate-interaction.js +21 -1
  6. package/lib/project-memory.js +3 -0
  7. package/lib/project-models.js +220 -0
  8. package/lib/project-session-handoff.js +162 -0
  9. package/lib/project-session-pair.js +14 -7
  10. package/lib/project-session-spawn.js +1 -1
  11. package/lib/project-sessions.js +13 -45
  12. package/lib/project-worker-proposal.js +51 -14
  13. package/lib/project.js +38 -80
  14. package/lib/public/antigravity-avatar.png +0 -0
  15. package/lib/public/app.js +29 -0
  16. package/lib/public/copilot-avatar.svg +5 -0
  17. package/lib/public/css/command-palette.css +22 -2
  18. package/lib/public/css/icon-strip.css +29 -13
  19. package/lib/public/css/input.css +56 -0
  20. package/lib/public/css/mates.css +6 -0
  21. package/lib/public/css/menus.css +38 -25
  22. package/lib/public/css/messages.css +9 -0
  23. package/lib/public/css/pane.css +16 -3
  24. package/lib/public/css/pwa-mobile.css +17 -0
  25. package/lib/public/css/session-actions.css +98 -0
  26. package/lib/public/css/title-bar.css +19 -0
  27. package/lib/public/grok-avatar.svg +4 -0
  28. package/lib/public/index.html +29 -7
  29. package/lib/public/junie-avatar.svg +11 -0
  30. package/lib/public/kimi-avatar.svg +4 -0
  31. package/lib/public/modules/agent-config-selects.js +69 -0
  32. package/lib/public/modules/app-header.js +4 -22
  33. package/lib/public/modules/app-messages.js +54 -11
  34. package/lib/public/modules/app-panels.js +36 -83
  35. package/lib/public/modules/app-projects.js +3 -1
  36. package/lib/public/modules/app-rendering.js +19 -4
  37. package/lib/public/modules/background-tasks-ui.js +55 -0
  38. package/lib/public/modules/mate-sidebar.js +11 -3
  39. package/lib/public/modules/model-picker.js +263 -0
  40. package/lib/public/modules/notifications.js +7 -1
  41. package/lib/public/modules/pane-bridge.js +11 -0
  42. package/lib/public/modules/pane-links.js +23 -0
  43. package/lib/public/modules/project-switcher.js +7 -6
  44. package/lib/public/modules/session-actions.js +294 -0
  45. package/lib/public/modules/sidebar-mates.js +1 -1
  46. package/lib/public/modules/sidebar-mobile.js +2 -1
  47. package/lib/public/modules/sidebar-projects.js +34 -43
  48. package/lib/public/modules/sidebar-sessions.js +20 -6
  49. package/lib/public/modules/split-pair-ui.js +16 -77
  50. package/lib/public/modules/split-view.js +3 -0
  51. package/lib/public/modules/tools.js +6 -1
  52. package/lib/public/modules/vendor-priority.js +14 -0
  53. package/lib/public/modules/vendor-selection.js +20 -0
  54. package/lib/public/modules/worker-proposal.js +6 -1
  55. package/lib/public/modules/worktree-location.js +17 -0
  56. package/lib/public/qwen-avatar.svg +4 -0
  57. package/lib/public/style.css +4 -2
  58. package/lib/sdk-bridge.js +103 -56
  59. package/lib/sdk-message-processor.js +26 -4
  60. package/lib/session-handoff-context.js +110 -0
  61. package/lib/session-notes-mcp-server.js +8 -1
  62. package/lib/sessions.js +4 -0
  63. package/lib/worktree.js +9 -4
  64. package/lib/ws-schema.js +9 -1
  65. package/lib/yoke/acp-agent-profiles.js +64 -14
  66. package/lib/yoke/adapters/antigravity.js +417 -0
  67. package/lib/yoke/adapters/claude.js +34 -0
  68. package/lib/yoke/adapters/codex.js +101 -5
  69. package/lib/yoke/adapters/copilot.js +7 -0
  70. package/lib/yoke/adapters/grok.js +7 -0
  71. package/lib/yoke/adapters/junie.js +7 -0
  72. package/lib/yoke/adapters/kimi.js +7 -0
  73. package/lib/yoke/adapters/kiro.js +2 -2
  74. package/lib/yoke/adapters/qwen.js +7 -0
  75. package/lib/yoke/codex-app-server.js +25 -8
  76. package/lib/yoke/index.js +67 -28
  77. package/lib/yoke/instructions.js +3 -0
  78. package/lib/yoke/interface.js +12 -0
  79. package/lib/yoke/vendor-registry.js +61 -6
  80. package/package.json +1 -1
  81. package/lib/public/gemini-avatar.svg +0 -11
  82. package/lib/yoke/adapters/gemini.js +0 -7
@@ -1,7 +1,7 @@
1
1
  import { store } from './store.js';
2
2
  import { getWs } from './ws-ref.js';
3
- import { VENDOR_AVATARS, VENDOR_NAMES, VENDOR_ORDER } from './app-rendering.js';
4
- import { effortLevelsFor, effortDisplayName } from './app-panels.js';
3
+ import { VENDOR_AVATARS } from './app-rendering.js';
4
+ import { buildAgentVendorSelect, fillAgentModels, buildAgentEffortSelect, fillAgentEffort } from './agent-config-selects.js';
5
5
  import { showToast } from './utils.js';
6
6
 
7
7
  var pairDialog = null;
@@ -9,77 +9,14 @@ var pairDialog = null;
9
9
  // that session becomes the Driver and the dialog only configures the Worker.
10
10
  var pendingDriver = null;
11
11
 
12
- function optionValue(entry) {
13
- if (typeof entry === "string") return entry;
14
- return entry && (entry.value || entry.id) || "";
15
- }
16
-
17
- function optionLabel(entry) {
18
- if (typeof entry === "string") return entry;
19
- return entry && (entry.displayName || entry.name || entry.value || entry.id) || "";
20
- }
21
-
22
- function fillModels(select, vendor, options) {
23
- var models = (options.modelsByVendor && options.modelsByVendor[vendor]) || [];
24
- select.innerHTML = "";
25
- var automatic = document.createElement("option");
26
- automatic.value = "";
27
- automatic.textContent = "Automatic";
28
- select.appendChild(automatic);
29
- for (var i = 0; i < models.length; i++) {
30
- var option = document.createElement("option");
31
- option.value = optionValue(models[i]);
32
- option.textContent = optionLabel(models[i]);
33
- select.appendChild(option);
34
- }
35
- }
36
-
37
12
  function closePairDialog() {
38
13
  if (pairDialog) pairDialog.remove();
39
14
  pairDialog = null;
40
15
  }
41
16
 
42
- function buildVendorSelect(installed, preferred) {
43
- var select = document.createElement("select");
44
- select.className = "wt-modal-input";
45
- for (var i = 0; i < VENDOR_ORDER.length; i++) {
46
- if (installed.indexOf(VENDOR_ORDER[i]) === -1) continue;
47
- var option = document.createElement("option");
48
- option.value = VENDOR_ORDER[i];
49
- option.textContent = VENDOR_NAMES[VENDOR_ORDER[i]] || VENDOR_ORDER[i];
50
- select.appendChild(option);
51
- }
52
- if (preferred && installed.indexOf(preferred) !== -1) select.value = preferred;
53
- return select;
54
- }
55
-
56
17
  // Effort levels are vendor- and model-specific (codex: minimal..xhigh,
57
18
  // claude/kiro: low..max, plus per-model supportedEffortLevels overrides), so
58
19
  // options are rebuilt whenever the role's vendor or model changes.
59
- function fillEffortOptions(select, vendor, options, modelValue) {
60
- var previous = select.value;
61
- var models = (options.modelsByVendor && options.modelsByVendor[vendor]) || [];
62
- var levels = effortLevelsFor(vendor, models, modelValue);
63
- select.innerHTML = "";
64
- var automatic = document.createElement("option");
65
- automatic.value = "";
66
- automatic.textContent = "Default";
67
- select.appendChild(automatic);
68
- for (var i = 0; i < levels.length; i++) {
69
- var option = document.createElement("option");
70
- option.value = levels[i];
71
- option.textContent = effortDisplayName(levels[i]);
72
- select.appendChild(option);
73
- }
74
- select.value = levels.indexOf(previous) !== -1 ? previous : "";
75
- }
76
-
77
- function buildEffortSelect() {
78
- var select = document.createElement("select");
79
- select.className = "wt-modal-input";
80
- return select;
81
- }
82
-
83
20
  function fieldLabel(text, control) {
84
21
  var label = document.createElement("label");
85
22
  label.className = "wt-modal-label";
@@ -154,25 +91,25 @@ export function showPairDialog(options) {
154
91
  : "One Driver plans and directs a visible Worker session.";
155
92
  modal.appendChild(desc);
156
93
 
157
- var driverVendor = buildVendorSelect(installed, installed.indexOf("claude") !== -1 ? "claude" : installed[0]);
94
+ var driverVendor = buildAgentVendorSelect(installed, installed.indexOf("claude") !== -1 ? "claude" : installed[0]);
158
95
  var workerDefault = options.lastVendor && options.lastVendor !== driverVendor.value ? options.lastVendor : (installed.indexOf("codex") !== -1 ? "codex" : installed[0]);
159
- var workerVendor = buildVendorSelect(installed, workerDefault);
96
+ var workerVendor = buildAgentVendorSelect(installed, workerDefault);
160
97
  var driverModel = document.createElement("select");
161
98
  driverModel.className = "wt-modal-input";
162
99
  var workerModel = document.createElement("select");
163
100
  workerModel.className = "wt-modal-input";
164
- var driverEffort = buildEffortSelect();
165
- var workerEffort = buildEffortSelect();
166
- function refreshDriverEffort() { fillEffortOptions(driverEffort, driverVendor.value, options, driverModel.value); }
167
- function refreshWorkerEffort() { fillEffortOptions(workerEffort, workerVendor.value, options, workerModel.value); }
168
- fillModels(driverModel, driverVendor.value, options);
169
- fillModels(workerModel, workerVendor.value, options);
101
+ var driverEffort = buildAgentEffortSelect();
102
+ var workerEffort = buildAgentEffortSelect();
103
+ function refreshDriverEffort() { fillAgentEffort(driverEffort, driverVendor.value, options, driverModel.value); }
104
+ function refreshWorkerEffort() { fillAgentEffort(workerEffort, workerVendor.value, options, workerModel.value); }
105
+ fillAgentModels(driverModel, driverVendor.value, options);
106
+ fillAgentModels(workerModel, workerVendor.value, options);
170
107
  refreshDriverEffort();
171
108
  refreshWorkerEffort();
172
109
  workerEffort.value = "medium";
173
110
  if (workerEffort.value !== "medium") workerEffort.value = "";
174
- driverVendor.addEventListener("change", function () { fillModels(driverModel, driverVendor.value, options); refreshDriverEffort(); });
175
- workerVendor.addEventListener("change", function () { fillModels(workerModel, workerVendor.value, options); refreshWorkerEffort(); });
111
+ driverVendor.addEventListener("change", function () { fillAgentModels(driverModel, driverVendor.value, options); refreshDriverEffort(); });
112
+ workerVendor.addEventListener("change", function () { fillAgentModels(workerModel, workerVendor.value, options); refreshWorkerEffort(); });
176
113
  driverModel.addEventListener("change", refreshDriverEffort);
177
114
  workerModel.addEventListener("change", refreshWorkerEffort);
178
115
 
@@ -318,7 +255,8 @@ export function syncPairChrome(host, split) {
318
255
  setBtn.title = "Make this session the Driver; the other pane becomes its Worker";
319
256
  setBtn.addEventListener("click", function () { sendSetPair(group.id, paneSessionId); });
320
257
  var titleEl = header.querySelector(".split-pane-title");
321
- header.insertBefore(setBtn, titleEl ? titleEl.nextSibling : null);
258
+ var accessEl = header.querySelector(".split-pane-full-access");
259
+ header.insertBefore(setBtn, accessEl ? accessEl.nextSibling : (titleEl ? titleEl.nextSibling : null));
322
260
  })(split.panes[ai].sessionId, headers[ai]);
323
261
  }
324
262
  return;
@@ -338,7 +276,8 @@ export function syncPairChrome(host, split) {
338
276
  sendSetPair(group.id, isDriver ? null : sessionId);
339
277
  });
340
278
  var title = header.querySelector(".split-pane-title");
341
- header.insertBefore(badge, title ? title.nextSibling : null);
279
+ var access = header.querySelector(".split-pane-full-access");
280
+ header.insertBefore(badge, access ? access.nextSibling : (title ? title.nextSibling : null));
342
281
  })(split.panes[pi].sessionId, headers[pi]);
343
282
  }
344
283
  var active = (store.get('splitDelegations') || {})[group.id];
@@ -231,6 +231,9 @@ function createPane(pane, index) {
231
231
  }, "Skip Permissions", true);
232
232
  });
233
233
  header.appendChild(fullAccess);
234
+ // Permission state belongs to the session identity on the left. Keep it
235
+ // immediately after the title instead of grouping it with usage and close.
236
+ header.insertBefore(fullAccess, ctxChip);
234
237
 
235
238
  var close = document.createElement("button");
236
239
  close.type = "button";
@@ -817,8 +817,13 @@ function resolvePermissionIdentity(mateId, vendor) {
817
817
  var vendorAvatars = {
818
818
  claude: "/claude-code-avatar.png",
819
819
  codex: "/codex-avatar.png",
820
- gemini: "/gemini-avatar.svg",
820
+ antigravity: "/antigravity-avatar.png",
821
821
  opencode: "/opencode-avatar.svg",
822
+ kimi: "/kimi-avatar.svg",
823
+ grok: "/grok-avatar.svg",
824
+ copilot: "/copilot-avatar.svg",
825
+ qwen: "/qwen-avatar.svg",
826
+ junie: "/junie-avatar.svg",
822
827
  kiro: "/kiro-avatar.svg",
823
828
  };
824
829
  var vendorName = (vendor && VENDOR_NAMES[vendor]) || VENDOR_NAMES.claude;
@@ -0,0 +1,14 @@
1
+ export var VENDOR_ORDER = ["claude", "codex", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
2
+ export var EXPERIMENTAL_VENDORS = ["grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode"];
3
+
4
+ export function isExperimentalVendor(vendor) {
5
+ return EXPERIMENTAL_VENDORS.indexOf(vendor) !== -1;
6
+ }
7
+
8
+ export function firstInstalledVendor(installedVendors) {
9
+ var installed = Array.isArray(installedVendors) ? installedVendors : [];
10
+ for (var i = 0; i < VENDOR_ORDER.length; i++) {
11
+ if (installed.indexOf(VENDOR_ORDER[i]) !== -1) return VENDOR_ORDER[i];
12
+ }
13
+ return "";
14
+ }
@@ -0,0 +1,20 @@
1
+ import { store } from './store.js';
2
+ import { firstInstalledVendor } from './vendor-priority.js';
3
+
4
+ export function selectDefaultVendorForBlankSession() {
5
+ var state = store.snap();
6
+ if (!state.activeSessionId || state.sessionHasHistory || state.sessionVendorBound || state.dmMode) return "";
7
+ var vendor = firstInstalledVendor(state.installedVendors);
8
+ if (!vendor) return "";
9
+ if (vendor === state.currentVendor) {
10
+ if (state.vendorSelectionLocked) store.set({ vendorSelectionLocked: false });
11
+ return vendor;
12
+ }
13
+ store.set({
14
+ currentVendor: vendor,
15
+ currentModel: "",
16
+ currentModels: [],
17
+ vendorSelectionLocked: false,
18
+ });
19
+ return vendor;
20
+ }
@@ -95,6 +95,7 @@ function statusLabel(status) {
95
95
  if (status === "starting") return "Starting Worker";
96
96
  if (status === "running") return "Worker running";
97
97
  if (status === "completed") return "Completed";
98
+ if (status === "interrupted") return "Interrupted";
98
99
  if (status === "declined") return "Continuing here";
99
100
  if (status === "error") return "Needs attention";
100
101
  return "Suggested by Fable";
@@ -103,8 +104,10 @@ function statusLabel(status) {
103
104
  function applyState(card, msg) {
104
105
  var status = msg.status || "pending";
105
106
  card.dataset.status = status;
107
+ if (msg.autoApproved) card.dataset.autoApproved = "true";
108
+ var autoApproved = card.dataset.autoApproved === "true";
106
109
  var badge = card.querySelector(".worker-proposal-status");
107
- if (badge) badge.textContent = statusLabel(status);
110
+ if (badge) badge.textContent = statusLabel(status) + (autoApproved ? " · auto-approved" : "");
108
111
  var error = card.querySelector(".worker-proposal-error");
109
112
  if (error) {
110
113
  error.textContent = msg.error || "";
@@ -116,6 +119,8 @@ function applyState(card, msg) {
116
119
  preview.classList.remove("hidden");
117
120
  }
118
121
  setControlsDisabled(card, status !== "pending");
122
+ var actions = card.querySelector(".worker-proposal-actions");
123
+ if (actions) actions.classList.toggle("hidden", autoApproved);
119
124
  }
120
125
 
121
126
  function sendDecision(card, accepted) {
@@ -0,0 +1,17 @@
1
+ export function isExternalWorktree(project) {
2
+ return !!(project && project.isWorktree && project.worktreeExternal === true);
3
+ }
4
+
5
+ export function externalWorktreeTooltip(name) {
6
+ return name + " — outside the main project folder";
7
+ }
8
+
9
+ export function appendExternalWorktreeBadge(container, className) {
10
+ var badge = document.createElement("span");
11
+ badge.className = className;
12
+ badge.setAttribute("role", "img");
13
+ badge.setAttribute("aria-label", "Outside the main project folder");
14
+ badge.innerHTML = '<i data-lucide="external-link"></i>';
15
+ container.appendChild(badge);
16
+ return badge;
17
+ }
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Qwen Code">
2
+ <rect width="64" height="64" rx="14" fill="#6b4eff"/>
3
+ <path d="M32 12a20 20 0 1 0 12 36l7 5-3-11a20 20 0 0 0-16-30zm0 9a11 11 0 1 1-7.8 18.8A11 11 0 0 1 32 21z" fill="#fff"/>
4
+ </svg>
@@ -1,12 +1,13 @@
1
1
  @import url("css/base.css");
2
2
  @import url("css/icon-strip.css");
3
- @import url("css/title-bar.css");
3
+ @import url("css/title-bar.css?v=20260824");
4
4
  @import url("css/pane.css");
5
5
  @import url("css/worker-proposal.css");
6
+ @import url("css/session-actions.css");
6
7
  @import url("css/sidebar.css");
7
8
  @import url("css/overlays.css");
8
9
  @import url("css/menus.css");
9
- @import url("css/messages.css?v=20260407");
10
+ @import url("css/messages.css?v=20260824");
10
11
  @import url("css/rewind.css");
11
12
  @import url("css/input.css");
12
13
  @import url("css/filebrowser.css");
@@ -35,3 +36,4 @@
35
36
  @import url("css/debate.css");
36
37
  @import url("css/notifications-center.css");
37
38
  @import url("css/tui-attention.css");
39
+ @import url("css/pwa-mobile.css?v=20260824f");