squad-openclaw 2026.2.1903 → 2026.2.1905

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.d.ts CHANGED
@@ -3,9 +3,34 @@
3
3
  *
4
4
  * Provides:
5
5
  * - In-memory entity registry with filesystem watching (entity_list, entity_search, entity_sync)
6
- * - Filesystem tools for remote clients (fs_read, fs_write, fs_list, fs_delete)
6
+ * - Filesystem tools for remote clients (fs_read, fs_write, fs_list, fs_delete, fs_rename)
7
+ * - Restricted SQL query tool (sql_query) — sqlite3 only, squad-ceo-data/ only
7
8
  * - Version check and self-update gateway methods (squad.version.*)
8
9
  * - Cloud relay client for remote browser access (relay-client)
10
+ *
11
+ * ┌──────────────────────────────────────────────────────────────────────────┐
12
+ * │ SECURITY POLICY — Credential Protection │
13
+ * │ │
14
+ * │ This plugin enforces hard-coded security rules in filesystem.ts: │
15
+ * │ │
16
+ * │ BLOCKED directories (no read, write, list, delete, or rename): │
17
+ * │ • ~/.openclaw/credentials/ │
18
+ * │ • ~/.openclaw/devices/ │
19
+ * │ • ~/.openclaw/identity/ │
20
+ * │ │
21
+ * │ REDACTED on read (sensitive fields replaced with "[REDACTED]"): │
22
+ * │ • ~/.openclaw/openclaw.json → channel.*.botToken │
23
+ * │ • ~/.openclaw/openclaw.json → gateway.auth.* │
24
+ * │ • squad-ceo-data/squad-relay.json → deviceKeys.privateKeyPem │
25
+ * │ │
26
+ * │ WRITE-PROTECTED (no writes, deletes, or renames): │
27
+ * │ • ~/.openclaw/openclaw.json │
28
+ * │ • squad-ceo-data/squad-relay.json │
29
+ * │ • All blocked directories above │
30
+ * │ │
31
+ * │ The bundle is NOT minified to allow security auditing of the │
32
+ * │ distributed code. See tsup.config.ts for build configuration. │
33
+ * └──────────────────────────────────────────────────────────────────────────┘
9
34
  */
10
35
  declare function squadAppPlugin(api: any): void;
11
36
 
package/dist/index.js CHANGED
@@ -618,9 +618,78 @@ function registerEntityTools(api, onFsChange) {
618
618
  // src/filesystem.ts
619
619
  import fs3 from "fs";
620
620
  import path3 from "path";
621
+ var HOME_DIR = process.env.HOME ?? "/root";
622
+ var OPENCLAW_DIR = path3.join(HOME_DIR, ".openclaw");
623
+ var SENSITIVE_BLOCKED_DIRS = [
624
+ path3.join(OPENCLAW_DIR, "credentials"),
625
+ path3.join(OPENCLAW_DIR, "devices"),
626
+ path3.join(OPENCLAW_DIR, "identity")
627
+ ];
628
+ var SENSITIVE_BLOCKED_FILES = [
629
+ path3.join(OPENCLAW_DIR, "squad-ceo-data", "squad-relay.json")
630
+ ];
631
+ function isSensitivePath(resolvedPath) {
632
+ for (const blocked of SENSITIVE_BLOCKED_DIRS) {
633
+ if (resolvedPath === blocked || resolvedPath.startsWith(blocked + path3.sep)) {
634
+ return true;
635
+ }
636
+ }
637
+ for (const blocked of SENSITIVE_BLOCKED_FILES) {
638
+ if (resolvedPath === blocked) {
639
+ return true;
640
+ }
641
+ }
642
+ return false;
643
+ }
644
+ var OPENCLAW_JSON_FILENAME = "openclaw.json";
645
+ function redactOpenclawJson(rawContent) {
646
+ let config;
647
+ try {
648
+ config = JSON.parse(rawContent);
649
+ } catch {
650
+ return rawContent;
651
+ }
652
+ let redactedCount = 0;
653
+ const channels = config.channels;
654
+ if (channels && typeof channels === "object") {
655
+ for (const channelKey of Object.keys(channels)) {
656
+ const channel = channels[channelKey];
657
+ if (channel && typeof channel === "object" && "botToken" in channel) {
658
+ channel.botToken = "[REDACTED]";
659
+ redactedCount++;
660
+ }
661
+ }
662
+ }
663
+ const gateway = config.gateway;
664
+ if (gateway && typeof gateway === "object") {
665
+ if (gateway.auth && typeof gateway.auth === "object") {
666
+ const auth = gateway.auth;
667
+ for (const key of Object.keys(auth)) {
668
+ auth[key] = "[REDACTED]";
669
+ redactedCount++;
670
+ }
671
+ }
672
+ if ("token" in gateway) {
673
+ gateway.token = "[REDACTED]";
674
+ redactedCount++;
675
+ }
676
+ const remote = gateway.remote;
677
+ if (remote && typeof remote === "object" && "token" in remote) {
678
+ remote.token = "[REDACTED]";
679
+ redactedCount++;
680
+ }
681
+ }
682
+ if (redactedCount > 0) {
683
+ console.log(`[security] Redacted ${redactedCount} sensitive field(s) from openclaw.json before returning to client`);
684
+ }
685
+ return JSON.stringify(config, null, 2);
686
+ }
687
+ function isOpenclawJson(resolvedPath) {
688
+ return path3.basename(resolvedPath) === OPENCLAW_JSON_FILENAME && resolvedPath.startsWith(OPENCLAW_DIR);
689
+ }
621
690
  function expandHome(p) {
622
691
  if (p.startsWith("~/") || p === "~") {
623
- return path3.join(process.env.HOME ?? "/root", p.slice(1));
692
+ return path3.join(HOME_DIR, p.slice(1));
624
693
  }
625
694
  return p;
626
695
  }
@@ -636,6 +705,24 @@ function validatePath(p, allowedRoots) {
636
705
  }
637
706
  return resolved;
638
707
  }
708
+ function validateAndBlockSensitive(p, allowedRoots) {
709
+ const resolved = validatePath(p, allowedRoots);
710
+ if (isSensitivePath(resolved)) {
711
+ throw new Error(
712
+ `Access denied: path "${p}" is inside a protected directory (credentials/devices/identity)`
713
+ );
714
+ }
715
+ return resolved;
716
+ }
717
+ function validateWritePath(p, allowedRoots) {
718
+ const resolved = validateAndBlockSensitive(p, allowedRoots);
719
+ if (isOpenclawJson(resolved)) {
720
+ throw new Error(
721
+ `Write denied: "${p}" is a protected configuration file (openclaw.json)`
722
+ );
723
+ }
724
+ return resolved;
725
+ }
639
726
  function ok(data) {
640
727
  return {
641
728
  content: [{ type: "text", text: JSON.stringify(data) }]
@@ -674,12 +761,20 @@ function listDir(dirPath, opts) {
674
761
  }
675
762
  return results;
676
763
  }
764
+ function filterSensitiveEntries(entries) {
765
+ return entries.filter((entry) => !isSensitivePath(entry.path)).map((entry) => {
766
+ if (entry.children) {
767
+ return { ...entry, children: filterSensitiveEntries(entry.children) };
768
+ }
769
+ return entry;
770
+ });
771
+ }
677
772
  function registerFilesystemTools(api) {
678
773
  const allowedRoots = api.pluginConfig?.["fs.allowedRoots"] ?? [];
679
774
  api.registerTool({
680
775
  name: "fs_read",
681
776
  label: "Read File",
682
- description: "Read a file from the server filesystem. Returns the file contents as text. Supports ~ for home directory expansion.",
777
+ description: "Read a file from the server filesystem. Returns the file contents as text. Supports ~ for home directory expansion. Sensitive directories (credentials, devices, identity) are blocked. Config files are returned with auth tokens redacted.",
683
778
  parameters: {
684
779
  type: "object",
685
780
  properties: {
@@ -697,10 +792,13 @@ function registerFilesystemTools(api) {
697
792
  },
698
793
  async execute(_id, params) {
699
794
  try {
700
- const filePath = validatePath(params.path, allowedRoots);
795
+ const filePath = validateAndBlockSensitive(params.path, allowedRoots);
701
796
  const encoding = params.encoding ?? "utf-8";
702
- const content = fs3.readFileSync(filePath, encoding);
797
+ let content = fs3.readFileSync(filePath, encoding);
703
798
  const stat = fs3.statSync(filePath);
799
+ if (isOpenclawJson(filePath) && encoding === "utf-8") {
800
+ content = redactOpenclawJson(content);
801
+ }
704
802
  return ok({
705
803
  path: filePath,
706
804
  content,
@@ -716,7 +814,7 @@ function registerFilesystemTools(api) {
716
814
  api.registerTool({
717
815
  name: "fs_write",
718
816
  label: "Write File",
719
- description: "Write content to a file on the server filesystem. Creates parent directories if they don't exist. Supports ~ for home directory expansion.",
817
+ description: "Write content to a file on the server filesystem. Creates parent directories if they don't exist. Supports ~ for home directory expansion. Writes to protected directories (credentials, devices, identity) and config files (openclaw.json) are denied.",
720
818
  parameters: {
721
819
  type: "object",
722
820
  properties: {
@@ -742,7 +840,7 @@ function registerFilesystemTools(api) {
742
840
  },
743
841
  async execute(_id, params) {
744
842
  try {
745
- const filePath = validatePath(params.path, allowedRoots);
843
+ const filePath = validateWritePath(params.path, allowedRoots);
746
844
  const content = params.content;
747
845
  const encoding = params.encoding ?? "utf-8";
748
846
  const mkdir = params.mkdir !== false;
@@ -765,7 +863,7 @@ function registerFilesystemTools(api) {
765
863
  api.registerTool({
766
864
  name: "fs_list",
767
865
  label: "List Directory",
768
- description: "List contents of a directory on the server filesystem. Returns file metadata including name, type, size, and modification time. Supports ~ for home directory expansion.",
866
+ description: "List contents of a directory on the server filesystem. Returns file metadata including name, type, size, and modification time. Supports ~ for home directory expansion. Protected directories (credentials, devices, identity) are excluded from results.",
769
867
  parameters: {
770
868
  type: "object",
771
869
  properties: {
@@ -786,10 +884,11 @@ function registerFilesystemTools(api) {
786
884
  },
787
885
  async execute(_id, params) {
788
886
  try {
789
- const dirPath = validatePath(params.path, allowedRoots);
887
+ const dirPath = validateAndBlockSensitive(params.path, allowedRoots);
790
888
  const recursive = params.recursive === true;
791
889
  const includeHidden = params.includeHidden === true;
792
- const entries = listDir(dirPath, { recursive, includeHidden, depth: 0, maxDepth: 3 });
890
+ let entries = listDir(dirPath, { recursive, includeHidden, depth: 0, maxDepth: 3 });
891
+ entries = filterSensitiveEntries(entries);
793
892
  return ok({
794
893
  path: dirPath,
795
894
  count: entries.length,
@@ -804,7 +903,7 @@ function registerFilesystemTools(api) {
804
903
  api.registerTool({
805
904
  name: "fs_mkdir",
806
905
  label: "Create Directory",
807
- description: "Create a directory on the server filesystem. Creates parent directories as needed. Supports ~ for home directory expansion.",
906
+ description: "Create a directory on the server filesystem. Creates parent directories as needed. Supports ~ for home directory expansion. Cannot create directories inside protected paths (credentials, devices, identity).",
808
907
  parameters: {
809
908
  type: "object",
810
909
  properties: {
@@ -817,7 +916,7 @@ function registerFilesystemTools(api) {
817
916
  },
818
917
  async execute(_id, params) {
819
918
  try {
820
- const targetPath = validatePath(params.path, allowedRoots);
919
+ const targetPath = validateWritePath(params.path, allowedRoots);
821
920
  fs3.mkdirSync(targetPath, { recursive: true });
822
921
  return ok({
823
922
  path: targetPath,
@@ -829,10 +928,44 @@ function registerFilesystemTools(api) {
829
928
  }
830
929
  }
831
930
  });
931
+ api.registerTool({
932
+ name: "fs_rename",
933
+ label: "Rename / Move",
934
+ description: "Rename or move a file or directory on the server filesystem. Supports ~ for home directory expansion. Cannot move files into or out of protected directories.",
935
+ parameters: {
936
+ type: "object",
937
+ properties: {
938
+ oldPath: {
939
+ type: "string",
940
+ description: "Current absolute or ~-prefixed path"
941
+ },
942
+ newPath: {
943
+ type: "string",
944
+ description: "New absolute or ~-prefixed path"
945
+ }
946
+ },
947
+ required: ["oldPath", "newPath"]
948
+ },
949
+ async execute(_id, params) {
950
+ try {
951
+ const resolvedOld = validateWritePath(params.oldPath, allowedRoots);
952
+ const resolvedNew = validateWritePath(params.newPath, allowedRoots);
953
+ fs3.renameSync(resolvedOld, resolvedNew);
954
+ return ok({
955
+ oldPath: resolvedOld,
956
+ newPath: resolvedNew,
957
+ renamed: true
958
+ });
959
+ } catch (e) {
960
+ const msg = e instanceof Error ? e.message : String(e);
961
+ return err(`fs_rename failed: ${msg}`);
962
+ }
963
+ }
964
+ });
832
965
  api.registerTool({
833
966
  name: "fs_delete",
834
967
  label: "Delete File or Directory",
835
- description: "Delete a file or directory from the server filesystem. For directories, removes recursively. Supports ~ for home directory expansion.",
968
+ description: "Delete a file or directory from the server filesystem. For directories, removes recursively. Supports ~ for home directory expansion. Cannot delete protected directories or config files.",
836
969
  parameters: {
837
970
  type: "object",
838
971
  properties: {
@@ -845,7 +978,7 @@ function registerFilesystemTools(api) {
845
978
  },
846
979
  async execute(_id, params) {
847
980
  try {
848
- const targetPath = validatePath(params.path, allowedRoots);
981
+ const targetPath = validateWritePath(params.path, allowedRoots);
849
982
  const stat = fs3.statSync(targetPath);
850
983
  const wasDirectory = stat.isDirectory();
851
984
  if (wasDirectory) {
@@ -866,17 +999,101 @@ function registerFilesystemTools(api) {
866
999
  });
867
1000
  }
868
1001
 
1002
+ // src/sql.ts
1003
+ import { execFile } from "child_process";
1004
+ import path4 from "path";
1005
+ import fs4 from "fs";
1006
+ import { Type as T2 } from "@sinclair/typebox";
1007
+ var HOME_DIR2 = process.env.HOME ?? "/root";
1008
+ var ALLOWED_DATA_DIR = path4.join(HOME_DIR2, ".openclaw", "squad-ceo-data");
1009
+ function validateDbPath(dbPath) {
1010
+ let expanded = dbPath;
1011
+ if (expanded.startsWith("~/") || expanded === "~") {
1012
+ expanded = path4.join(HOME_DIR2, expanded.slice(1));
1013
+ }
1014
+ const resolved = path4.resolve(expanded);
1015
+ if (resolved !== ALLOWED_DATA_DIR && !resolved.startsWith(ALLOWED_DATA_DIR + path4.sep)) {
1016
+ throw new Error(
1017
+ `Access denied: database path must be within ~/.openclaw/squad-ceo-data/`
1018
+ );
1019
+ }
1020
+ try {
1021
+ const stat = fs4.statSync(resolved);
1022
+ if (!stat.isFile()) {
1023
+ throw new Error(`Not a file: ${dbPath}`);
1024
+ }
1025
+ } catch (e) {
1026
+ if (e.code === "ENOENT") {
1027
+ throw new Error(`Database file not found: ${dbPath}`);
1028
+ }
1029
+ throw e;
1030
+ }
1031
+ return resolved;
1032
+ }
1033
+ function runSqlite3(dbPath, args) {
1034
+ return new Promise((resolve, reject) => {
1035
+ execFile(
1036
+ "sqlite3",
1037
+ [dbPath, ...args],
1038
+ { timeout: 3e4, maxBuffer: 10 * 1024 * 1024 },
1039
+ (error, stdout, stderr) => {
1040
+ if (error) {
1041
+ reject(new Error(stderr || error.message));
1042
+ return;
1043
+ }
1044
+ resolve(stdout);
1045
+ }
1046
+ );
1047
+ });
1048
+ }
1049
+ function registerSqlTools(api) {
1050
+ api.registerTool({
1051
+ name: "sql_query",
1052
+ label: "SQL Query",
1053
+ description: "Execute a sqlite3 query on a database file within ~/.openclaw/squad-ceo-data/. Only sqlite3 is allowed \u2014 no arbitrary shell commands. Use jsonOutput: true for structured JSON results.",
1054
+ parameters: T2.Object({
1055
+ dbPath: T2.String({
1056
+ description: "Path to the SQLite database file (must be within ~/.openclaw/squad-ceo-data/)"
1057
+ }),
1058
+ query: T2.String({ description: "SQL query to execute" }),
1059
+ jsonOutput: T2.Optional(
1060
+ T2.Boolean({
1061
+ description: "Return results as JSON (sqlite3 -json flag)"
1062
+ })
1063
+ )
1064
+ }),
1065
+ async execute(_id, params) {
1066
+ try {
1067
+ const resolvedDb = validateDbPath(params.dbPath);
1068
+ const args = [];
1069
+ if (params.jsonOutput) args.push("-json");
1070
+ args.push(params.query);
1071
+ const output = await runSqlite3(resolvedDb, args);
1072
+ return {
1073
+ content: [{ type: "text", text: output }]
1074
+ };
1075
+ } catch (e) {
1076
+ const msg = e instanceof Error ? e.message : String(e);
1077
+ return {
1078
+ content: [{ type: "text", text: JSON.stringify({ error: msg }) }],
1079
+ isError: true
1080
+ };
1081
+ }
1082
+ }
1083
+ });
1084
+ }
1085
+
869
1086
  // src/version.ts
870
1087
  import { execSync } from "child_process";
871
- import fs4 from "fs";
872
- import path4 from "path";
1088
+ import fs5 from "fs";
1089
+ import path5 from "path";
873
1090
  import { fileURLToPath } from "url";
874
1091
  var PACKAGE_NAME = "squad-openclaw";
875
1092
  function getCurrentVersion() {
876
1093
  const thisFile = fileURLToPath(import.meta.url);
877
- const pkgPath = path4.resolve(path4.dirname(thisFile), "..", "package.json");
1094
+ const pkgPath = path5.resolve(path5.dirname(thisFile), "..", "package.json");
878
1095
  try {
879
- const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
1096
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
880
1097
  return pkg.version ?? "0.0.0";
881
1098
  } catch {
882
1099
  return "0.0.0";
@@ -974,8 +1191,8 @@ function registerVersionMethods(api) {
974
1191
  // src/relay-client.ts
975
1192
  import { WebSocket as NodeWebSocket } from "ws";
976
1193
  import crypto2 from "crypto";
977
- import fs5 from "fs";
978
- import path5 from "path";
1194
+ import fs6 from "fs";
1195
+ import path6 from "path";
979
1196
  import os from "os";
980
1197
 
981
1198
  // src/e2e-crypto.ts
@@ -1057,31 +1274,31 @@ var E2ECrypto = class {
1057
1274
 
1058
1275
  // src/relay-client.ts
1059
1276
  function readOperatorToken() {
1060
- const stateDir = process.env.OPENCLAW_STATE_DIR || path5.join(os.homedir(), ".openclaw");
1061
- const configPath = path5.join(stateDir, "openclaw.json");
1277
+ const stateDir = process.env.OPENCLAW_STATE_DIR || path6.join(os.homedir(), ".openclaw");
1278
+ const configPath = path6.join(stateDir, "openclaw.json");
1062
1279
  try {
1063
- const raw = fs5.readFileSync(configPath, "utf-8");
1280
+ const raw = fs6.readFileSync(configPath, "utf-8");
1064
1281
  const config = JSON.parse(raw);
1065
1282
  return config?.gateway?.auth?.token ?? config?.gateway?.remote?.token ?? config?.gateway?.token ?? null;
1066
1283
  } catch {
1067
1284
  return null;
1068
1285
  }
1069
1286
  }
1070
- var RELAY_DATA_DIR = path5.join(os.homedir(), ".openclaw", "squad-ceo-data");
1071
- var RELAY_STATE_PATH = path5.join(RELAY_DATA_DIR, "squad-relay.json");
1287
+ var RELAY_DATA_DIR = path6.join(os.homedir(), ".openclaw", "squad-ceo-data");
1288
+ var RELAY_STATE_PATH = path6.join(RELAY_DATA_DIR, "squad-relay.json");
1072
1289
  function readRelayState() {
1073
1290
  try {
1074
- const raw = fs5.readFileSync(RELAY_STATE_PATH, "utf-8");
1291
+ const raw = fs6.readFileSync(RELAY_STATE_PATH, "utf-8");
1075
1292
  return JSON.parse(raw);
1076
1293
  } catch {
1077
1294
  return {};
1078
1295
  }
1079
1296
  }
1080
1297
  function writeRelayState(state) {
1081
- if (!fs5.existsSync(RELAY_DATA_DIR)) {
1082
- fs5.mkdirSync(RELAY_DATA_DIR, { recursive: true });
1298
+ if (!fs6.existsSync(RELAY_DATA_DIR)) {
1299
+ fs6.mkdirSync(RELAY_DATA_DIR, { recursive: true });
1083
1300
  }
1084
- fs5.writeFileSync(RELAY_STATE_PATH, JSON.stringify(state, null, 2), { mode: 384 });
1301
+ fs6.writeFileSync(RELAY_STATE_PATH, JSON.stringify(state, null, 2), { mode: 384 });
1085
1302
  }
1086
1303
  function toBase64Url(buf) {
1087
1304
  return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
@@ -1103,11 +1320,11 @@ function loadOrCreateRelayDeviceKeys() {
1103
1320
  return keys;
1104
1321
  }
1105
1322
  function ensureDevicePaired(keys, operatorToken) {
1106
- const stateDir = process.env.OPENCLAW_STATE_DIR || path5.join(os.homedir(), ".openclaw");
1107
- const pairedPath = path5.join(stateDir, "devices", "paired.json");
1323
+ const stateDir = process.env.OPENCLAW_STATE_DIR || path6.join(os.homedir(), ".openclaw");
1324
+ const pairedPath = path6.join(stateDir, "devices", "paired.json");
1108
1325
  let paired = {};
1109
1326
  try {
1110
- paired = JSON.parse(fs5.readFileSync(pairedPath, "utf-8"));
1327
+ paired = JSON.parse(fs6.readFileSync(pairedPath, "utf-8"));
1111
1328
  } catch {
1112
1329
  }
1113
1330
  if (paired[keys.deviceId]) return false;
@@ -1129,9 +1346,9 @@ function ensureDevicePaired(keys, operatorToken) {
1129
1346
  approvedAtMs: now,
1130
1347
  displayName: "squad-relay"
1131
1348
  };
1132
- const dir = path5.dirname(pairedPath);
1133
- if (!fs5.existsSync(dir)) fs5.mkdirSync(dir, { recursive: true });
1134
- fs5.writeFileSync(pairedPath, JSON.stringify(paired, null, 2), { mode: 384 });
1349
+ const dir = path6.dirname(pairedPath);
1350
+ if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
1351
+ fs6.writeFileSync(pairedPath, JSON.stringify(paired, null, 2), { mode: 384 });
1135
1352
  console.log(`[relay-client] Device pairing entry created in paired.json`);
1136
1353
  return true;
1137
1354
  }
@@ -1645,6 +1862,7 @@ function squadAppPlugin(api) {
1645
1862
  const onFsChange = (evt) => broadcastToUsers("fs.change", evt);
1646
1863
  registerEntityTools(api, onFsChange);
1647
1864
  registerFilesystemTools(api);
1865
+ registerSqlTools(api);
1648
1866
  registerVersionMethods(api);
1649
1867
  api.registerGatewayMethod(
1650
1868
  "tools.invoke",
@@ -9,7 +9,7 @@
9
9
  "fs.allowedRoots": {
10
10
  "type": "array",
11
11
  "items": { "type": "string" },
12
- "description": "Restrict fs_read/fs_write/fs_list/fs_delete to these directories. Empty or omitted = allow all."
12
+ "description": "Restrict fs_read/fs_write/fs_list/fs_delete/fs_rename to these directories. Empty or omitted = allow all."
13
13
  },
14
14
  "relay.enabled": {
15
15
  "type": "boolean",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squad-openclaw",
3
- "version": "2026.2.1903",
3
+ "version": "2026.2.1905",
4
4
  "description": "Entity registry, filesystem tools, and version management plugin for OpenClaw gateway",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,12 +35,12 @@
35
35
  "squad"
36
36
  ],
37
37
  "dependencies": {
38
- "@sinclair/typebox": "^0.31.0",
39
- "chokidar": "^4.0.0",
40
- "ws": "^8.18.0"
38
+ "@sinclair/typebox": "0.31.28",
39
+ "chokidar": "4.0.3",
40
+ "ws": "8.18.3"
41
41
  },
42
42
  "devDependencies": {
43
- "tsup": "^8.0.0",
44
- "typescript": "^5.0.0"
43
+ "tsup": "8.5.1",
44
+ "typescript": "5.9.3"
45
45
  }
46
46
  }