clay-server 3.4.0-beta.9 → 3.4.0

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 (66) hide show
  1. package/lib/daemon.js +58 -58
  2. package/lib/project-connection.js +19 -6
  3. package/lib/project-models.js +220 -0
  4. package/lib/project-session-handoff.js +162 -0
  5. package/lib/project-session-pair.js +14 -7
  6. package/lib/project-session-spawn.js +1 -1
  7. package/lib/project-sessions.js +13 -45
  8. package/lib/project-worker-proposal.js +51 -14
  9. package/lib/project.js +33 -77
  10. package/lib/public/app.js +11 -0
  11. package/lib/public/copilot-avatar.svg +5 -0
  12. package/lib/public/css/filebrowser.css +6 -1
  13. package/lib/public/css/input.css +56 -0
  14. package/lib/public/css/mates.css +6 -0
  15. package/lib/public/css/menus.css +35 -56
  16. package/lib/public/css/pane.css +18 -3
  17. package/lib/public/css/session-actions.css +98 -0
  18. package/lib/public/grok-avatar.svg +4 -0
  19. package/lib/public/index.html +26 -9
  20. package/lib/public/junie-avatar.svg +11 -0
  21. package/lib/public/kimi-avatar.svg +4 -0
  22. package/lib/public/modules/agent-config-selects.js +69 -0
  23. package/lib/public/modules/app-connection.js +6 -0
  24. package/lib/public/modules/app-header.js +0 -22
  25. package/lib/public/modules/app-messages.js +48 -9
  26. package/lib/public/modules/app-panels.js +33 -82
  27. package/lib/public/modules/app-projects.js +2 -0
  28. package/lib/public/modules/app-rendering.js +16 -1
  29. package/lib/public/modules/background-tasks-ui.js +55 -0
  30. package/lib/public/modules/filebrowser-tabs.js +65 -0
  31. package/lib/public/modules/filebrowser.js +23 -3
  32. package/lib/public/modules/mate-sidebar.js +10 -2
  33. package/lib/public/modules/model-picker.js +263 -0
  34. package/lib/public/modules/pane-bridge.js +6 -0
  35. package/lib/public/modules/session-actions.js +294 -0
  36. package/lib/public/modules/sidebar-mobile.js +2 -1
  37. package/lib/public/modules/sidebar-sessions.js +17 -1
  38. package/lib/public/modules/split-pair-ui.js +16 -77
  39. package/lib/public/modules/split-view.js +11 -1
  40. package/lib/public/modules/tools.js +5 -0
  41. package/lib/public/modules/vendor-priority.js +6 -1
  42. package/lib/public/modules/worker-proposal.js +6 -1
  43. package/lib/public/qwen-avatar.svg +4 -0
  44. package/lib/public/style.css +1 -0
  45. package/lib/sdk-bridge.js +57 -34
  46. package/lib/sdk-message-processor.js +26 -4
  47. package/lib/session-handoff-context.js +110 -0
  48. package/lib/session-notes-mcp-server.js +1 -0
  49. package/lib/sessions.js +4 -0
  50. package/lib/ws-schema.js +9 -1
  51. package/lib/yoke/acp-agent-profiles.js +64 -0
  52. package/lib/yoke/adapters/acp.js +2 -1
  53. package/lib/yoke/adapters/claude.js +34 -0
  54. package/lib/yoke/adapters/codex.js +38 -3
  55. package/lib/yoke/adapters/copilot.js +7 -0
  56. package/lib/yoke/adapters/grok.js +7 -0
  57. package/lib/yoke/adapters/junie.js +7 -0
  58. package/lib/yoke/adapters/kimi.js +7 -0
  59. package/lib/yoke/adapters/kiro.js +4 -3
  60. package/lib/yoke/adapters/qwen.js +7 -0
  61. package/lib/yoke/codex-background-tasks.js +84 -0
  62. package/lib/yoke/index.js +43 -14
  63. package/lib/yoke/instructions.js +3 -0
  64. package/lib/yoke/interface.js +21 -0
  65. package/lib/yoke/vendor-registry.js +55 -0
  66. package/package.json +1 -1
package/lib/yoke/index.js CHANGED
@@ -8,11 +8,16 @@ var createClaudeAdapter = require("./adapters/claude").createClaudeAdapter;
8
8
  var createCodexAdapter = require("./adapters/codex").createCodexAdapter;
9
9
  var createAntigravityAdapter = require("./adapters/antigravity").createAntigravityAdapter;
10
10
  var createOpenCodeAdapter = require("./adapters/opencode").createOpenCodeAdapter;
11
+ var createKimiAdapter = require("./adapters/kimi").createKimiAdapter;
12
+ var createGrokAdapter = require("./adapters/grok").createGrokAdapter;
13
+ var createCopilotAdapter = require("./adapters/copilot").createCopilotAdapter;
14
+ var createQwenAdapter = require("./adapters/qwen").createQwenAdapter;
15
+ var createJunieAdapter = require("./adapters/junie").createJunieAdapter;
11
16
  var createKiroAdapter = require("./adapters/kiro").createKiroAdapter;
12
17
 
13
18
  // Keep the first session in a new project predictable. This order is also
14
19
  // used by the UI when a project has no remembered vendor yet.
15
- var DEFAULT_VENDOR_ORDER = ["claude", "codex", "antigravity", "opencode", "kiro"];
20
+ var DEFAULT_VENDOR_ORDER = ["claude", "codex", "grok", "kimi", "copilot", "qwen", "junie", "antigravity", "opencode", "kiro"];
16
21
 
17
22
  function resolveDefaultVendor(availableVendors) {
18
23
  availableVendors = availableVendors || {};
@@ -77,6 +82,16 @@ function createAdapter(opts) {
77
82
  adapter = createAntigravityAdapter(opts);
78
83
  } else if (vendor === "opencode") {
79
84
  adapter = createOpenCodeAdapter(opts);
85
+ } else if (vendor === "kimi") {
86
+ adapter = createKimiAdapter(opts);
87
+ } else if (vendor === "grok") {
88
+ adapter = createGrokAdapter(opts);
89
+ } else if (vendor === "copilot") {
90
+ adapter = createCopilotAdapter(opts);
91
+ } else if (vendor === "qwen") {
92
+ adapter = createQwenAdapter(opts);
93
+ } else if (vendor === "junie") {
94
+ adapter = createJunieAdapter(opts);
80
95
  } else if (vendor === "kiro") {
81
96
  adapter = createKiroAdapter(opts);
82
97
  } else {
@@ -102,7 +117,7 @@ function logAuthCheck(auth) {
102
117
  if (_lastAuthLogKey === key && now - _lastAuthLogAt < 30000) return;
103
118
  _lastAuthLogKey = key;
104
119
  _lastAuthLogAt = now;
105
- console.log("[yoke] Auth check: claude=" + auth.claude + " codex=" + auth.codex + " antigravity=" + auth.antigravity + " opencode=" + auth.opencode + " kiro=" + auth.kiro);
120
+ console.log("[yoke] Auth check: " + Object.keys(auth).map(function(vendor) { return vendor + "=" + auth[vendor]; }).join(" "));
106
121
  }
107
122
 
108
123
  function checkAuth() {
@@ -238,6 +253,11 @@ function checkAuth() {
238
253
  codex: checkCodex(),
239
254
  antigravity: !!lookupBinary("agy"),
240
255
  opencode: !!lookupBinary("opencode"),
256
+ kimi: !!lookupBinary("kimi"),
257
+ grok: !!lookupBinary("grok"),
258
+ copilot: !!lookupBinary("copilot"),
259
+ qwen: !!lookupBinary("qwen"),
260
+ junie: !!lookupBinary("junie"),
241
261
  kiro: checkKiro(),
242
262
  };
243
263
  logAuthCheck(_authCache);
@@ -261,7 +281,7 @@ function checkInstalled() {
261
281
 
262
282
  var fs = require("fs");
263
283
  var execFileSync = require("child_process").execFileSync;
264
- var result = { claude: false, codex: false, antigravity: false, opencode: false, kiro: false };
284
+ var result = { claude: false, codex: false, antigravity: false, opencode: false, kimi: false, grok: false, copilot: false, qwen: false, junie: false, kiro: false };
265
285
  try {
266
286
  if (process.platform === "win32") execFileSync("where", ["claude"], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
267
287
  else execFileSync("which", ["claude"], { timeout: 3000, stdio: ["pipe", "pipe", "pipe"] });
@@ -295,10 +315,14 @@ function checkInstalled() {
295
315
  : execFileSync("which", ["agy"], { timeout: 3000, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
296
316
  result.antigravity = !!antigravityBinary.trim();
297
317
  } catch (e) {}
298
- try {
299
- var acpProfiles = require("./acp-agent-profiles");
300
- result.opencode = !!acpProfiles.findAcpAgentPath(acpProfiles.getAcpAgentProfile("opencode"));
301
- } catch (e) {}
318
+ var acpVendorKeys = ["opencode", "kimi", "grok", "copilot", "qwen", "junie"];
319
+ for (var acpIndex = 0; acpIndex < acpVendorKeys.length; acpIndex++) {
320
+ try {
321
+ var acpProfiles = require("./acp-agent-profiles");
322
+ var acpVendor = acpVendorKeys[acpIndex];
323
+ result[acpVendor] = !!acpProfiles.findAcpAgentPath(acpProfiles.getAcpAgentProfile(acpVendor));
324
+ } catch (e) {}
325
+ }
302
326
  _installedCache = result;
303
327
  return result;
304
328
  }
@@ -322,8 +346,10 @@ function createAdapters(opts) {
322
346
  // Claude Code supports multiple auth modes (OAuth, Bedrock, Vertex, API key)
323
347
  // that `claude auth status` does not always detect. Runtime auth failures are
324
348
  // handled downstream via query-level error detection.
325
- var installed = checkInstalled();
326
- var auth = { claude: false, codex: false, antigravity: false, opencode: false, kiro: false };
349
+ // Tests can supply a fixed installation snapshot without probing or spawning
350
+ // vendor binaries; production callers always use the cached host scan.
351
+ var installed = opts._installed || checkInstalled();
352
+ var auth = { claude: false, codex: false, antigravity: false, opencode: false, kimi: false, grok: false, copilot: false, qwen: false, junie: false, kiro: false };
327
353
  var adapters = {};
328
354
 
329
355
  function supportsConfiguredIsolation(vendor) {
@@ -339,10 +365,10 @@ function createAdapters(opts) {
339
365
  // per-project teardown never shuts it down on behalf of one project
340
366
  // (see destroy() in lib/project.js).
341
367
  _sharedClaudeAdapter.shared = true;
368
+ console.log("[yoke] Shared adapter created: claude");
342
369
  }
343
370
  adapters.claude = _sharedClaudeAdapter;
344
371
  auth.claude = true;
345
- console.log("[yoke] Adapter created: claude");
346
372
  } catch (e) {
347
373
  console.error("[yoke] Failed to create adapter for claude:", e.message);
348
374
  }
@@ -352,13 +378,12 @@ function createAdapters(opts) {
352
378
  try {
353
379
  adapters.codex = createAdapter({ vendor: "codex", cwd: opts.cwd, slug: opts.slug, osUsers: !!opts.osUsers });
354
380
  auth.codex = true;
355
- console.log("[yoke] Adapter created: codex");
356
381
  } catch (e) {
357
382
  console.error("[yoke] Failed to create adapter for codex:", e.message);
358
383
  }
359
384
  }
360
385
 
361
- var subprocessVendors = ["antigravity", "opencode"];
386
+ var subprocessVendors = ["antigravity", "opencode", "kimi", "grok", "copilot", "qwen", "junie"];
362
387
  for (var subprocessIndex = 0; subprocessIndex < subprocessVendors.length; subprocessIndex++) {
363
388
  var subprocessVendor = subprocessVendors[subprocessIndex];
364
389
  var subprocessInfo = vendorRegistry.getVendorInfo(subprocessVendor);
@@ -366,7 +391,6 @@ function createAdapters(opts) {
366
391
  try {
367
392
  adapters[subprocessVendor] = createAdapter({ vendor: subprocessVendor, cwd: opts.cwd, slug: opts.slug });
368
393
  auth[subprocessVendor] = true;
369
- console.log("[yoke] Adapter created: " + subprocessVendor);
370
394
  } catch (e) {
371
395
  console.error("[yoke] Failed to create adapter for " + subprocessVendor + ":", e.message);
372
396
  }
@@ -380,7 +404,6 @@ function createAdapters(opts) {
380
404
  try {
381
405
  adapters.kiro = createAdapter({ vendor: "kiro", cwd: opts.cwd, slug: opts.slug });
382
406
  auth.kiro = true;
383
- console.log("[yoke] Adapter created: kiro");
384
407
  } catch (e) {
385
408
  console.error("[yoke] Failed to create adapter for kiro:", e.message);
386
409
  }
@@ -388,6 +411,12 @@ function createAdapters(opts) {
388
411
  console.log("[yoke] " + kiroInfo.displayName + " adapter disabled: OS-user isolation requires per-user spawning");
389
412
  }
390
413
 
414
+ var registeredVendors = Object.keys(adapters);
415
+ if (registeredVendors.length > 0) {
416
+ var registrationScope = opts.slug ? " for " + opts.slug : "";
417
+ console.log("[yoke] Adapters registered" + registrationScope + ": " + registeredVendors.join(", "));
418
+ }
419
+
391
420
  return { adapters: adapters, auth: auth };
392
421
  }
393
422
 
@@ -18,12 +18,15 @@ var KNOWN_FILES = [
18
18
  { file: ".cursorrules", label: ".cursorrules" },
19
19
  { file: ".github/copilot-instructions.md", label: ".github/copilot-instructions.md" },
20
20
  { file: "COPILOT.md", label: "COPILOT.md" },
21
+ { file: "QWEN.md", label: "QWEN.md" },
21
22
  ];
22
23
 
23
24
  // Files each vendor reads natively (skip these to avoid duplication).
24
25
  var NATIVE_FILES = {
25
26
  claude: ["CLAUDE.md"],
26
27
  codex: ["AGENTS.md"],
28
+ copilot: [".github/copilot-instructions.md", "COPILOT.md"],
29
+ qwen: ["QWEN.md"],
27
30
  };
28
31
 
29
32
  // Scan projectDir for instruction files and return merged text.
@@ -9,6 +9,25 @@
9
9
  // 2. QueryHandle (returned by adapter.createQuery)
10
10
 
11
11
  var TOOL_POLICIES = ["ask", "allow-all"];
12
+ var BACKGROUND_TASK_TYPES = ["shell", "agent", "monitor", "other"];
13
+
14
+ // Shared budget for the initialize handshake every vendor process manager
15
+ // performs. Agents do their cold start before answering it: kiro-cli boots the
16
+ // KAS server, MCP subsystem and SQLite first, which measures ~20s, and Codex
17
+ // launches its configured MCP servers. The cost is asymmetric, since too short
18
+ // a window makes a working agent unusable while too long a one only delays the
19
+ // error for an agent that is already broken, so keep it generous.
20
+ var INITIALIZE_TIMEOUT_MS = 90000;
21
+
22
+ /*
23
+ * Optional adapter event contract:
24
+ * { yokeType: "background_tasks_changed", tasks: [{ task_id, task_type, description }] }
25
+ *
26
+ * Each event replaces the complete live set. An adapter that emits this event
27
+ * must reset it to an empty set when its CLI process restarts. task_type uses
28
+ * BACKGROUND_TASK_TYPES; adapters without a level signal may synthesize one,
29
+ * and adapters that emit nothing simply have no background-task indicator.
30
+ */
12
31
 
13
32
  /**
14
33
  * Validate that an adapter object implements all required methods.
@@ -93,6 +112,8 @@ function validateQueryHandle(handle) {
93
112
 
94
113
  module.exports = {
95
114
  TOOL_POLICIES: TOOL_POLICIES,
115
+ INITIALIZE_TIMEOUT_MS: INITIALIZE_TIMEOUT_MS,
116
+ BACKGROUND_TASK_TYPES: BACKGROUND_TASK_TYPES,
96
117
  ADAPTER_METHODS: ADAPTER_METHODS,
97
118
  QUERY_HANDLE_METHODS: QUERY_HANDLE_METHODS,
98
119
  validateAdapter: validateAdapter,
@@ -62,6 +62,61 @@ var VENDOR_REGISTRY = {
62
62
  usageDashboard: null,
63
63
  rateLimitTracking: false,
64
64
  },
65
+ kimi: {
66
+ displayName: "Kimi Code",
67
+ loginCommand: "kimi login",
68
+ binaryName: "kimi",
69
+ avatar: "/kimi-avatar.svg",
70
+ sessionModes: ["gui"],
71
+ effortLevels: [],
72
+ osUserIsolation: false,
73
+ usageDashboard: null,
74
+ rateLimitTracking: false,
75
+ },
76
+ grok: {
77
+ displayName: "Grok Build",
78
+ loginCommand: "grok login --device-auth",
79
+ binaryName: "grok",
80
+ avatar: "/grok-avatar.svg",
81
+ sessionModes: ["gui"],
82
+ effortLevels: [],
83
+ osUserIsolation: false,
84
+ usageDashboard: null,
85
+ rateLimitTracking: false,
86
+ },
87
+ copilot: {
88
+ displayName: "GitHub Copilot CLI",
89
+ loginCommand: "copilot login",
90
+ binaryName: "copilot",
91
+ avatar: "/copilot-avatar.svg",
92
+ sessionModes: ["gui"],
93
+ effortLevels: [],
94
+ osUserIsolation: false,
95
+ usageDashboard: null,
96
+ rateLimitTracking: false,
97
+ },
98
+ qwen: {
99
+ displayName: "Qwen Code",
100
+ loginCommand: "qwen",
101
+ binaryName: "qwen",
102
+ avatar: "/qwen-avatar.svg",
103
+ sessionModes: ["gui"],
104
+ effortLevels: [],
105
+ osUserIsolation: false,
106
+ usageDashboard: null,
107
+ rateLimitTracking: false,
108
+ },
109
+ junie: {
110
+ displayName: "Junie CLI",
111
+ loginCommand: "junie",
112
+ binaryName: "junie",
113
+ avatar: "/junie-avatar.svg",
114
+ sessionModes: ["gui"],
115
+ effortLevels: [],
116
+ osUserIsolation: false,
117
+ usageDashboard: null,
118
+ rateLimitTracking: false,
119
+ },
65
120
  kiro: {
66
121
  displayName: "Kiro CLI",
67
122
  loginCommand: "kiro-cli login",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "3.4.0-beta.9",
3
+ "version": "3.4.0",
4
4
  "description": "Self-hosted team workspace for Claude Code and Codex. Multi-user, browser-based, with persistent AI mates.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",