squad-openclaw 2026.2.1817 → 2026.2.1902
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/dist/index.js +94 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,6 +20,20 @@ function debounced(key, fn) {
|
|
|
20
20
|
}, DEBOUNCE_MS)
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
|
+
var fsDebounceTimers = /* @__PURE__ */ new Map();
|
|
24
|
+
var FS_DEBOUNCE_MS = 300;
|
|
25
|
+
function debouncedFs(relPath, action, fn) {
|
|
26
|
+
const key = `fs:${action}:${relPath}`;
|
|
27
|
+
const existing = fsDebounceTimers.get(key);
|
|
28
|
+
if (existing) clearTimeout(existing);
|
|
29
|
+
fsDebounceTimers.set(
|
|
30
|
+
key,
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
fsDebounceTimers.delete(key);
|
|
33
|
+
fn();
|
|
34
|
+
}, FS_DEBOUNCE_MS)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
23
37
|
function isWorkspaceIdentity(filePath, configDir) {
|
|
24
38
|
const rel = path.relative(configDir, filePath);
|
|
25
39
|
const match = rel.match(/^(workspace(?:-([^/]+))?)\/IDENTITY\.md$/);
|
|
@@ -126,7 +140,7 @@ function updatePlugin(pluginDirName, configDir) {
|
|
|
126
140
|
registryDelete(`plugin:${pluginDirName}`);
|
|
127
141
|
}
|
|
128
142
|
}
|
|
129
|
-
function startWatcher(configDir) {
|
|
143
|
+
function startWatcher(configDir, onFsChange) {
|
|
130
144
|
const watcher = chokidar.watch(configDir, {
|
|
131
145
|
persistent: true,
|
|
132
146
|
usePolling: false,
|
|
@@ -141,7 +155,15 @@ function startWatcher(configDir) {
|
|
|
141
155
|
"**/data/**"
|
|
142
156
|
]
|
|
143
157
|
});
|
|
144
|
-
const
|
|
158
|
+
const emitFsChange = (action, filePath) => {
|
|
159
|
+
if (!onFsChange) return;
|
|
160
|
+
const rel = path.relative(configDir, filePath);
|
|
161
|
+
debouncedFs(rel, action, () => {
|
|
162
|
+
onFsChange({ action, path: rel });
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
const handleChange = (filePath, action) => {
|
|
166
|
+
emitFsChange(action, filePath);
|
|
145
167
|
const identity = isWorkspaceIdentity(filePath, configDir);
|
|
146
168
|
if (identity) {
|
|
147
169
|
debounced(
|
|
@@ -172,6 +194,7 @@ function startWatcher(configDir) {
|
|
|
172
194
|
}
|
|
173
195
|
};
|
|
174
196
|
const handleAddDir = (dirPath) => {
|
|
197
|
+
emitFsChange("addDir", dirPath);
|
|
175
198
|
const globalSkill = isGlobalSkillDir(dirPath, configDir);
|
|
176
199
|
if (globalSkill) {
|
|
177
200
|
debounced(
|
|
@@ -195,6 +218,7 @@ function startWatcher(configDir) {
|
|
|
195
218
|
}
|
|
196
219
|
};
|
|
197
220
|
const handleUnlinkDir = (dirPath) => {
|
|
221
|
+
emitFsChange("unlinkDir", dirPath);
|
|
198
222
|
const rel = path.relative(configDir, dirPath);
|
|
199
223
|
const wsMatch = rel.match(/^workspace(?:-([^/]+))?$/);
|
|
200
224
|
if (wsMatch) {
|
|
@@ -213,9 +237,9 @@ function startWatcher(configDir) {
|
|
|
213
237
|
return;
|
|
214
238
|
}
|
|
215
239
|
};
|
|
216
|
-
watcher.on("add", handleChange);
|
|
217
|
-
watcher.on("change", handleChange);
|
|
218
|
-
watcher.on("unlink", handleChange);
|
|
240
|
+
watcher.on("add", (fp) => handleChange(fp, "add"));
|
|
241
|
+
watcher.on("change", (fp) => handleChange(fp, "change"));
|
|
242
|
+
watcher.on("unlink", (fp) => handleChange(fp, "unlink"));
|
|
219
243
|
watcher.on("addDir", handleAddDir);
|
|
220
244
|
watcher.on("unlinkDir", handleUnlinkDir);
|
|
221
245
|
return () => {
|
|
@@ -223,6 +247,10 @@ function startWatcher(configDir) {
|
|
|
223
247
|
clearTimeout(timer);
|
|
224
248
|
}
|
|
225
249
|
debounceTimers.clear();
|
|
250
|
+
for (const timer of fsDebounceTimers.values()) {
|
|
251
|
+
clearTimeout(timer);
|
|
252
|
+
}
|
|
253
|
+
fsDebounceTimers.clear();
|
|
226
254
|
watcher.close();
|
|
227
255
|
};
|
|
228
256
|
}
|
|
@@ -500,7 +528,7 @@ function fullScan(configDir) {
|
|
|
500
528
|
scanTools(configDir);
|
|
501
529
|
scanMedia(configDir);
|
|
502
530
|
}
|
|
503
|
-
function registerEntityTools(api) {
|
|
531
|
+
function registerEntityTools(api, onFsChange) {
|
|
504
532
|
const configDir = process.env.HOME + "/.openclaw";
|
|
505
533
|
api.registerTool({
|
|
506
534
|
name: "entity_list",
|
|
@@ -576,7 +604,7 @@ function registerEntityTools(api) {
|
|
|
576
604
|
}
|
|
577
605
|
let stopWatcher = null;
|
|
578
606
|
try {
|
|
579
|
-
stopWatcher = startWatcher(configDir);
|
|
607
|
+
stopWatcher = startWatcher(configDir, onFsChange);
|
|
580
608
|
} catch (err2) {
|
|
581
609
|
console.error("[squad-openclaw] Watcher failed to start:", err2);
|
|
582
610
|
}
|
|
@@ -773,6 +801,34 @@ function registerFilesystemTools(api) {
|
|
|
773
801
|
}
|
|
774
802
|
}
|
|
775
803
|
});
|
|
804
|
+
api.registerTool({
|
|
805
|
+
name: "fs_mkdir",
|
|
806
|
+
label: "Create Directory",
|
|
807
|
+
description: "Create a directory on the server filesystem. Creates parent directories as needed. Supports ~ for home directory expansion.",
|
|
808
|
+
parameters: {
|
|
809
|
+
type: "object",
|
|
810
|
+
properties: {
|
|
811
|
+
path: {
|
|
812
|
+
type: "string",
|
|
813
|
+
description: "Absolute or ~-prefixed path of the directory to create"
|
|
814
|
+
}
|
|
815
|
+
},
|
|
816
|
+
required: ["path"]
|
|
817
|
+
},
|
|
818
|
+
async execute(_id, params) {
|
|
819
|
+
try {
|
|
820
|
+
const targetPath = validatePath(params.path, allowedRoots);
|
|
821
|
+
fs3.mkdirSync(targetPath, { recursive: true });
|
|
822
|
+
return ok({
|
|
823
|
+
path: targetPath,
|
|
824
|
+
created: true
|
|
825
|
+
});
|
|
826
|
+
} catch (e) {
|
|
827
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
828
|
+
return err(`fs_mkdir failed: ${msg}`);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
});
|
|
776
832
|
api.registerTool({
|
|
777
833
|
name: "fs_delete",
|
|
778
834
|
label: "Delete File or Directory",
|
|
@@ -1008,7 +1064,8 @@ function readOperatorToken() {
|
|
|
1008
1064
|
return null;
|
|
1009
1065
|
}
|
|
1010
1066
|
}
|
|
1011
|
-
var
|
|
1067
|
+
var RELAY_DATA_DIR = path5.join(os.homedir(), ".openclaw", "squad-ceo-data");
|
|
1068
|
+
var RELAY_STATE_PATH = path5.join(RELAY_DATA_DIR, "squad-relay.json");
|
|
1012
1069
|
function readRelayState() {
|
|
1013
1070
|
try {
|
|
1014
1071
|
const raw = fs5.readFileSync(RELAY_STATE_PATH, "utf-8");
|
|
@@ -1018,9 +1075,8 @@ function readRelayState() {
|
|
|
1018
1075
|
}
|
|
1019
1076
|
}
|
|
1020
1077
|
function writeRelayState(state) {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
fs5.mkdirSync(dir, { recursive: true });
|
|
1078
|
+
if (!fs5.existsSync(RELAY_DATA_DIR)) {
|
|
1079
|
+
fs5.mkdirSync(RELAY_DATA_DIR, { recursive: true });
|
|
1024
1080
|
}
|
|
1025
1081
|
fs5.writeFileSync(RELAY_STATE_PATH, JSON.stringify(state, null, 2), { mode: 384 });
|
|
1026
1082
|
}
|
|
@@ -1520,6 +1576,28 @@ var RelayClient = class {
|
|
|
1520
1576
|
} catch {
|
|
1521
1577
|
}
|
|
1522
1578
|
}
|
|
1579
|
+
/** Broadcast an event to all connected users, E2E encrypted per-user */
|
|
1580
|
+
broadcastToUsers(event, payload) {
|
|
1581
|
+
const msg = { type: "event", event, payload };
|
|
1582
|
+
for (const [userId, conn] of this.userConnections) {
|
|
1583
|
+
if (!conn.connectHandshakeComplete) continue;
|
|
1584
|
+
let innerMsg = msg;
|
|
1585
|
+
if (conn.e2e) {
|
|
1586
|
+
try {
|
|
1587
|
+
const encrypted = conn.e2e.encrypt(JSON.stringify(msg));
|
|
1588
|
+
innerMsg = { _e2e: true, ...encrypted };
|
|
1589
|
+
} catch (err2) {
|
|
1590
|
+
console.error(`[relay-client] E2E encrypt error for broadcast to ${userId}:`, err2);
|
|
1591
|
+
innerMsg = msg;
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
this.sendToRelay({
|
|
1595
|
+
type: "relay.forward",
|
|
1596
|
+
userId,
|
|
1597
|
+
inner: innerMsg
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1523
1601
|
};
|
|
1524
1602
|
var relayClient = null;
|
|
1525
1603
|
function startRelayClient(api, relayUrl) {
|
|
@@ -1547,6 +1625,9 @@ function startRelayClient(api, relayUrl) {
|
|
|
1547
1625
|
process.on("SIGTERM", cleanup);
|
|
1548
1626
|
process.on("SIGINT", cleanup);
|
|
1549
1627
|
}
|
|
1628
|
+
function broadcastToUsers(event, payload) {
|
|
1629
|
+
relayClient?.broadcastToUsers(event, payload);
|
|
1630
|
+
}
|
|
1550
1631
|
|
|
1551
1632
|
// src/index.ts
|
|
1552
1633
|
function squadAppPlugin(api) {
|
|
@@ -1558,7 +1639,8 @@ function squadAppPlugin(api) {
|
|
|
1558
1639
|
}
|
|
1559
1640
|
return origRegisterTool(toolDef);
|
|
1560
1641
|
};
|
|
1561
|
-
|
|
1642
|
+
const onFsChange = (evt) => broadcastToUsers("fs.change", evt);
|
|
1643
|
+
registerEntityTools(api, onFsChange);
|
|
1562
1644
|
registerFilesystemTools(api);
|
|
1563
1645
|
registerVersionMethods(api);
|
|
1564
1646
|
api.registerGatewayMethod(
|
package/package.json
CHANGED