clay-server 2.44.1-beta.1 → 2.45.0-beta.1
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.
- package/lib/daemon.js +27 -4
- package/lib/os-users.js +69 -2
- package/lib/project-http.js +4 -2
- package/lib/project-sessions.js +86 -21
- package/lib/public/app.js +1 -1
- package/lib/public/index.html +15 -0
- package/lib/public/modules/app-messages.js +54 -2
- package/lib/public/modules/mcp-ui.js +44 -0
- package/lib/public/modules/profile.js +2 -2
- package/lib/public/modules/server-settings.js +34 -0
- package/lib/public/modules/skills.js +16 -0
- package/lib/public/modules/tools.js +156 -0
- package/lib/public/modules/user-settings.js +2 -2
- package/lib/sdk-bridge.js +76 -0
- package/lib/sdk-message-processor.js +67 -0
- package/lib/server-settings.js +2 -2
- package/lib/server.js +2 -0
- package/lib/terminal.js +4 -1
- package/lib/users-preferences.js +8 -7
- package/lib/ws-schema.js +9 -0
- package/lib/yoke/adapters/claude-worker.js +62 -0
- package/lib/yoke/adapters/claude.js +121 -3
- package/package.json +2 -2
|
@@ -12,6 +12,12 @@ var crypto = require("crypto");
|
|
|
12
12
|
var { spawn } = require("child_process");
|
|
13
13
|
var { resolveOsUserInfo } = require("../../os-users");
|
|
14
14
|
|
|
15
|
+
// SDK-specific knowledge stays in the adapter (not the relay): the host dialog
|
|
16
|
+
// kinds this client can render, declared to the SDK when an onUserDialog
|
|
17
|
+
// callback is wired. The CLI fails closed — kinds not listed here are never
|
|
18
|
+
// emitted. Keep in sync with the client's generic user-dialog renderer.
|
|
19
|
+
var SUPPORTED_DIALOG_KINDS = ["refusal_fallback_prompt"];
|
|
20
|
+
|
|
15
21
|
// --- SDK loading ---
|
|
16
22
|
// Async loader (ESM dynamic import, same pattern as current project.js getSDK)
|
|
17
23
|
var _sdkPromise = null;
|
|
@@ -182,6 +188,68 @@ function flattenEvent(raw) {
|
|
|
182
188
|
base.summary = raw.summary || null;
|
|
183
189
|
return base;
|
|
184
190
|
}
|
|
191
|
+
// Model refusal: the model declined and the CLI either fell back to
|
|
192
|
+
// another model or ended the turn. Translate to a vendor-neutral
|
|
193
|
+
// yokeType so the relay never sees SDK subtype strings.
|
|
194
|
+
if (raw.subtype === "model_refusal_fallback") {
|
|
195
|
+
base.yokeType = "model_refusal";
|
|
196
|
+
base.refusalKind = "fallback";
|
|
197
|
+
base.originalModel = raw.original_model || null;
|
|
198
|
+
base.fallbackModel = raw.fallback_model || null;
|
|
199
|
+
base.direction = raw.direction || null;
|
|
200
|
+
base.category = raw.api_refusal_category || null;
|
|
201
|
+
return base;
|
|
202
|
+
}
|
|
203
|
+
if (raw.subtype === "model_refusal_no_fallback") {
|
|
204
|
+
base.yokeType = "model_refusal";
|
|
205
|
+
base.refusalKind = "no_fallback";
|
|
206
|
+
base.originalModel = raw.original_model || null;
|
|
207
|
+
base.category = raw.api_refusal_category || null;
|
|
208
|
+
base.explanation = raw.api_refusal_explanation || null;
|
|
209
|
+
base.content = raw.content || null;
|
|
210
|
+
return base;
|
|
211
|
+
}
|
|
212
|
+
// Slash-command list changed mid-session (e.g. skills discovered dynamically).
|
|
213
|
+
if (raw.subtype === "commands_changed") {
|
|
214
|
+
base.yokeType = "commands_changed";
|
|
215
|
+
base.commandNames = Array.isArray(raw.commands)
|
|
216
|
+
? raw.commands.map(function(c) { return (c && typeof c === "object") ? c.name : c; }).filter(Boolean)
|
|
217
|
+
: [];
|
|
218
|
+
return base;
|
|
219
|
+
}
|
|
220
|
+
// The session worker is shutting down (reason is a host-set snake_case code).
|
|
221
|
+
if (raw.subtype === "worker_shutting_down") {
|
|
222
|
+
base.yokeType = "worker_shutting_down";
|
|
223
|
+
base.reason = raw.reason || "";
|
|
224
|
+
return base;
|
|
225
|
+
}
|
|
226
|
+
// Live thinking-token estimate (ephemeral progress).
|
|
227
|
+
if (raw.subtype === "thinking_tokens") {
|
|
228
|
+
base.yokeType = "thinking_tokens";
|
|
229
|
+
base.estimatedTokens = raw.estimated_tokens || 0;
|
|
230
|
+
base.estimatedTokensDelta = raw.estimated_tokens_delta || 0;
|
|
231
|
+
return base;
|
|
232
|
+
}
|
|
233
|
+
// Informational system message (render-leveled: info/notice/suggestion/warning).
|
|
234
|
+
if (raw.subtype === "informational") {
|
|
235
|
+
base.yokeType = "informational";
|
|
236
|
+
base.level = raw.level || "info";
|
|
237
|
+
base.content = raw.content || "";
|
|
238
|
+
base.toolUseId = raw.tool_use_id || null;
|
|
239
|
+
base.preventContinuation = !!raw.prevent_continuation;
|
|
240
|
+
return base;
|
|
241
|
+
}
|
|
242
|
+
// A tool call was denied (by classifier, rule, mode, or async agent).
|
|
243
|
+
if (raw.subtype === "permission_denied") {
|
|
244
|
+
base.yokeType = "permission_denied";
|
|
245
|
+
base.toolName = raw.tool_name || "";
|
|
246
|
+
base.toolUseId = raw.tool_use_id || null;
|
|
247
|
+
base.agentId = raw.agent_id || null;
|
|
248
|
+
base.reasonType = raw.decision_reason_type || null;
|
|
249
|
+
base.reason = raw.decision_reason || null;
|
|
250
|
+
base.message = raw.message || "";
|
|
251
|
+
return base;
|
|
252
|
+
}
|
|
185
253
|
// Catch-all system event
|
|
186
254
|
base.yokeType = "system";
|
|
187
255
|
base.subtype = raw.subtype;
|
|
@@ -338,6 +406,20 @@ function createQueryHandle(rawQuery, messageQueue, abortController) {
|
|
|
338
406
|
return Promise.resolve();
|
|
339
407
|
},
|
|
340
408
|
|
|
409
|
+
reloadSkills: function() {
|
|
410
|
+
if (rawQuery && typeof rawQuery.reloadSkills === "function") {
|
|
411
|
+
return rawQuery.reloadSkills();
|
|
412
|
+
}
|
|
413
|
+
return Promise.resolve(null);
|
|
414
|
+
},
|
|
415
|
+
|
|
416
|
+
setMcpPermissionModeOverride: function(serverName, mode) {
|
|
417
|
+
if (rawQuery && typeof rawQuery.setMcpPermissionModeOverride === "function") {
|
|
418
|
+
return rawQuery.setMcpPermissionModeOverride(serverName, mode);
|
|
419
|
+
}
|
|
420
|
+
return Promise.resolve(null);
|
|
421
|
+
},
|
|
422
|
+
|
|
341
423
|
getContextUsage: function() {
|
|
342
424
|
if (rawQuery && typeof rawQuery.getContextUsage === "function") {
|
|
343
425
|
return rawQuery.getContextUsage();
|
|
@@ -517,13 +599,16 @@ function spawnWorker(linuxUser, workerScriptPath, cwd) {
|
|
|
517
599
|
console.log("[yoke/claude] Spawning worker: uid=" + userInfo.uid + " gid=" + userInfo.gid + " cwd=" + cwd + " socket=" + socketPath);
|
|
518
600
|
console.log("[yoke/claude] Worker script: " + workerScriptPath);
|
|
519
601
|
console.log("[yoke/claude] Node: " + process.execPath);
|
|
520
|
-
|
|
602
|
+
// Route through setpriv when group inheritance is enabled so the worker
|
|
603
|
+
// (and the agent CLI it spawns) inherits the user's supplementary groups.
|
|
604
|
+
var workerSpawn = require("../../os-users").wrapSpawnAsUser(process.execPath, [workerScriptPath, socketPath], {
|
|
521
605
|
uid: userInfo.uid,
|
|
522
606
|
gid: userInfo.gid,
|
|
523
607
|
env: workerEnv,
|
|
524
608
|
cwd: cwd,
|
|
525
609
|
stdio: ["ignore", "pipe", "pipe"],
|
|
526
610
|
});
|
|
611
|
+
worker.process = spawn(workerSpawn.command, workerSpawn.args, workerSpawn.options);
|
|
527
612
|
|
|
528
613
|
worker.process.stdout.on("data", function(data) {
|
|
529
614
|
console.log("[sdk-worker:" + linuxUser + "] " + data.toString().trim());
|
|
@@ -681,7 +766,7 @@ function serializeWorkerValue(value, seen) {
|
|
|
681
766
|
// in-process QueryHandle. This allows processQueryStream to iterate a worker
|
|
682
767
|
// query identically to an in-process query.
|
|
683
768
|
|
|
684
|
-
function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool) {
|
|
769
|
+
function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool, onUserDialog) {
|
|
685
770
|
// Async iterable state
|
|
686
771
|
var iterQueue = [];
|
|
687
772
|
var iterWaiting = null;
|
|
@@ -779,6 +864,24 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool)
|
|
|
779
864
|
}
|
|
780
865
|
break;
|
|
781
866
|
|
|
867
|
+
case "user_dialog_request":
|
|
868
|
+
if (onUserDialog) {
|
|
869
|
+
onUserDialog({
|
|
870
|
+
dialogKind: msg.dialogKind,
|
|
871
|
+
payload: msg.payload || {},
|
|
872
|
+
toolUseID: msg.toolUseId || undefined,
|
|
873
|
+
}, {
|
|
874
|
+
signal: { addEventListener: function() {} },
|
|
875
|
+
}).then(function(result) {
|
|
876
|
+
worker.send({ type: "user_dialog_response", requestId: msg.requestId, result: result });
|
|
877
|
+
}).catch(function(e) {
|
|
878
|
+
console.error("[yoke/claude] user_dialog_response send failed:", e.message || e);
|
|
879
|
+
});
|
|
880
|
+
} else {
|
|
881
|
+
worker.send({ type: "user_dialog_response", requestId: msg.requestId, result: { behavior: "cancelled" } });
|
|
882
|
+
}
|
|
883
|
+
break;
|
|
884
|
+
|
|
782
885
|
case "mcp_tool_call":
|
|
783
886
|
if (callMcpTool) {
|
|
784
887
|
callMcpTool(msg.serverName, msg.toolName, msg.args || {}).then(function(result) {
|
|
@@ -916,6 +1019,16 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation, callMcpTool)
|
|
|
916
1019
|
return Promise.resolve();
|
|
917
1020
|
},
|
|
918
1021
|
|
|
1022
|
+
reloadSkills: function() {
|
|
1023
|
+
worker.send({ type: "reload_skills" });
|
|
1024
|
+
return Promise.resolve(null);
|
|
1025
|
+
},
|
|
1026
|
+
|
|
1027
|
+
setMcpPermissionModeOverride: function(serverName, mode) {
|
|
1028
|
+
worker.send({ type: "set_mcp_permission_mode_override", serverName: serverName, mode: mode });
|
|
1029
|
+
return Promise.resolve(null);
|
|
1030
|
+
},
|
|
1031
|
+
|
|
919
1032
|
getContextUsage: function() {
|
|
920
1033
|
return Promise.resolve(null);
|
|
921
1034
|
},
|
|
@@ -1215,6 +1328,10 @@ function createClaudeAdapter(opts) {
|
|
|
1215
1328
|
if (queryOpts.toolServers) sdkOptions.mcpServers = queryOpts.toolServers;
|
|
1216
1329
|
if (queryOpts.canUseTool) sdkOptions.canUseTool = queryOpts.canUseTool;
|
|
1217
1330
|
if (queryOpts.onElicitation) sdkOptions.onElicitation = queryOpts.onElicitation;
|
|
1331
|
+
if (queryOpts.onUserDialog) {
|
|
1332
|
+
sdkOptions.onUserDialog = queryOpts.onUserDialog;
|
|
1333
|
+
sdkOptions.supportedDialogKinds = SUPPORTED_DIALOG_KINDS;
|
|
1334
|
+
}
|
|
1218
1335
|
if (queryOpts.resumeSessionId) sdkOptions.resume = queryOpts.resumeSessionId;
|
|
1219
1336
|
|
|
1220
1337
|
// Claude-specific options from adapterOptions.CLAUDE
|
|
@@ -1363,7 +1480,7 @@ function createClaudeAdapter(opts) {
|
|
|
1363
1480
|
}
|
|
1364
1481
|
|
|
1365
1482
|
// Create the worker query handle (sets up message handler on worker)
|
|
1366
|
-
var handle = createWorkerQueryHandle(worker, queryOpts.canUseTool, queryOpts.onElicitation, queryOpts.callMcpTool);
|
|
1483
|
+
var handle = createWorkerQueryHandle(worker, queryOpts.canUseTool, queryOpts.onElicitation, queryOpts.callMcpTool, queryOpts.onUserDialog);
|
|
1367
1484
|
|
|
1368
1485
|
// Wait for worker to be ready before sending query_start
|
|
1369
1486
|
if (!reusingWorker) {
|
|
@@ -1390,6 +1507,7 @@ function createClaudeAdapter(opts) {
|
|
|
1390
1507
|
if (claudeOpts.settings) queryOptions.settings = claudeOpts.settings;
|
|
1391
1508
|
|
|
1392
1509
|
if (queryOpts.toolServerDescriptors) queryOptions.mcpServerDescriptors = queryOpts.toolServerDescriptors;
|
|
1510
|
+
if (queryOpts.onUserDialog) queryOptions.supportedDialogKinds = SUPPORTED_DIALOG_KINDS;
|
|
1393
1511
|
if (queryOpts.model) queryOptions.model = queryOpts.model;
|
|
1394
1512
|
if (queryOpts.effort) queryOptions.effort = queryOpts.effort;
|
|
1395
1513
|
if (queryOpts.resumeSessionId) queryOptions.resume = queryOpts.resumeSessionId;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clay-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.45.0-beta.1",
|
|
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",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"homepage": "https://github.com/chadbyte/clay#readme",
|
|
49
49
|
"author": "Chad",
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@anthropic-ai/claude-agent-sdk": "^0.
|
|
51
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.196",
|
|
52
52
|
"@lydell/node-pty": "^1.2.0-beta.3",
|
|
53
53
|
"@openai/codex": "^0.124.0",
|
|
54
54
|
"imapflow": "^1.3.1",
|