claude-relay 2.4.1 → 2.4.3

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 CHANGED
@@ -4,6 +4,10 @@
4
4
  if (!Symbol.dispose) Symbol.dispose = Symbol("Symbol.dispose");
5
5
  if (!Symbol.asyncDispose) Symbol.asyncDispose = Symbol("Symbol.asyncDispose");
6
6
 
7
+ // Remove CLAUDECODE env var so the SDK can spawn Claude Code child processes
8
+ // (prevents "cannot be launched inside another Claude Code session" error)
9
+ delete process.env.CLAUDECODE;
10
+
7
11
  var fs = require("fs");
8
12
  var path = require("path");
9
13
  var { loadConfig, saveConfig, socketPath, generateSlug, syncClayrc, writeCrashInfo, readCrashInfo, clearCrashInfo } = require("./config");
package/lib/sdk-bridge.js CHANGED
@@ -1,4 +1,7 @@
1
1
  const crypto = require("crypto");
2
+ var fs = require("fs");
3
+ var path = require("path");
4
+ var os = require("os");
2
5
 
3
6
  // Async message queue for streaming input to SDK
4
7
  function createMessageQueue() {
@@ -50,6 +53,53 @@ function createSDKBridge(opts) {
50
53
  var getSDK = opts.getSDK;
51
54
  var dangerouslySkipPermissions = opts.dangerouslySkipPermissions || false;
52
55
 
56
+ // --- Skill discovery helpers ---
57
+
58
+ function discoverSkillDirs() {
59
+ var skills = {};
60
+ var dirs = [
61
+ path.join(os.homedir(), ".claude", "skills"),
62
+ path.join(cwd, ".claude", "skills"),
63
+ ];
64
+ for (var d = 0; d < dirs.length; d++) {
65
+ var base = dirs[d];
66
+ var entries;
67
+ try {
68
+ entries = fs.readdirSync(base, { withFileTypes: true });
69
+ } catch (e) {
70
+ continue; // directory doesn't exist
71
+ }
72
+ for (var i = 0; i < entries.length; i++) {
73
+ var entry = entries[i];
74
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
75
+ var skillDir = path.join(base, entry.name);
76
+ var skillMd = path.join(skillDir, "SKILL.md");
77
+ try {
78
+ fs.accessSync(skillMd, fs.constants.R_OK);
79
+ // project skills override global skills with same name
80
+ skills[entry.name] = skillDir;
81
+ } catch (e) {
82
+ // no SKILL.md, skip
83
+ }
84
+ }
85
+ }
86
+ return skills;
87
+ }
88
+
89
+ function mergeSkills(sdkSkills, fsSkills) {
90
+ var merged = new Set();
91
+ if (Array.isArray(sdkSkills)) {
92
+ for (var i = 0; i < sdkSkills.length; i++) {
93
+ merged.add(sdkSkills[i]);
94
+ }
95
+ }
96
+ var fsNames = Object.keys(fsSkills);
97
+ for (var i = 0; i < fsNames.length; i++) {
98
+ merged.add(fsNames[i]);
99
+ }
100
+ return merged;
101
+ }
102
+
53
103
  function sendAndRecord(session, obj) {
54
104
  sm.sendAndRecord(session, obj);
55
105
  }
@@ -79,13 +129,20 @@ function createSDKBridge(opts) {
79
129
 
80
130
  // Cache slash_commands and model from CLI init message
81
131
  if (parsed.type === "system" && parsed.subtype === "init") {
82
- if (parsed.skills) {
83
- sm.skillNames = new Set(parsed.skills);
84
- }
132
+ var fsSkills = discoverSkillDirs();
133
+ sm.skillNames = mergeSkills(parsed.skills, fsSkills);
85
134
  if (parsed.slash_commands) {
86
- sm.slashCommands = parsed.slash_commands.filter(function(name) {
87
- return !sm.skillNames || !sm.skillNames.has(name);
88
- });
135
+ // Union: SDK slash_commands + merged skills (deduplicated)
136
+ var seen = new Set();
137
+ var combined = [];
138
+ var all = parsed.slash_commands.concat(Array.from(sm.skillNames));
139
+ for (var k = 0; k < all.length; k++) {
140
+ if (!seen.has(all[k])) {
141
+ seen.add(all[k]);
142
+ combined.push(all[k]);
143
+ }
144
+ }
145
+ sm.slashCommands = combined;
89
146
  send({ type: "slash_commands", commands: sm.slashCommands });
90
147
  }
91
148
  if (parsed.model) {
@@ -649,13 +706,20 @@ function createSDKBridge(opts) {
649
706
  });
650
707
  for await (var msg of stream) {
651
708
  if (msg.type === "system" && msg.subtype === "init") {
652
- if (msg.skills) {
653
- sm.skillNames = new Set(msg.skills);
654
- }
709
+ var fsSkills = discoverSkillDirs();
710
+ sm.skillNames = mergeSkills(msg.skills, fsSkills);
655
711
  if (msg.slash_commands) {
656
- sm.slashCommands = msg.slash_commands.filter(function(name) {
657
- return !sm.skillNames || !sm.skillNames.has(name);
658
- });
712
+ // Union: SDK slash_commands + merged skills (deduplicated)
713
+ var seen = new Set();
714
+ var combined = [];
715
+ var all = msg.slash_commands.concat(Array.from(sm.skillNames));
716
+ for (var k = 0; k < all.length; k++) {
717
+ if (!seen.has(all[k])) {
718
+ seen.add(all[k]);
719
+ combined.push(all[k]);
720
+ }
721
+ }
722
+ sm.slashCommands = combined;
659
723
  send({ type: "slash_commands", commands: sm.slashCommands });
660
724
  }
661
725
  if (msg.model) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-relay",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "Web UI for Claude Code. Any device. Push notifications.",
5
5
  "bin": {
6
6
  "claude-relay": "./bin/cli.js"