clay-server 2.32.0-beta.6 → 2.32.0-beta.8
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/codex-defaults.js +18 -0
- package/lib/project-connection.js +5 -4
- package/lib/project-mate-interaction.js +30 -0
- package/lib/project-notifications.js +9 -0
- package/lib/project-sessions.js +7 -6
- package/lib/project.js +29 -9
- package/lib/public/app.js +5 -0
- package/lib/public/css/input.css +146 -3
- package/lib/public/css/notifications-center.css +7 -0
- package/lib/public/css/tooltip.css +47 -0
- package/lib/public/index.html +34 -4
- package/lib/public/modules/app-dm.js +5 -0
- package/lib/public/modules/app-messages.js +5 -4
- package/lib/public/modules/app-notifications.js +42 -26
- package/lib/public/modules/app-panels.js +3 -3
- package/lib/public/modules/context-sources.js +92 -27
- package/lib/public/modules/input.js +36 -0
- package/lib/public/modules/terminal.js +12 -0
- package/lib/public/modules/tools.js +4 -4
- package/lib/public/modules/tooltip.js +32 -5
- package/lib/sdk-bridge.js +7 -3
- package/lib/sdk-message-processor.js +9 -0
- package/lib/sessions.js +24 -2
- package/lib/yoke/adapters/claude.js +13 -0
- package/lib/yoke/adapters/codex.js +119 -8
- package/package.json +1 -1
|
@@ -895,9 +895,18 @@ function createWorkerQueryHandle(worker, canUseTool, onElicitation) {
|
|
|
895
895
|
|
|
896
896
|
// --- Adapter factory ---
|
|
897
897
|
|
|
898
|
+
function resolveClaudeBinaryPath() {
|
|
899
|
+
try {
|
|
900
|
+
var result = require("child_process").execSync("which claude", { encoding: "utf8", timeout: 5000 }).trim();
|
|
901
|
+
if (result && fs.existsSync(result)) return result;
|
|
902
|
+
} catch (e) {}
|
|
903
|
+
return null;
|
|
904
|
+
}
|
|
905
|
+
|
|
898
906
|
function createClaudeAdapter(opts) {
|
|
899
907
|
var _cwd = (opts && opts.cwd) || process.cwd();
|
|
900
908
|
var _cachedModels = [];
|
|
909
|
+
var _claudeBinaryPath = resolveClaudeBinaryPath();
|
|
901
910
|
|
|
902
911
|
// Path to the worker script (for OS-level user isolation)
|
|
903
912
|
var workerScriptPath = path.join(__dirname, "claude-worker.js");
|
|
@@ -935,6 +944,7 @@ function createClaudeAdapter(opts) {
|
|
|
935
944
|
settingSources: ["user", "project", "local"],
|
|
936
945
|
abortController: ac,
|
|
937
946
|
};
|
|
947
|
+
if (_claudeBinaryPath) warmupOptions.pathToClaudeCodeExecutable = _claudeBinaryPath;
|
|
938
948
|
|
|
939
949
|
if (initOpts && initOpts.dangerouslySkipPermissions) {
|
|
940
950
|
warmupOptions.permissionMode = "bypassPermissions";
|
|
@@ -1069,6 +1079,7 @@ function createClaudeAdapter(opts) {
|
|
|
1069
1079
|
cwd: queryOpts.cwd || _cwd,
|
|
1070
1080
|
abortController: ac,
|
|
1071
1081
|
};
|
|
1082
|
+
if (_claudeBinaryPath) sdkOptions.pathToClaudeCodeExecutable = _claudeBinaryPath;
|
|
1072
1083
|
|
|
1073
1084
|
// YOKE standard options -> SDK options
|
|
1074
1085
|
if (queryOpts.systemPrompt) sdkOptions.systemPrompt = queryOpts.systemPrompt;
|
|
@@ -1346,6 +1357,7 @@ function createClaudeAdapter(opts) {
|
|
|
1346
1357
|
settingSources: ["user", "project", "local"],
|
|
1347
1358
|
abortController: ac,
|
|
1348
1359
|
};
|
|
1360
|
+
if (_claudeBinaryPath) warmupOptions.pathToClaudeCodeExecutable = _claudeBinaryPath;
|
|
1349
1361
|
|
|
1350
1362
|
if (initOpts && initOpts.dangerouslySkipPermissions) {
|
|
1351
1363
|
warmupOptions.permissionMode = "bypassPermissions";
|
|
@@ -1419,6 +1431,7 @@ function createClaudeAdapter(opts) {
|
|
|
1419
1431
|
}
|
|
1420
1432
|
|
|
1421
1433
|
var warmupOptions = { cwd: workerCwd, settingSources: ["user", "project", "local"] };
|
|
1434
|
+
if (_claudeBinaryPath) warmupOptions.pathToClaudeCodeExecutable = _claudeBinaryPath;
|
|
1422
1435
|
if (initOpts && initOpts.dangerouslySkipPermissions) {
|
|
1423
1436
|
warmupOptions.permissionMode = "bypassPermissions";
|
|
1424
1437
|
warmupOptions.allowDangerouslySkipPermissions = true;
|
|
@@ -3,8 +3,59 @@
|
|
|
3
3
|
// Implements the YOKE interface using codex app-server protocol.
|
|
4
4
|
// Bidirectional JSON-RPC over stdin/stdout enables interactive approval flows.
|
|
5
5
|
|
|
6
|
+
var path = require("path");
|
|
7
|
+
var fs = require("fs");
|
|
6
8
|
var { CodexAppServer } = require("../codex-app-server");
|
|
7
9
|
|
|
10
|
+
// --- Claude skill discovery ---
|
|
11
|
+
// Finds Claude skills in ~/.claude/skills/ and <cwd>/.claude/skills/
|
|
12
|
+
// so Codex can recognize $<skill-name> in user input.
|
|
13
|
+
function discoverClaudeSkills(cwd) {
|
|
14
|
+
var skills = {};
|
|
15
|
+
var REAL_HOME;
|
|
16
|
+
try { REAL_HOME = require("../../config").REAL_HOME; } catch (e) { REAL_HOME = require("os").homedir(); }
|
|
17
|
+
var dirs = [
|
|
18
|
+
path.join(REAL_HOME, ".claude", "skills"),
|
|
19
|
+
path.join(cwd || "", ".claude", "skills"),
|
|
20
|
+
];
|
|
21
|
+
for (var d = 0; d < dirs.length; d++) {
|
|
22
|
+
var base = dirs[d];
|
|
23
|
+
if (!base) continue;
|
|
24
|
+
var entries;
|
|
25
|
+
try { entries = fs.readdirSync(base, { withFileTypes: true }); } catch (e) { continue; }
|
|
26
|
+
for (var i = 0; i < entries.length; i++) {
|
|
27
|
+
var entry = entries[i];
|
|
28
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
29
|
+
var skillMd = path.join(base, entry.name, "SKILL.md");
|
|
30
|
+
try {
|
|
31
|
+
fs.accessSync(skillMd, fs.constants.R_OK);
|
|
32
|
+
// project skills override global skills
|
|
33
|
+
skills[entry.name] = skillMd;
|
|
34
|
+
} catch (e) {}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return skills;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Parse user text for $<skill-name> references.
|
|
41
|
+
// Returns { text, skills: [{ name, path }] }
|
|
42
|
+
function parseSkillRefs(text, availableSkills) {
|
|
43
|
+
if (typeof text !== "string") return { text: text, skills: [] };
|
|
44
|
+
var skills = [];
|
|
45
|
+
var seen = {};
|
|
46
|
+
var re = /\$([a-zA-Z0-9_-]+)/g;
|
|
47
|
+
var match;
|
|
48
|
+
while ((match = re.exec(text)) !== null) {
|
|
49
|
+
var name = match[1];
|
|
50
|
+
if (seen[name]) continue;
|
|
51
|
+
if (availableSkills[name]) {
|
|
52
|
+
seen[name] = true;
|
|
53
|
+
skills.push({ name: name, path: availableSkills[name] });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { text: text, skills: skills };
|
|
57
|
+
}
|
|
58
|
+
|
|
8
59
|
// --- Event flattening ---
|
|
9
60
|
// Converts app-server JSON-RPC notifications into flat objects with a yokeType field.
|
|
10
61
|
//
|
|
@@ -463,13 +514,15 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
463
514
|
var cmdParams = msg.params || {};
|
|
464
515
|
if (canUseTool) {
|
|
465
516
|
canUseTool("Bash", { command: cmdParams.command }, {}).then(function(decision) {
|
|
466
|
-
|
|
517
|
+
var approved = isApproved(decision);
|
|
518
|
+
// Response must be wrapped in { decision: ... } object per app-server protocol
|
|
519
|
+
appServer.respond(msg.id, { decision: approved ? "accept" : "decline" });
|
|
467
520
|
}).catch(function(err) {
|
|
468
521
|
console.error("[yoke/codex] canUseTool error:", err.message);
|
|
469
|
-
appServer.respond(msg.id, "decline");
|
|
522
|
+
appServer.respond(msg.id, { decision: "decline" });
|
|
470
523
|
});
|
|
471
524
|
} else {
|
|
472
|
-
appServer.respond(msg.id, "accept");
|
|
525
|
+
appServer.respond(msg.id, { decision: "accept" });
|
|
473
526
|
}
|
|
474
527
|
return;
|
|
475
528
|
}
|
|
@@ -480,13 +533,13 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
480
533
|
if (canUseTool) {
|
|
481
534
|
var changeInfo = (fcParams.changes || []).map(function(c) { return c.kind + " " + c.path; }).join(", ");
|
|
482
535
|
canUseTool("Edit", { changes: changeInfo, path: fcParams.path }, {}).then(function(decision) {
|
|
483
|
-
appServer.respond(msg.id, isApproved(decision) ? "accept" : "decline");
|
|
536
|
+
appServer.respond(msg.id, { decision: isApproved(decision) ? "accept" : "decline" });
|
|
484
537
|
}).catch(function(err) {
|
|
485
538
|
console.error("[yoke/codex] canUseTool error:", err.message);
|
|
486
|
-
appServer.respond(msg.id, "decline");
|
|
539
|
+
appServer.respond(msg.id, { decision: "decline" });
|
|
487
540
|
});
|
|
488
541
|
} else {
|
|
489
|
-
appServer.respond(msg.id, "accept");
|
|
542
|
+
appServer.respond(msg.id, { decision: "accept" });
|
|
490
543
|
}
|
|
491
544
|
return;
|
|
492
545
|
}
|
|
@@ -584,6 +637,26 @@ function createCodexQueryHandle(appServer, queryOpts) {
|
|
|
584
637
|
input = currentMessage;
|
|
585
638
|
}
|
|
586
639
|
|
|
640
|
+
// Detect $<skill-name> references (Claude skills) and inject skill input items
|
|
641
|
+
var availableSkills = discoverClaudeSkills(queryOpts.cwd);
|
|
642
|
+
var skillItemsToInject = [];
|
|
643
|
+
var injected = {};
|
|
644
|
+
for (var ii = 0; ii < input.length; ii++) {
|
|
645
|
+
if (input[ii].type === "text" && input[ii].text) {
|
|
646
|
+
var parsed = parseSkillRefs(input[ii].text, availableSkills);
|
|
647
|
+
for (var si = 0; si < parsed.skills.length; si++) {
|
|
648
|
+
if (!injected[parsed.skills[si].name]) {
|
|
649
|
+
injected[parsed.skills[si].name] = true;
|
|
650
|
+
skillItemsToInject.push({ type: "skill", name: parsed.skills[si].name, path: parsed.skills[si].path });
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
if (skillItemsToInject.length > 0) {
|
|
656
|
+
console.log("[yoke/codex] injecting Claude skills:", skillItemsToInject.map(function(s) { return s.name; }).join(", "));
|
|
657
|
+
input = input.concat(skillItemsToInject);
|
|
658
|
+
}
|
|
659
|
+
|
|
587
660
|
await appServer.send("turn/start", {
|
|
588
661
|
threadId: state.threadId,
|
|
589
662
|
input: input,
|
|
@@ -850,13 +923,51 @@ function createCodexAdapter(opts) {
|
|
|
850
923
|
"gpt-5.2",
|
|
851
924
|
];
|
|
852
925
|
|
|
926
|
+
// Discover skills: built-in Codex skills + Claude skills
|
|
927
|
+
var skillNames = [];
|
|
928
|
+
try {
|
|
929
|
+
var REAL_HOME;
|
|
930
|
+
try { REAL_HOME = require("../../config").REAL_HOME; } catch (e) { REAL_HOME = require("os").homedir(); }
|
|
931
|
+
var claudeSkillsDir = require("path").join(REAL_HOME, ".claude", "skills");
|
|
932
|
+
var extraRoots = _cwd ? [{ cwd: _cwd, extraUserRoots: [claudeSkillsDir] }] : [];
|
|
933
|
+
var skillsResult = await _appServer.send("skills/list", {
|
|
934
|
+
cwds: _cwd ? [_cwd] : [],
|
|
935
|
+
forceReload: true,
|
|
936
|
+
perCwdExtraUserRoots: extraRoots,
|
|
937
|
+
}, 10000).catch(function(e) {
|
|
938
|
+
console.error("[codex] skills/list failed:", e.message);
|
|
939
|
+
return null;
|
|
940
|
+
});
|
|
941
|
+
// Response shape: { data: [{ cwd, skills: [{ name, ... }] }] }
|
|
942
|
+
if (skillsResult && skillsResult.data) {
|
|
943
|
+
for (var di = 0; di < skillsResult.data.length; di++) {
|
|
944
|
+
var entry = skillsResult.data[di];
|
|
945
|
+
if (!entry.skills) continue;
|
|
946
|
+
for (var sk = 0; sk < entry.skills.length; sk++) {
|
|
947
|
+
if (entry.skills[sk].name && skillNames.indexOf(entry.skills[sk].name) === -1) {
|
|
948
|
+
skillNames.push(entry.skills[sk].name);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
// Also discover Claude skills directly as fallback
|
|
954
|
+
var claudeSkills = discoverClaudeSkills(_cwd);
|
|
955
|
+
var claudeSkillNames = Object.keys(claudeSkills);
|
|
956
|
+
for (var csn = 0; csn < claudeSkillNames.length; csn++) {
|
|
957
|
+
if (skillNames.indexOf(claudeSkillNames[csn]) === -1) skillNames.push(claudeSkillNames[csn]);
|
|
958
|
+
}
|
|
959
|
+
console.log("[codex] Discovered skills:", skillNames.length, "(" + skillNames.slice(0, 5).join(", ") + (skillNames.length > 5 ? "..." : "") + ")");
|
|
960
|
+
} catch (e) {
|
|
961
|
+
console.error("[codex] Failed to discover skills:", e.message);
|
|
962
|
+
}
|
|
963
|
+
|
|
853
964
|
_initPromise = null;
|
|
854
965
|
|
|
855
966
|
return {
|
|
856
967
|
models: _cachedModels,
|
|
857
968
|
defaultModel: "gpt-5.4",
|
|
858
|
-
skills:
|
|
859
|
-
slashCommands:
|
|
969
|
+
skills: skillNames,
|
|
970
|
+
slashCommands: skillNames,
|
|
860
971
|
fastModeState: null,
|
|
861
972
|
capabilities: {
|
|
862
973
|
thinking: true,
|