@agenshield/daemon 0.5.0 → 0.6.0

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/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // libs/shield-daemon/src/main.ts
4
- import * as fs20 from "node:fs";
4
+ import * as fs21 from "node:fs";
5
5
 
6
6
  // libs/shield-daemon/src/config/paths.ts
7
7
  import * as path from "node:path";
@@ -86,7 +86,7 @@ function updateConfig(updates) {
86
86
  }
87
87
 
88
88
  // libs/shield-daemon/src/server.ts
89
- import * as fs19 from "node:fs";
89
+ import * as fs20 from "node:fs";
90
90
  import Fastify from "fastify";
91
91
  import cors from "@fastify/cors";
92
92
  import fastifyStatic from "@fastify/static";
@@ -213,8 +213,8 @@ async function statusRoutes(app) {
213
213
  }
214
214
 
215
215
  // libs/shield-daemon/src/routes/config.ts
216
- import * as fs6 from "node:fs";
217
- import * as path5 from "node:path";
216
+ import * as fs7 from "node:fs";
217
+ import * as path7 from "node:path";
218
218
 
219
219
  // libs/shield-daemon/src/vault/index.ts
220
220
  import * as fs3 from "node:fs";
@@ -518,8 +518,30 @@ function getSessionManager() {
518
518
  import { execSync as execSync2 } from "node:child_process";
519
519
  import * as os3 from "node:os";
520
520
  import * as fs4 from "node:fs";
521
+ import * as path4 from "node:path";
521
522
  var noop = { warn() {
522
523
  } };
524
+ var TRAVERSAL_PERMS = "search";
525
+ var WORLD_TRAVERSABLE_PATHS = /* @__PURE__ */ new Set([
526
+ "/",
527
+ "/Users",
528
+ "/tmp",
529
+ "/private",
530
+ "/private/tmp",
531
+ "/private/var",
532
+ "/var",
533
+ "/opt",
534
+ "/usr",
535
+ "/usr/local",
536
+ "/Applications",
537
+ "/Library",
538
+ "/System",
539
+ "/Volumes"
540
+ ]);
541
+ function normalizePath(p) {
542
+ if (p === "/") return p;
543
+ return p.replace(/\/+$/, "") || "/";
544
+ }
523
545
  function stripGlobToBasePath(pattern) {
524
546
  let p = pattern;
525
547
  if (p.startsWith("~")) {
@@ -531,7 +553,7 @@ function stripGlobToBasePath(pattern) {
531
553
  if (/[*?[]/.test(seg)) break;
532
554
  base.push(seg);
533
555
  }
534
- return base.length === 0 ? "/" : base.join("/") || "/";
556
+ return normalizePath(base.length === 0 ? "/" : base.join("/") || "/");
535
557
  }
536
558
  function operationsToAclPerms(operations) {
537
559
  const perms = [];
@@ -589,49 +611,69 @@ function removeGroupAcl(targetPath, groupName, log = noop) {
589
611
  log.warn(`[acl] failed to read ACLs on ${targetPath}: ${err.message}`);
590
612
  }
591
613
  }
592
- function syncFilesystemPolicyAcls(oldPolicies, newPolicies, groupName, logger) {
593
- const log = logger ?? noop;
594
- const oldFs = oldPolicies.filter((p) => p.target === "filesystem");
595
- const newFs = newPolicies.filter((p) => p.target === "filesystem");
596
- const oldMap = new Map(oldFs.map((p) => [p.id, p]));
597
- const newMap = new Map(newFs.map((p) => [p.id, p]));
598
- for (const [id, oldP] of oldMap) {
599
- if (!newMap.has(id)) {
600
- for (const pattern of oldP.patterns) {
601
- removeGroupAcl(stripGlobToBasePath(pattern), groupName, log);
602
- }
614
+ function getAncestorsNeedingTraversal(targetPath) {
615
+ const ancestors = [];
616
+ let dir = path4.dirname(targetPath);
617
+ while (dir !== targetPath && dir !== "/") {
618
+ if (!WORLD_TRAVERSABLE_PATHS.has(dir)) {
619
+ ancestors.push(dir);
603
620
  }
621
+ targetPath = dir;
622
+ dir = path4.dirname(dir);
604
623
  }
605
- for (const [id, newP] of newMap) {
606
- if (!oldMap.has(id)) {
607
- const perms = operationsToAclPerms(newP.operations ?? []);
608
- if (!perms) continue;
609
- for (const pattern of newP.patterns) {
610
- addGroupAcl(stripGlobToBasePath(pattern), groupName, perms, log);
611
- }
624
+ return ancestors;
625
+ }
626
+ function mergePerms(a, b) {
627
+ const set = /* @__PURE__ */ new Set([
628
+ ...a.split(",").filter(Boolean),
629
+ ...b.split(",").filter(Boolean)
630
+ ]);
631
+ return [...set].join(",");
632
+ }
633
+ function computeAclMap(policies) {
634
+ const aclMap = /* @__PURE__ */ new Map();
635
+ for (const policy of policies) {
636
+ const perms = operationsToAclPerms(policy.operations ?? []);
637
+ if (!perms) continue;
638
+ for (const pattern of policy.patterns) {
639
+ const target = stripGlobToBasePath(pattern);
640
+ const existing = aclMap.get(target);
641
+ aclMap.set(target, existing ? mergePerms(existing, perms) : perms);
612
642
  }
613
643
  }
614
- for (const [id, newP] of newMap) {
615
- const oldP = oldMap.get(id);
616
- if (!oldP) continue;
617
- const patternsChanged = JSON.stringify(oldP.patterns) !== JSON.stringify(newP.patterns);
618
- const opsChanged = JSON.stringify(oldP.operations ?? []) !== JSON.stringify(newP.operations ?? []);
619
- if (patternsChanged || opsChanged) {
620
- for (const pattern of oldP.patterns) {
621
- removeGroupAcl(stripGlobToBasePath(pattern), groupName, log);
622
- }
623
- const perms = operationsToAclPerms(newP.operations ?? []);
624
- if (!perms) continue;
625
- for (const pattern of newP.patterns) {
626
- addGroupAcl(stripGlobToBasePath(pattern), groupName, perms, log);
644
+ for (const policy of policies) {
645
+ const perms = operationsToAclPerms(policy.operations ?? []);
646
+ if (!perms) continue;
647
+ for (const pattern of policy.patterns) {
648
+ const target = stripGlobToBasePath(pattern);
649
+ for (const ancestor of getAncestorsNeedingTraversal(target)) {
650
+ if (!aclMap.has(ancestor)) {
651
+ aclMap.set(ancestor, TRAVERSAL_PERMS);
652
+ }
627
653
  }
628
654
  }
629
655
  }
656
+ return aclMap;
657
+ }
658
+ function syncFilesystemPolicyAcls(oldPolicies, newPolicies, groupName, logger) {
659
+ const log = logger ?? noop;
660
+ const oldFs = oldPolicies.filter((p) => p.target === "filesystem");
661
+ const newFs = newPolicies.filter((p) => p.target === "filesystem");
662
+ const oldAclMap = computeAclMap(oldFs);
663
+ const newAclMap = computeAclMap(newFs);
664
+ for (const oldPath of oldAclMap.keys()) {
665
+ if (!newAclMap.has(oldPath)) {
666
+ removeGroupAcl(oldPath, groupName, log);
667
+ }
668
+ }
669
+ for (const [targetPath, perms] of newAclMap) {
670
+ addGroupAcl(targetPath, groupName, perms, log);
671
+ }
630
672
  }
631
673
 
632
674
  // libs/shield-daemon/src/command-sync.ts
633
675
  import * as fs5 from "node:fs";
634
- import * as path4 from "node:path";
676
+ import * as path5 from "node:path";
635
677
  import { execSync as execSync3 } from "node:child_process";
636
678
  var noop2 = { warn() {
637
679
  }, info() {
@@ -664,7 +706,7 @@ var ALL_PROXIED_COMMANDS = [
664
706
  function resolveCommandPaths(name) {
665
707
  const paths = [];
666
708
  for (const dir of BIN_SEARCH_DIRS) {
667
- const candidate = path4.join(dir, name);
709
+ const candidate = path5.join(dir, name);
668
710
  try {
669
711
  if (fs5.existsSync(candidate)) {
670
712
  const stat = fs5.statSync(candidate);
@@ -678,7 +720,7 @@ function resolveCommandPaths(name) {
678
720
  if (paths.length === 0) {
679
721
  try {
680
722
  const result = execSync3(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
681
- if (result && path4.isAbsolute(result)) {
723
+ if (result && path5.isAbsolute(result)) {
682
724
  paths.push(result);
683
725
  }
684
726
  } catch {
@@ -720,15 +762,26 @@ function syncCommandPolicies(policies, logger) {
720
762
  version: "1.0.0",
721
763
  commands
722
764
  };
765
+ const json = JSON.stringify(config, null, 2) + "\n";
723
766
  try {
724
- const dir = path4.dirname(ALLOWED_COMMANDS_PATH);
767
+ const dir = path5.dirname(ALLOWED_COMMANDS_PATH);
725
768
  if (!fs5.existsSync(dir)) {
726
769
  fs5.mkdirSync(dir, { recursive: true });
727
770
  }
728
- fs5.writeFileSync(ALLOWED_COMMANDS_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
771
+ fs5.writeFileSync(ALLOWED_COMMANDS_PATH, json, "utf-8");
729
772
  log.info(`[command-sync] wrote ${commands.length} commands to allowlist`);
730
- } catch (err) {
731
- log.warn(`[command-sync] failed to write allowlist: ${err.message}`);
773
+ } catch {
774
+ try {
775
+ execSync3(`sudo -n tee "${ALLOWED_COMMANDS_PATH}" > /dev/null`, {
776
+ input: json,
777
+ stdio: ["pipe", "pipe", "pipe"],
778
+ timeout: 5e3
779
+ });
780
+ log.info(`[command-sync] wrote ${commands.length} commands to allowlist (via sudo)`);
781
+ } catch (sudoErr) {
782
+ log.warn(`[command-sync] cannot write to ${ALLOWED_COMMANDS_PATH} \u2014 fix with: sudo chmod 775 ${path5.dirname(ALLOWED_COMMANDS_PATH)}`);
783
+ log.warn(`[command-sync] error: ${sudoErr.message}`);
784
+ }
732
785
  }
733
786
  }
734
787
  function installWrappersInDir(binDir, log) {
@@ -736,24 +789,38 @@ function installWrappersInDir(binDir, log) {
736
789
  if (!fs5.existsSync(binDir)) {
737
790
  try {
738
791
  fs5.mkdirSync(binDir, { recursive: true, mode: 493 });
739
- } catch (err) {
740
- log.warn(`[command-sync] failed to create bin dir ${binDir}: ${err.message}`);
741
- return;
792
+ } catch {
793
+ try {
794
+ execSync3(`sudo -n mkdir -p "${binDir}" && sudo -n chmod 755 "${binDir}"`, {
795
+ stdio: "pipe",
796
+ timeout: 5e3
797
+ });
798
+ } catch (sudoErr) {
799
+ log.warn(`[command-sync] failed to create bin dir ${binDir}: ${sudoErr.message}`);
800
+ return;
801
+ }
742
802
  }
743
803
  }
804
+ if (!fs5.existsSync(shieldExecPath)) {
805
+ log.warn(`[command-sync] shield-exec not found at ${shieldExecPath}, skipping wrapper installation`);
806
+ return;
807
+ }
744
808
  for (const cmd of ALL_PROXIED_COMMANDS) {
745
- const wrapperPath = path4.join(binDir, cmd);
809
+ const wrapperPath = path5.join(binDir, cmd);
746
810
  if (fs5.existsSync(wrapperPath)) {
747
811
  continue;
748
812
  }
749
813
  try {
750
- if (fs5.existsSync(shieldExecPath)) {
751
- fs5.symlinkSync(shieldExecPath, wrapperPath);
752
- } else {
753
- log.warn(`[command-sync] shield-exec not found at ${shieldExecPath}, skipping ${cmd} wrapper`);
814
+ fs5.symlinkSync(shieldExecPath, wrapperPath);
815
+ } catch {
816
+ try {
817
+ execSync3(`sudo -n ln -s "${shieldExecPath}" "${wrapperPath}"`, {
818
+ stdio: "pipe",
819
+ timeout: 5e3
820
+ });
821
+ } catch (sudoErr) {
822
+ log.warn(`[command-sync] failed to create wrapper ${wrapperPath}: ${sudoErr.message}`);
754
823
  }
755
- } catch (err) {
756
- log.warn(`[command-sync] failed to create wrapper ${wrapperPath}: ${err.message}`);
757
824
  }
758
825
  }
759
826
  }
@@ -764,12 +831,12 @@ function ensureWrappersInstalled(state, logger) {
764
831
  log.warn("[command-sync] no agent user in state, skipping wrapper installation");
765
832
  return;
766
833
  }
767
- const agentBinDir = path4.join(agentUser.homeDir, "bin");
834
+ const agentBinDir = path5.join(agentUser.homeDir, "bin");
768
835
  log.info(`[command-sync] ensuring wrappers in agent bin: ${agentBinDir}`);
769
836
  installWrappersInDir(agentBinDir, log);
770
837
  const agentHomeEnv = process.env["AGENSHIELD_AGENT_HOME"];
771
838
  if (agentHomeEnv && agentHomeEnv !== agentUser.homeDir) {
772
- const envBinDir = path4.join(agentHomeEnv, "bin");
839
+ const envBinDir = path5.join(agentHomeEnv, "bin");
773
840
  log.info(`[command-sync] ensuring wrappers in env agent bin: ${envBinDir}`);
774
841
  installWrappersInDir(envBinDir, log);
775
842
  }
@@ -779,6 +846,90 @@ function syncCommandPoliciesAndWrappers(policies, state, logger) {
779
846
  ensureWrappersInstalled(state, logger);
780
847
  }
781
848
 
849
+ // libs/shield-daemon/src/policy-sync.ts
850
+ import * as fs6 from "node:fs";
851
+ import * as path6 from "node:path";
852
+ import { execSync as execSync4 } from "node:child_process";
853
+ var noop3 = { warn() {
854
+ }, info() {
855
+ } };
856
+ var BROKER_POLICIES_DIR = "/opt/agenshield/policies";
857
+ var USER_POLICIES_FILE = path6.join(BROKER_POLICIES_DIR, "custom", "user-policies.json");
858
+ var BROKER_TARGETS = /* @__PURE__ */ new Set(["url", "command", "skill"]);
859
+ function normalizeUrlPatterns(pattern) {
860
+ let p = pattern.trim();
861
+ p = p.replace(/\/+$/, "");
862
+ if (!p.match(/^(\*|https?):\/\//i)) {
863
+ p = `https://${p}`;
864
+ }
865
+ if (p.endsWith("*")) {
866
+ const base = p.replace(/\/\*+$/, "");
867
+ if (base !== p) {
868
+ return [base, p];
869
+ }
870
+ return [p];
871
+ }
872
+ return [p, `${p}/**`];
873
+ }
874
+ function inferOperations(target) {
875
+ switch (target) {
876
+ case "url":
877
+ return ["http_request", "open_url"];
878
+ case "command":
879
+ return ["exec"];
880
+ case "skill":
881
+ return ["skill_install", "skill_uninstall"];
882
+ default:
883
+ return ["*"];
884
+ }
885
+ }
886
+ function toBrokerRule(policy) {
887
+ let patterns;
888
+ if (policy.target === "url") {
889
+ patterns = policy.patterns.flatMap(normalizeUrlPatterns);
890
+ patterns = [...new Set(patterns)];
891
+ } else {
892
+ patterns = [...policy.patterns];
893
+ }
894
+ return {
895
+ id: policy.id,
896
+ name: policy.name,
897
+ action: policy.action,
898
+ target: policy.target,
899
+ operations: policy.operations?.length ? [...policy.operations] : inferOperations(policy.target),
900
+ patterns,
901
+ enabled: policy.enabled,
902
+ priority: policy.priority ?? 0
903
+ };
904
+ }
905
+ function syncPoliciesToBrokerDir(policies, logger) {
906
+ const log = logger ?? noop3;
907
+ const applicable = policies.filter((p) => BROKER_TARGETS.has(p.target));
908
+ const rules = applicable.map(toBrokerRule);
909
+ const payload = { rules };
910
+ const json = JSON.stringify(payload, null, 2) + "\n";
911
+ try {
912
+ const dir = path6.dirname(USER_POLICIES_FILE);
913
+ if (!fs6.existsSync(dir)) {
914
+ fs6.mkdirSync(dir, { recursive: true });
915
+ }
916
+ fs6.writeFileSync(USER_POLICIES_FILE, json, "utf-8");
917
+ log.info(`[policy-sync] wrote ${rules.length} user policies to broker dir`);
918
+ } catch {
919
+ try {
920
+ execSync4(`sudo -n tee "${USER_POLICIES_FILE}" > /dev/null`, {
921
+ input: json,
922
+ stdio: ["pipe", "pipe", "pipe"],
923
+ timeout: 5e3
924
+ });
925
+ log.info(`[policy-sync] wrote ${rules.length} user policies to broker dir (via sudo)`);
926
+ } catch (sudoErr) {
927
+ log.warn(`[policy-sync] cannot write to ${USER_POLICIES_FILE} \u2014 fix with: sudo chmod 775 ${path6.dirname(USER_POLICIES_FILE)}`);
928
+ log.warn(`[policy-sync] error: ${sudoErr.message}`);
929
+ }
930
+ }
931
+ }
932
+
782
933
  // libs/shield-daemon/src/routes/config.ts
783
934
  async function configRoutes(app) {
784
935
  app.get("/config", async () => {
@@ -801,6 +952,7 @@ async function configRoutes(app) {
801
952
  syncFilesystemPolicyAcls(oldPolicies, updated.policies, wsGroup.name, app.log);
802
953
  }
803
954
  syncCommandPoliciesAndWrappers(updated.policies, state, app.log);
955
+ syncPoliciesToBrokerDir(updated.policies, app.log);
804
956
  }
805
957
  return {
806
958
  success: true,
@@ -826,6 +978,7 @@ async function configRoutes(app) {
826
978
  syncFilesystemPolicyAcls(oldConfig.policies, [], wsGroup.name, app.log);
827
979
  }
828
980
  syncCommandPoliciesAndWrappers([], state, app.log);
981
+ syncPoliciesToBrokerDir([], app.log);
829
982
  saveConfig(getDefaultConfig());
830
983
  const vault = getVault();
831
984
  await vault.destroy();
@@ -843,7 +996,7 @@ async function configRoutes(app) {
843
996
  });
844
997
  app.get("/config/openclaw", async (_request, reply) => {
845
998
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
846
- const configDir = path5.join(agentHome, ".openclaw");
999
+ const configDir = path7.join(agentHome, ".openclaw");
847
1000
  const configFiles = readConfigDir(configDir);
848
1001
  return reply.send({ configDir, files: configFiles });
849
1002
  });
@@ -855,7 +1008,7 @@ async function configRoutes(app) {
855
1008
  return reply.code(400).send({ error: "original query param required" });
856
1009
  }
857
1010
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
858
- const agentConfigDir = path5.join(agentHome, ".openclaw");
1011
+ const agentConfigDir = path7.join(agentHome, ".openclaw");
859
1012
  const diff = diffConfigDirs(original, agentConfigDir);
860
1013
  return reply.send({ diff });
861
1014
  }
@@ -865,27 +1018,27 @@ var SKIP_DIRS = /* @__PURE__ */ new Set(["skills", "node_modules", ".git", "dist
865
1018
  function readConfigDir(dir, base) {
866
1019
  const result = {};
867
1020
  const root = base ?? dir;
868
- if (!fs6.existsSync(dir)) {
1021
+ if (!fs7.existsSync(dir)) {
869
1022
  return result;
870
1023
  }
871
1024
  let entries;
872
1025
  try {
873
- entries = fs6.readdirSync(dir, { withFileTypes: true });
1026
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
874
1027
  } catch {
875
1028
  return result;
876
1029
  }
877
1030
  for (const entry of entries) {
878
1031
  if (entry.isDirectory()) {
879
1032
  if (SKIP_DIRS.has(entry.name)) continue;
880
- const sub = readConfigDir(path5.join(dir, entry.name), root);
1033
+ const sub = readConfigDir(path7.join(dir, entry.name), root);
881
1034
  Object.assign(result, sub);
882
1035
  } else if (entry.isFile()) {
883
- const ext = path5.extname(entry.name).toLowerCase();
1036
+ const ext = path7.extname(entry.name).toLowerCase();
884
1037
  if ([".json", ".yaml", ".yml", ".toml", ".txt", ".md", ".conf", ""].includes(ext)) {
885
- const filePath = path5.join(dir, entry.name);
886
- const relPath = path5.relative(root, filePath);
1038
+ const filePath = path7.join(dir, entry.name);
1039
+ const relPath = path7.relative(root, filePath);
887
1040
  try {
888
- result[relPath] = fs6.readFileSync(filePath, "utf-8");
1041
+ result[relPath] = fs7.readFileSync(filePath, "utf-8");
889
1042
  } catch {
890
1043
  }
891
1044
  }
@@ -1005,10 +1158,10 @@ function emitSecurityWarning(warning) {
1005
1158
  function emitSecurityCritical(issue) {
1006
1159
  daemonEvents.broadcast("security:critical", { message: issue });
1007
1160
  }
1008
- function emitApiRequest(method, path18, statusCode, duration, requestBody, responseBody) {
1161
+ function emitApiRequest(method, path20, statusCode, duration, requestBody, responseBody) {
1009
1162
  daemonEvents.broadcast("api:request", {
1010
1163
  method,
1011
- path: path18,
1164
+ path: path20,
1012
1165
  statusCode,
1013
1166
  duration,
1014
1167
  ...requestBody !== void 0 && { requestBody },
@@ -1215,16 +1368,16 @@ var PROTECTED_ROUTES = [
1215
1368
  { method: "POST", path: "/api/config/factory-reset" },
1216
1369
  { method: "POST", path: "/api/skills/install" }
1217
1370
  ];
1218
- function isProtectedRoute(method, path18) {
1371
+ function isProtectedRoute(method, path20) {
1219
1372
  return PROTECTED_ROUTES.some(
1220
- (route) => route.method === method && path18.startsWith(route.path)
1373
+ (route) => route.method === method && path20.startsWith(route.path)
1221
1374
  );
1222
1375
  }
1223
1376
  function createAuthHook() {
1224
1377
  return async (request, reply) => {
1225
1378
  const method = request.method;
1226
- const path18 = request.url.split("?")[0];
1227
- if (!isProtectedRoute(method, path18)) {
1379
+ const path20 = request.url.split("?")[0];
1380
+ if (!isProtectedRoute(method, path20)) {
1228
1381
  return;
1229
1382
  }
1230
1383
  if (!isAuthenticated(request)) {
@@ -2056,8 +2209,8 @@ function getMCPState() {
2056
2209
  }
2057
2210
 
2058
2211
  // libs/shield-daemon/src/services/integration-skills.ts
2059
- import * as fs8 from "node:fs";
2060
- import * as path7 from "node:path";
2212
+ import * as fs9 from "node:fs";
2213
+ import * as path9 from "node:path";
2061
2214
 
2062
2215
  // libs/shield-skills/dist/index.js
2063
2216
  import * as path22 from "node:path";
@@ -2122,9 +2275,9 @@ var __skills_dirname = path22.dirname(fileURLToPath(import.meta.url));
2122
2275
  var BUILTIN_SKILLS_DIR = path22.resolve(__skills_dirname, "..", "skills");
2123
2276
 
2124
2277
  // libs/shield-daemon/src/watchers/skills.ts
2125
- import * as fs7 from "node:fs";
2126
- import * as path6 from "node:path";
2127
- import { execSync as execSync4 } from "node:child_process";
2278
+ import * as fs8 from "node:fs";
2279
+ import * as path8 from "node:path";
2280
+ import { execSync as execSync5 } from "node:child_process";
2128
2281
  var APPROVED_SKILLS_PATH = "/opt/agenshield/config/approved-skills.json";
2129
2282
  var QUARANTINE_DIR = "/opt/agenshield/quarantine/skills";
2130
2283
  var DEBOUNCE_MS = 500;
@@ -2135,8 +2288,8 @@ var skillsDir = "";
2135
2288
  var callbacks = {};
2136
2289
  function loadApprovedSkills() {
2137
2290
  try {
2138
- if (fs7.existsSync(APPROVED_SKILLS_PATH)) {
2139
- const content = fs7.readFileSync(APPROVED_SKILLS_PATH, "utf-8");
2291
+ if (fs8.existsSync(APPROVED_SKILLS_PATH)) {
2292
+ const content = fs8.readFileSync(APPROVED_SKILLS_PATH, "utf-8");
2140
2293
  return JSON.parse(content);
2141
2294
  }
2142
2295
  } catch {
@@ -2145,10 +2298,10 @@ function loadApprovedSkills() {
2145
2298
  }
2146
2299
  function saveApprovedSkills(skills) {
2147
2300
  try {
2148
- const dir = path6.dirname(APPROVED_SKILLS_PATH);
2149
- fs7.mkdirSync(dir, { recursive: true });
2301
+ const dir = path8.dirname(APPROVED_SKILLS_PATH);
2302
+ fs8.mkdirSync(dir, { recursive: true });
2150
2303
  const content = JSON.stringify(skills, null, 2);
2151
- fs7.writeFileSync(APPROVED_SKILLS_PATH, content, "utf-8");
2304
+ fs8.writeFileSync(APPROVED_SKILLS_PATH, content, "utf-8");
2152
2305
  } catch (err) {
2153
2306
  console.error("Failed to save approved skills:", err.message);
2154
2307
  }
@@ -2159,16 +2312,16 @@ function isApproved(skillName) {
2159
2312
  }
2160
2313
  function quarantineSkill(skillName, skillPath) {
2161
2314
  try {
2162
- const quarantinePath = path6.join(QUARANTINE_DIR, skillName);
2163
- if (!fs7.existsSync(QUARANTINE_DIR)) {
2164
- fs7.mkdirSync(QUARANTINE_DIR, { recursive: true, mode: 448 });
2315
+ const quarantinePath = path8.join(QUARANTINE_DIR, skillName);
2316
+ if (!fs8.existsSync(QUARANTINE_DIR)) {
2317
+ fs8.mkdirSync(QUARANTINE_DIR, { recursive: true, mode: 448 });
2165
2318
  }
2166
- if (fs7.existsSync(quarantinePath)) {
2167
- fs7.rmSync(quarantinePath, { recursive: true, force: true });
2319
+ if (fs8.existsSync(quarantinePath)) {
2320
+ fs8.rmSync(quarantinePath, { recursive: true, force: true });
2168
2321
  }
2169
- execSync4(`mv "${skillPath}" "${quarantinePath}"`, { stdio: "pipe" });
2170
- execSync4(`chown -R root:wheel "${quarantinePath}"`, { stdio: "pipe" });
2171
- execSync4(`chmod -R 700 "${quarantinePath}"`, { stdio: "pipe" });
2322
+ execSync5(`mv "${skillPath}" "${quarantinePath}"`, { stdio: "pipe" });
2323
+ execSync5(`chown -R root:wheel "${quarantinePath}"`, { stdio: "pipe" });
2324
+ execSync5(`chmod -R 700 "${quarantinePath}"`, { stdio: "pipe" });
2172
2325
  const info = {
2173
2326
  name: skillName,
2174
2327
  quarantinedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -2183,16 +2336,16 @@ function quarantineSkill(skillName, skillPath) {
2183
2336
  }
2184
2337
  }
2185
2338
  function scanSkills() {
2186
- if (!skillsDir || !fs7.existsSync(skillsDir)) {
2339
+ if (!skillsDir || !fs8.existsSync(skillsDir)) {
2187
2340
  return;
2188
2341
  }
2189
2342
  try {
2190
- const entries = fs7.readdirSync(skillsDir, { withFileTypes: true });
2343
+ const entries = fs8.readdirSync(skillsDir, { withFileTypes: true });
2191
2344
  for (const entry of entries) {
2192
2345
  if (!entry.isDirectory()) continue;
2193
2346
  const skillName = entry.name;
2194
2347
  if (!isApproved(skillName)) {
2195
- const fullPath = path6.join(skillsDir, skillName);
2348
+ const fullPath = path8.join(skillsDir, skillName);
2196
2349
  const info = quarantineSkill(skillName, fullPath);
2197
2350
  if (info && callbacks.onQuarantined) {
2198
2351
  callbacks.onQuarantined(info);
@@ -2225,8 +2378,8 @@ function startSkillsWatcher(watchDir, cbs = {}, pollIntervalMs = 3e4) {
2225
2378
  callbacks = cbs;
2226
2379
  scanSkills();
2227
2380
  try {
2228
- if (fs7.existsSync(skillsDir)) {
2229
- watcher = fs7.watch(skillsDir, { persistent: false }, handleFsEvent);
2381
+ if (fs8.existsSync(skillsDir)) {
2382
+ watcher = fs8.watch(skillsDir, { persistent: false }, handleFsEvent);
2230
2383
  watcher.on("error", (err) => {
2231
2384
  console.warn("[SkillsWatcher] fs.watch error, falling back to polling:", err.message);
2232
2385
  watcher?.close();
@@ -2258,9 +2411,9 @@ function stopSkillsWatcher() {
2258
2411
  }
2259
2412
  function approveSkill(skillName) {
2260
2413
  try {
2261
- const quarantinedPath = path6.join(QUARANTINE_DIR, skillName);
2262
- const destPath = path6.join(skillsDir, skillName);
2263
- if (!fs7.existsSync(quarantinedPath)) {
2414
+ const quarantinedPath = path8.join(QUARANTINE_DIR, skillName);
2415
+ const destPath = path8.join(skillsDir, skillName);
2416
+ if (!fs8.existsSync(quarantinedPath)) {
2264
2417
  return { success: false, error: `Skill "${skillName}" not found in quarantine` };
2265
2418
  }
2266
2419
  const approved = loadApprovedSkills();
@@ -2271,9 +2424,9 @@ function approveSkill(skillName) {
2271
2424
  });
2272
2425
  saveApprovedSkills(approved);
2273
2426
  }
2274
- execSync4(`mv "${quarantinedPath}" "${destPath}"`, { stdio: "pipe" });
2275
- execSync4(`chown -R root:wheel "${destPath}"`, { stdio: "pipe" });
2276
- execSync4(`chmod -R a+rX,go-w "${destPath}"`, { stdio: "pipe" });
2427
+ execSync5(`mv "${quarantinedPath}" "${destPath}"`, { stdio: "pipe" });
2428
+ execSync5(`chown -R root:wheel "${destPath}"`, { stdio: "pipe" });
2429
+ execSync5(`chmod -R a+rX,go-w "${destPath}"`, { stdio: "pipe" });
2277
2430
  if (callbacks.onApproved) {
2278
2431
  callbacks.onApproved(skillName);
2279
2432
  }
@@ -2285,11 +2438,11 @@ function approveSkill(skillName) {
2285
2438
  }
2286
2439
  function rejectSkill(skillName) {
2287
2440
  try {
2288
- const quarantinedPath = path6.join(QUARANTINE_DIR, skillName);
2289
- if (!fs7.existsSync(quarantinedPath)) {
2441
+ const quarantinedPath = path8.join(QUARANTINE_DIR, skillName);
2442
+ if (!fs8.existsSync(quarantinedPath)) {
2290
2443
  return { success: false, error: `Skill "${skillName}" not found in quarantine` };
2291
2444
  }
2292
- fs7.rmSync(quarantinedPath, { recursive: true, force: true });
2445
+ fs8.rmSync(quarantinedPath, { recursive: true, force: true });
2293
2446
  console.log(`[SkillsWatcher] Rejected and deleted skill: ${skillName}`);
2294
2447
  return { success: true };
2295
2448
  } catch (err) {
@@ -2301,8 +2454,8 @@ function revokeSkill(skillName) {
2301
2454
  const approved = loadApprovedSkills();
2302
2455
  const filtered = approved.filter((s) => s.name !== skillName);
2303
2456
  saveApprovedSkills(filtered);
2304
- const skillPath = path6.join(skillsDir, skillName);
2305
- if (fs7.existsSync(skillPath)) {
2457
+ const skillPath = path8.join(skillsDir, skillName);
2458
+ if (fs8.existsSync(skillPath)) {
2306
2459
  quarantineSkill(skillName, skillPath);
2307
2460
  }
2308
2461
  console.log(`[SkillsWatcher] Revoked approval for skill: ${skillName}`);
@@ -2314,17 +2467,17 @@ function revokeSkill(skillName) {
2314
2467
  function listQuarantined() {
2315
2468
  const results = [];
2316
2469
  try {
2317
- if (!fs7.existsSync(QUARANTINE_DIR)) {
2470
+ if (!fs8.existsSync(QUARANTINE_DIR)) {
2318
2471
  return results;
2319
2472
  }
2320
- const entries = fs7.readdirSync(QUARANTINE_DIR, { withFileTypes: true });
2473
+ const entries = fs8.readdirSync(QUARANTINE_DIR, { withFileTypes: true });
2321
2474
  for (const entry of entries) {
2322
2475
  if (entry.isDirectory()) {
2323
- const stat = fs7.statSync(path6.join(QUARANTINE_DIR, entry.name));
2476
+ const stat = fs8.statSync(path8.join(QUARANTINE_DIR, entry.name));
2324
2477
  results.push({
2325
2478
  name: entry.name,
2326
2479
  quarantinedAt: stat.mtime.toISOString(),
2327
- originalPath: path6.join(skillsDir, entry.name),
2480
+ originalPath: path8.join(skillsDir, entry.name),
2328
2481
  reason: "Skill not in approved list"
2329
2482
  });
2330
2483
  }
@@ -2361,15 +2514,15 @@ function removeFromApprovedList(skillName) {
2361
2514
  // libs/shield-daemon/src/services/integration-skills.ts
2362
2515
  var AGENCO_SKILL_NAME = "agenco-secure-integrations";
2363
2516
  function copyDirSync(src, dest) {
2364
- fs8.mkdirSync(dest, { recursive: true });
2365
- const entries = fs8.readdirSync(src, { withFileTypes: true });
2517
+ fs9.mkdirSync(dest, { recursive: true });
2518
+ const entries = fs9.readdirSync(src, { withFileTypes: true });
2366
2519
  for (const entry of entries) {
2367
- const srcPath = path7.join(src, entry.name);
2368
- const destPath = path7.join(dest, entry.name);
2520
+ const srcPath = path9.join(src, entry.name);
2521
+ const destPath = path9.join(dest, entry.name);
2369
2522
  if (entry.isDirectory()) {
2370
2523
  copyDirSync(srcPath, destPath);
2371
2524
  } else {
2372
- fs8.copyFileSync(srcPath, destPath);
2525
+ fs9.copyFileSync(srcPath, destPath);
2373
2526
  }
2374
2527
  }
2375
2528
  }
@@ -2379,9 +2532,9 @@ async function provisionAgenCoSkill() {
2379
2532
  console.warn("[IntegrationSkills] Skills directory not configured \u2014 skipping provision");
2380
2533
  return { installed: false };
2381
2534
  }
2382
- const destDir = path7.join(skillsDir2, AGENCO_SKILL_NAME);
2383
- const srcDir = path7.join(BUILTIN_SKILLS_DIR, AGENCO_SKILL_NAME);
2384
- if (fs8.existsSync(destDir)) {
2535
+ const destDir = path9.join(skillsDir2, AGENCO_SKILL_NAME);
2536
+ const srcDir = path9.join(BUILTIN_SKILLS_DIR, AGENCO_SKILL_NAME);
2537
+ if (fs9.existsSync(destDir)) {
2385
2538
  return { installed: false };
2386
2539
  }
2387
2540
  try {
@@ -2392,8 +2545,8 @@ async function provisionAgenCoSkill() {
2392
2545
  } catch (err) {
2393
2546
  console.error(`[IntegrationSkills] Failed to install "${AGENCO_SKILL_NAME}":`, err.message);
2394
2547
  try {
2395
- if (fs8.existsSync(destDir)) {
2396
- fs8.rmSync(destDir, { recursive: true, force: true });
2548
+ if (fs9.existsSync(destDir)) {
2549
+ fs9.rmSync(destDir, { recursive: true, force: true });
2397
2550
  }
2398
2551
  removeFromApprovedList(AGENCO_SKILL_NAME);
2399
2552
  } catch {
@@ -2408,12 +2561,12 @@ async function provisionIntegrationSkill(integrationSlug) {
2408
2561
  return { installed: false };
2409
2562
  }
2410
2563
  const skillName = `integration-${integrationSlug}`;
2411
- const destDir = path7.join(skillsDir2, skillName);
2412
- const srcDir = path7.join(BUILTIN_SKILLS_DIR, skillName);
2413
- if (fs8.existsSync(destDir)) {
2564
+ const destDir = path9.join(skillsDir2, skillName);
2565
+ const srcDir = path9.join(BUILTIN_SKILLS_DIR, skillName);
2566
+ if (fs9.existsSync(destDir)) {
2414
2567
  return { installed: false };
2415
2568
  }
2416
- if (!fs8.existsSync(srcDir)) {
2569
+ if (!fs9.existsSync(srcDir)) {
2417
2570
  return { installed: false };
2418
2571
  }
2419
2572
  try {
@@ -2424,8 +2577,8 @@ async function provisionIntegrationSkill(integrationSlug) {
2424
2577
  } catch (err) {
2425
2578
  console.error(`[IntegrationSkills] Failed to install "${skillName}":`, err.message);
2426
2579
  try {
2427
- if (fs8.existsSync(destDir)) {
2428
- fs8.rmSync(destDir, { recursive: true, force: true });
2580
+ if (fs9.existsSync(destDir)) {
2581
+ fs9.rmSync(destDir, { recursive: true, force: true });
2429
2582
  }
2430
2583
  removeFromApprovedList(skillName);
2431
2584
  } catch {
@@ -4948,15 +5101,15 @@ async function agencoRoutes(app) {
4948
5101
  }
4949
5102
 
4950
5103
  // libs/shield-daemon/src/routes/skills.ts
4951
- import * as fs13 from "node:fs";
4952
- import * as path12 from "node:path";
4953
- import { execSync as execSync8 } from "node:child_process";
5104
+ import * as fs14 from "node:fs";
5105
+ import * as path14 from "node:path";
5106
+ import { execSync as execSync9 } from "node:child_process";
4954
5107
  import { parseSkillMd } from "@agenshield/sandbox";
4955
5108
 
4956
5109
  // libs/shield-daemon/src/services/skill-analyzer.ts
4957
- import * as fs9 from "node:fs";
4958
- import * as path8 from "node:path";
4959
- import { execSync as execSync5 } from "node:child_process";
5110
+ import * as fs10 from "node:fs";
5111
+ import * as path10 from "node:path";
5112
+ import { execSync as execSync6 } from "node:child_process";
4960
5113
  var ANALYSIS_CACHE_PATH = "/opt/agenshield/config/skill-analyses.json";
4961
5114
  var COMMAND_PATTERNS = [
4962
5115
  // Bash-style: command at start of line or after pipe/semicolon
@@ -5017,8 +5170,8 @@ var IGNORE_WORDS = /* @__PURE__ */ new Set([
5017
5170
  ]);
5018
5171
  function loadCache() {
5019
5172
  try {
5020
- if (fs9.existsSync(ANALYSIS_CACHE_PATH)) {
5021
- return JSON.parse(fs9.readFileSync(ANALYSIS_CACHE_PATH, "utf-8"));
5173
+ if (fs10.existsSync(ANALYSIS_CACHE_PATH)) {
5174
+ return JSON.parse(fs10.readFileSync(ANALYSIS_CACHE_PATH, "utf-8"));
5022
5175
  }
5023
5176
  } catch {
5024
5177
  }
@@ -5026,18 +5179,18 @@ function loadCache() {
5026
5179
  }
5027
5180
  function saveCache(cache3) {
5028
5181
  try {
5029
- const dir = path8.dirname(ANALYSIS_CACHE_PATH);
5030
- if (!fs9.existsSync(dir)) {
5031
- fs9.mkdirSync(dir, { recursive: true });
5182
+ const dir = path10.dirname(ANALYSIS_CACHE_PATH);
5183
+ if (!fs10.existsSync(dir)) {
5184
+ fs10.mkdirSync(dir, { recursive: true });
5032
5185
  }
5033
- fs9.writeFileSync(ANALYSIS_CACHE_PATH, JSON.stringify(cache3, null, 2) + "\n", "utf-8");
5186
+ fs10.writeFileSync(ANALYSIS_CACHE_PATH, JSON.stringify(cache3, null, 2) + "\n", "utf-8");
5034
5187
  } catch (err) {
5035
5188
  console.error("[SkillAnalyzer] Failed to save cache:", err.message);
5036
5189
  }
5037
5190
  }
5038
5191
  function resolveCommand(name) {
5039
5192
  try {
5040
- const result = execSync5(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
5193
+ const result = execSync6(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
5041
5194
  return result || void 0;
5042
5195
  } catch {
5043
5196
  return void 0;
@@ -5172,33 +5325,33 @@ function clearCachedAnalysis(skillName) {
5172
5325
  }
5173
5326
 
5174
5327
  // libs/shield-daemon/src/services/skill-lifecycle.ts
5175
- import * as fs10 from "node:fs";
5176
- import * as path9 from "node:path";
5177
- import { execSync as execSync6 } from "node:child_process";
5328
+ import * as fs11 from "node:fs";
5329
+ import * as path11 from "node:path";
5330
+ import { execSync as execSync7 } from "node:child_process";
5178
5331
  function createSkillWrapper(name, binDir) {
5179
- if (!fs10.existsSync(binDir)) {
5180
- fs10.mkdirSync(binDir, { recursive: true });
5332
+ if (!fs11.existsSync(binDir)) {
5333
+ fs11.mkdirSync(binDir, { recursive: true });
5181
5334
  }
5182
- const wrapperPath = path9.join(binDir, name);
5335
+ const wrapperPath = path11.join(binDir, name);
5183
5336
  const wrapperContent = `#!/bin/bash
5184
5337
  # ${name} skill wrapper - policy-enforced execution
5185
5338
  # Ensure accessible working directory
5186
5339
  if ! /bin/pwd > /dev/null 2>&1; then cd ~ 2>/dev/null || cd /; fi
5187
5340
  exec /opt/agenshield/bin/shield-client skill run "${name}" "$@"
5188
5341
  `;
5189
- fs10.writeFileSync(wrapperPath, wrapperContent, { mode: 493 });
5342
+ fs11.writeFileSync(wrapperPath, wrapperContent, { mode: 493 });
5190
5343
  const socketGroup = process.env["AGENSHIELD_SOCKET_GROUP"] || "clawshield";
5191
5344
  try {
5192
- execSync6(`chown root:${socketGroup} "${wrapperPath}"`, { stdio: "pipe" });
5193
- execSync6(`chmod 755 "${wrapperPath}"`, { stdio: "pipe" });
5345
+ execSync7(`chown root:${socketGroup} "${wrapperPath}"`, { stdio: "pipe" });
5346
+ execSync7(`chmod 755 "${wrapperPath}"`, { stdio: "pipe" });
5194
5347
  } catch {
5195
5348
  }
5196
5349
  }
5197
5350
  function removeSkillWrapper(name, binDir) {
5198
- const wrapperPath = path9.join(binDir, name);
5351
+ const wrapperPath = path11.join(binDir, name);
5199
5352
  try {
5200
- if (fs10.existsSync(wrapperPath)) {
5201
- fs10.unlinkSync(wrapperPath);
5353
+ if (fs11.existsSync(wrapperPath)) {
5354
+ fs11.unlinkSync(wrapperPath);
5202
5355
  }
5203
5356
  } catch {
5204
5357
  }
@@ -5231,18 +5384,18 @@ function removeSkillPolicy(name) {
5231
5384
  }
5232
5385
 
5233
5386
  // libs/shield-daemon/src/services/openclaw-config.ts
5234
- import * as fs11 from "node:fs";
5235
- import * as path10 from "node:path";
5236
- import { execSync as execSync7 } from "node:child_process";
5387
+ import * as fs12 from "node:fs";
5388
+ import * as path12 from "node:path";
5389
+ import { execSync as execSync8 } from "node:child_process";
5237
5390
  function getOpenClawConfigPath() {
5238
5391
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
5239
- return path10.join(agentHome, ".openclaw", "openclaw.json");
5392
+ return path12.join(agentHome, ".openclaw", "openclaw.json");
5240
5393
  }
5241
5394
  function readConfig() {
5242
5395
  const configPath = getOpenClawConfigPath();
5243
5396
  try {
5244
- if (fs11.existsSync(configPath)) {
5245
- return JSON.parse(fs11.readFileSync(configPath, "utf-8"));
5397
+ if (fs12.existsSync(configPath)) {
5398
+ return JSON.parse(fs12.readFileSync(configPath, "utf-8"));
5246
5399
  }
5247
5400
  } catch {
5248
5401
  console.warn("[OpenClawConfig] Failed to read openclaw.json, starting fresh");
@@ -5251,14 +5404,14 @@ function readConfig() {
5251
5404
  }
5252
5405
  function writeConfig(config) {
5253
5406
  const configPath = getOpenClawConfigPath();
5254
- fs11.mkdirSync(path10.dirname(configPath), { recursive: true });
5255
- fs11.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
5407
+ fs12.mkdirSync(path12.dirname(configPath), { recursive: true });
5408
+ fs12.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
5256
5409
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
5257
- const brokerUser = path10.basename(agentHome) + "_broker";
5410
+ const brokerUser = path12.basename(agentHome) + "_broker";
5258
5411
  const socketGroup = process.env["AGENSHIELD_SOCKET_GROUP"] || "clawshield";
5259
5412
  try {
5260
- execSync7(`chown ${brokerUser}:${socketGroup} "${configPath}"`, { stdio: "pipe" });
5261
- execSync7(`chmod 664 "${configPath}"`, { stdio: "pipe" });
5413
+ execSync8(`chown ${brokerUser}:${socketGroup} "${configPath}"`, { stdio: "pipe" });
5414
+ execSync8(`chmod 664 "${configPath}"`, { stdio: "pipe" });
5262
5415
  } catch {
5263
5416
  }
5264
5417
  }
@@ -5287,8 +5440,8 @@ function removeSkillEntry(slug) {
5287
5440
  }
5288
5441
 
5289
5442
  // libs/shield-daemon/src/services/marketplace.ts
5290
- import * as fs12 from "node:fs";
5291
- import * as path11 from "node:path";
5443
+ import * as fs13 from "node:fs";
5444
+ import * as path13 from "node:path";
5292
5445
  import * as os4 from "node:os";
5293
5446
  import { CONFIG_DIR as CONFIG_DIR2, MARKETPLACE_DIR } from "@agenshield/ipc";
5294
5447
  var cache = /* @__PURE__ */ new Map();
@@ -5312,35 +5465,35 @@ var ANALYSIS_TIMEOUT = 4 * 6e4;
5312
5465
  var SEARCH_CACHE_TTL = 6e4;
5313
5466
  var DETAIL_CACHE_TTL = 5 * 6e4;
5314
5467
  var SHORT_TIMEOUT = 1e4;
5315
- async function convexAction(path18, args, timeout) {
5468
+ async function convexAction(path20, args, timeout) {
5316
5469
  const res = await fetch(`${CONVEX_BASE}/api/action`, {
5317
5470
  method: "POST",
5318
5471
  signal: AbortSignal.timeout(timeout),
5319
5472
  headers: { "Content-Type": "application/json" },
5320
- body: JSON.stringify({ path: path18, args, format: "json" })
5473
+ body: JSON.stringify({ path: path20, args, format: "json" })
5321
5474
  });
5322
5475
  if (!res.ok) {
5323
- throw new Error(`Convex action ${path18} returned ${res.status}`);
5476
+ throw new Error(`Convex action ${path20} returned ${res.status}`);
5324
5477
  }
5325
5478
  const body = await res.json();
5326
5479
  if (body.status === "error") {
5327
- throw new Error(`Convex action ${path18}: ${body.errorMessage ?? "unknown error"}`);
5480
+ throw new Error(`Convex action ${path20}: ${body.errorMessage ?? "unknown error"}`);
5328
5481
  }
5329
5482
  return body.value;
5330
5483
  }
5331
- async function convexQuery(path18, args, timeout) {
5484
+ async function convexQuery(path20, args, timeout) {
5332
5485
  const res = await fetch(`${CONVEX_BASE}/api/query`, {
5333
5486
  method: "POST",
5334
5487
  signal: AbortSignal.timeout(timeout),
5335
5488
  headers: { "Content-Type": "application/json" },
5336
- body: JSON.stringify({ path: path18, args, format: "json" })
5489
+ body: JSON.stringify({ path: path20, args, format: "json" })
5337
5490
  });
5338
5491
  if (!res.ok) {
5339
- throw new Error(`Convex query ${path18} returned ${res.status}`);
5492
+ throw new Error(`Convex query ${path20} returned ${res.status}`);
5340
5493
  }
5341
5494
  const body = await res.json();
5342
5495
  if (body.status === "error") {
5343
- throw new Error(`Convex query ${path18}: ${body.errorMessage ?? "unknown error"}`);
5496
+ throw new Error(`Convex query ${path20}: ${body.errorMessage ?? "unknown error"}`);
5344
5497
  }
5345
5498
  return body.value;
5346
5499
  }
@@ -5401,7 +5554,7 @@ function isImageExt(filePath) {
5401
5554
  }
5402
5555
  var MAX_IMAGE_SIZE = 5e5;
5403
5556
  function getMarketplaceDir() {
5404
- return path11.join(os4.homedir(), CONFIG_DIR2, MARKETPLACE_DIR);
5557
+ return path13.join(os4.homedir(), CONFIG_DIR2, MARKETPLACE_DIR);
5405
5558
  }
5406
5559
  async function downloadAndExtractZip(slug) {
5407
5560
  const url = `${CLAWHUB_DOWNLOAD_BASE}/download?slug=${encodeURIComponent(slug)}`;
@@ -5439,39 +5592,39 @@ async function downloadAndExtractZip(slug) {
5439
5592
  return files;
5440
5593
  }
5441
5594
  function storeDownloadedSkill(slug, meta, files) {
5442
- const dir = path11.join(getMarketplaceDir(), slug);
5443
- const filesDir = path11.join(dir, "files");
5444
- fs12.mkdirSync(filesDir, { recursive: true });
5595
+ const dir = path13.join(getMarketplaceDir(), slug);
5596
+ const filesDir = path13.join(dir, "files");
5597
+ fs13.mkdirSync(filesDir, { recursive: true });
5445
5598
  const fullMeta = { ...meta, downloadedAt: (/* @__PURE__ */ new Date()).toISOString() };
5446
- fs12.writeFileSync(path11.join(dir, "metadata.json"), JSON.stringify(fullMeta, null, 2), "utf-8");
5599
+ fs13.writeFileSync(path13.join(dir, "metadata.json"), JSON.stringify(fullMeta, null, 2), "utf-8");
5447
5600
  for (const file of files) {
5448
- const filePath = path11.join(filesDir, file.name);
5449
- fs12.mkdirSync(path11.dirname(filePath), { recursive: true });
5450
- fs12.writeFileSync(filePath, file.content, "utf-8");
5601
+ const filePath = path13.join(filesDir, file.name);
5602
+ fs13.mkdirSync(path13.dirname(filePath), { recursive: true });
5603
+ fs13.writeFileSync(filePath, file.content, "utf-8");
5451
5604
  }
5452
5605
  console.log(`[Marketplace] Stored ${files.length} files for ${slug}`);
5453
5606
  }
5454
5607
  function updateDownloadedAnalysis(slug, analysis) {
5455
- const metaPath = path11.join(getMarketplaceDir(), slug, "metadata.json");
5608
+ const metaPath = path13.join(getMarketplaceDir(), slug, "metadata.json");
5456
5609
  try {
5457
- if (!fs12.existsSync(metaPath)) return;
5458
- const meta = JSON.parse(fs12.readFileSync(metaPath, "utf-8"));
5610
+ if (!fs13.existsSync(metaPath)) return;
5611
+ const meta = JSON.parse(fs13.readFileSync(metaPath, "utf-8"));
5459
5612
  meta.analysis = analysis;
5460
- fs12.writeFileSync(metaPath, JSON.stringify(meta, null, 2), "utf-8");
5613
+ fs13.writeFileSync(metaPath, JSON.stringify(meta, null, 2), "utf-8");
5461
5614
  } catch {
5462
5615
  }
5463
5616
  }
5464
5617
  function listDownloadedSkills() {
5465
5618
  const baseDir = getMarketplaceDir();
5466
- if (!fs12.existsSync(baseDir)) return [];
5619
+ if (!fs13.existsSync(baseDir)) return [];
5467
5620
  const results = [];
5468
5621
  try {
5469
- const entries = fs12.readdirSync(baseDir, { withFileTypes: true });
5622
+ const entries = fs13.readdirSync(baseDir, { withFileTypes: true });
5470
5623
  for (const entry of entries) {
5471
5624
  if (!entry.isDirectory()) continue;
5472
- const metaPath = path11.join(baseDir, entry.name, "metadata.json");
5625
+ const metaPath = path13.join(baseDir, entry.name, "metadata.json");
5473
5626
  try {
5474
- const meta = JSON.parse(fs12.readFileSync(metaPath, "utf-8"));
5627
+ const meta = JSON.parse(fs13.readFileSync(metaPath, "utf-8"));
5475
5628
  results.push({
5476
5629
  slug: meta.slug,
5477
5630
  name: meta.name,
@@ -5488,17 +5641,17 @@ function listDownloadedSkills() {
5488
5641
  return results;
5489
5642
  }
5490
5643
  function getDownloadedSkillFiles(slug) {
5491
- const filesDir = path11.join(getMarketplaceDir(), slug, "files");
5492
- if (!fs12.existsSync(filesDir)) return [];
5644
+ const filesDir = path13.join(getMarketplaceDir(), slug, "files");
5645
+ if (!fs13.existsSync(filesDir)) return [];
5493
5646
  const files = [];
5494
5647
  function walk(dir, prefix) {
5495
- const entries = fs12.readdirSync(dir, { withFileTypes: true });
5648
+ const entries = fs13.readdirSync(dir, { withFileTypes: true });
5496
5649
  for (const entry of entries) {
5497
5650
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
5498
5651
  if (entry.isDirectory()) {
5499
- walk(path11.join(dir, entry.name), rel);
5652
+ walk(path13.join(dir, entry.name), rel);
5500
5653
  } else {
5501
- const content = fs12.readFileSync(path11.join(dir, entry.name), "utf-8");
5654
+ const content = fs13.readFileSync(path13.join(dir, entry.name), "utf-8");
5502
5655
  files.push({ name: rel, type: guessContentType(entry.name), content });
5503
5656
  }
5504
5657
  }
@@ -5507,10 +5660,10 @@ function getDownloadedSkillFiles(slug) {
5507
5660
  return files;
5508
5661
  }
5509
5662
  function getDownloadedSkillMeta(slug) {
5510
- const metaPath = path11.join(getMarketplaceDir(), slug, "metadata.json");
5663
+ const metaPath = path13.join(getMarketplaceDir(), slug, "metadata.json");
5511
5664
  try {
5512
- if (fs12.existsSync(metaPath)) {
5513
- return JSON.parse(fs12.readFileSync(metaPath, "utf-8"));
5665
+ if (fs13.existsSync(metaPath)) {
5666
+ return JSON.parse(fs13.readFileSync(metaPath, "utf-8"));
5514
5667
  }
5515
5668
  } catch {
5516
5669
  }
@@ -6047,13 +6200,13 @@ function findSkillMdRecursive(dir, depth = 0) {
6047
6200
  if (depth > 3) return null;
6048
6201
  try {
6049
6202
  for (const name of ["SKILL.md", "skill.md", "README.md", "readme.md"]) {
6050
- const candidate = path12.join(dir, name);
6051
- if (fs13.existsSync(candidate)) return candidate;
6203
+ const candidate = path14.join(dir, name);
6204
+ if (fs14.existsSync(candidate)) return candidate;
6052
6205
  }
6053
- const entries = fs13.readdirSync(dir, { withFileTypes: true });
6206
+ const entries = fs14.readdirSync(dir, { withFileTypes: true });
6054
6207
  for (const entry of entries) {
6055
6208
  if (!entry.isDirectory()) continue;
6056
- const found = findSkillMdRecursive(path12.join(dir, entry.name), depth + 1);
6209
+ const found = findSkillMdRecursive(path14.join(dir, entry.name), depth + 1);
6057
6210
  if (found) return found;
6058
6211
  }
6059
6212
  } catch {
@@ -6064,7 +6217,7 @@ function readSkillDescription(skillDir) {
6064
6217
  try {
6065
6218
  const mdPath = findSkillMdRecursive(skillDir);
6066
6219
  if (!mdPath) return void 0;
6067
- const content = fs13.readFileSync(mdPath, "utf-8");
6220
+ const content = fs14.readFileSync(mdPath, "utf-8");
6068
6221
  const parsed = parseSkillMd(content);
6069
6222
  return parsed?.metadata?.description ?? void 0;
6070
6223
  } catch {
@@ -6083,7 +6236,7 @@ async function skillsRoutes(app) {
6083
6236
  let onDiskNames = [];
6084
6237
  if (skillsDir2) {
6085
6238
  try {
6086
- onDiskNames = fs13.readdirSync(skillsDir2, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
6239
+ onDiskNames = fs14.readdirSync(skillsDir2, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
6087
6240
  } catch {
6088
6241
  }
6089
6242
  }
@@ -6096,9 +6249,9 @@ async function skillsRoutes(app) {
6096
6249
  name: a.name,
6097
6250
  source: "user",
6098
6251
  status: "active",
6099
- path: path12.join(skillsDir2 ?? "", a.name),
6252
+ path: path14.join(skillsDir2 ?? "", a.name),
6100
6253
  publisher: a.publisher,
6101
- description: skillsDir2 ? readSkillDescription(path12.join(skillsDir2, a.name)) : void 0
6254
+ description: skillsDir2 ? readSkillDescription(path14.join(skillsDir2, a.name)) : void 0
6102
6255
  })),
6103
6256
  // Quarantined
6104
6257
  ...quarantined.map((q) => ({
@@ -6113,8 +6266,8 @@ async function skillsRoutes(app) {
6113
6266
  name,
6114
6267
  source: "workspace",
6115
6268
  status: "workspace",
6116
- path: path12.join(skillsDir2 ?? "", name),
6117
- description: skillsDir2 ? readSkillDescription(path12.join(skillsDir2, name)) : void 0
6269
+ path: path14.join(skillsDir2 ?? "", name),
6270
+ description: skillsDir2 ? readSkillDescription(path14.join(skillsDir2, name)) : void 0
6118
6271
  })),
6119
6272
  // Downloaded (not installed) → available
6120
6273
  ...availableDownloads.map((d) => ({
@@ -6155,20 +6308,20 @@ async function skillsRoutes(app) {
6155
6308
  } else if (entry) {
6156
6309
  source = "user";
6157
6310
  status = "active";
6158
- skillPath = skillsDir2 ? path12.join(skillsDir2, name) : "";
6311
+ skillPath = skillsDir2 ? path14.join(skillsDir2, name) : "";
6159
6312
  } else if (skillsDir2) {
6160
6313
  source = "workspace";
6161
6314
  status = "workspace";
6162
- skillPath = path12.join(skillsDir2, name);
6315
+ skillPath = path14.join(skillsDir2, name);
6163
6316
  }
6164
6317
  let content = "";
6165
6318
  let metadata;
6166
- const dirToRead = skillPath || (skillsDir2 ? path12.join(skillsDir2, name) : "");
6319
+ const dirToRead = skillPath || (skillsDir2 ? path14.join(skillsDir2, name) : "");
6167
6320
  if (dirToRead) {
6168
6321
  try {
6169
6322
  const mdPath = findSkillMdRecursive(dirToRead);
6170
6323
  if (mdPath) {
6171
- content = fs13.readFileSync(mdPath, "utf-8");
6324
+ content = fs14.readFileSync(mdPath, "utf-8");
6172
6325
  const parsed = parseSkillMd(content);
6173
6326
  metadata = parsed?.metadata;
6174
6327
  }
@@ -6297,10 +6450,10 @@ async function skillsRoutes(app) {
6297
6450
  return reply.code(500).send({ error: "Skills directory not configured" });
6298
6451
  }
6299
6452
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
6300
- const binDir = path12.join(agentHome, "bin");
6453
+ const binDir = path14.join(agentHome, "bin");
6301
6454
  const socketGroup = process.env["AGENSHIELD_SOCKET_GROUP"] || "clawshield";
6302
- const skillDir = path12.join(skillsDir2, name);
6303
- const isInstalled = fs13.existsSync(skillDir);
6455
+ const skillDir = path14.join(skillsDir2, name);
6456
+ const isInstalled = fs14.existsSync(skillDir);
6304
6457
  if (isInstalled) {
6305
6458
  try {
6306
6459
  const brokerAvailable = await isBrokerAvailable();
@@ -6310,7 +6463,7 @@ async function skillsRoutes(app) {
6310
6463
  agentHome
6311
6464
  });
6312
6465
  } else {
6313
- fs13.rmSync(skillDir, { recursive: true, force: true });
6466
+ fs14.rmSync(skillDir, { recursive: true, force: true });
6314
6467
  removeSkillWrapper(name, binDir);
6315
6468
  }
6316
6469
  removeSkillEntry(name);
@@ -6344,15 +6497,15 @@ async function skillsRoutes(app) {
6344
6497
  throw new Error("Broker failed to install skill files");
6345
6498
  }
6346
6499
  } else {
6347
- fs13.mkdirSync(skillDir, { recursive: true });
6500
+ fs14.mkdirSync(skillDir, { recursive: true });
6348
6501
  for (const file of files) {
6349
- const filePath = path12.join(skillDir, file.name);
6350
- fs13.mkdirSync(path12.dirname(filePath), { recursive: true });
6351
- fs13.writeFileSync(filePath, file.content, "utf-8");
6502
+ const filePath = path14.join(skillDir, file.name);
6503
+ fs14.mkdirSync(path14.dirname(filePath), { recursive: true });
6504
+ fs14.writeFileSync(filePath, file.content, "utf-8");
6352
6505
  }
6353
6506
  try {
6354
- execSync8(`chown -R root:${socketGroup} "${skillDir}"`, { stdio: "pipe" });
6355
- execSync8(`chmod -R a+rX,go-w "${skillDir}"`, { stdio: "pipe" });
6507
+ execSync9(`chown -R root:${socketGroup} "${skillDir}"`, { stdio: "pipe" });
6508
+ execSync9(`chmod -R a+rX,go-w "${skillDir}"`, { stdio: "pipe" });
6356
6509
  } catch {
6357
6510
  }
6358
6511
  createSkillWrapper(name, binDir);
@@ -6363,8 +6516,8 @@ async function skillsRoutes(app) {
6363
6516
  return reply.send({ success: true, action: "enabled", name });
6364
6517
  } catch (err) {
6365
6518
  try {
6366
- if (fs13.existsSync(skillDir)) {
6367
- fs13.rmSync(skillDir, { recursive: true, force: true });
6519
+ if (fs14.existsSync(skillDir)) {
6520
+ fs14.rmSync(skillDir, { recursive: true, force: true });
6368
6521
  }
6369
6522
  removeFromApprovedList(name);
6370
6523
  } catch {
@@ -6402,20 +6555,20 @@ async function skillsRoutes(app) {
6402
6555
  return reply.code(500).send({ error: "Skills directory not configured" });
6403
6556
  }
6404
6557
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
6405
- const binDir = path12.join(agentHome, "bin");
6558
+ const binDir = path14.join(agentHome, "bin");
6406
6559
  const socketGroup = process.env["AGENSHIELD_SOCKET_GROUP"] || "clawshield";
6407
- const skillDir = path12.join(skillsDir2, name);
6560
+ const skillDir = path14.join(skillsDir2, name);
6408
6561
  try {
6409
6562
  addToApprovedList(name, publisher);
6410
- fs13.mkdirSync(skillDir, { recursive: true });
6563
+ fs14.mkdirSync(skillDir, { recursive: true });
6411
6564
  for (const file of files) {
6412
- const filePath = path12.join(skillDir, file.name);
6413
- fs13.mkdirSync(path12.dirname(filePath), { recursive: true });
6414
- fs13.writeFileSync(filePath, file.content, "utf-8");
6565
+ const filePath = path14.join(skillDir, file.name);
6566
+ fs14.mkdirSync(path14.dirname(filePath), { recursive: true });
6567
+ fs14.writeFileSync(filePath, file.content, "utf-8");
6415
6568
  }
6416
6569
  try {
6417
- execSync8(`chown -R root:${socketGroup} "${skillDir}"`, { stdio: "pipe" });
6418
- execSync8(`chmod -R a+rX,go-w "${skillDir}"`, { stdio: "pipe" });
6570
+ execSync9(`chown -R root:${socketGroup} "${skillDir}"`, { stdio: "pipe" });
6571
+ execSync9(`chmod -R a+rX,go-w "${skillDir}"`, { stdio: "pipe" });
6419
6572
  } catch {
6420
6573
  }
6421
6574
  createSkillWrapper(name, binDir);
@@ -6423,8 +6576,8 @@ async function skillsRoutes(app) {
6423
6576
  return reply.send({ success: true, name, analysis });
6424
6577
  } catch (err) {
6425
6578
  try {
6426
- if (fs13.existsSync(skillDir)) {
6427
- fs13.rmSync(skillDir, { recursive: true, force: true });
6579
+ if (fs14.existsSync(skillDir)) {
6580
+ fs14.rmSync(skillDir, { recursive: true, force: true });
6428
6581
  }
6429
6582
  removeFromApprovedList(name);
6430
6583
  } catch {
@@ -6439,8 +6592,8 @@ async function skillsRoutes(app) {
6439
6592
  }
6440
6593
 
6441
6594
  // libs/shield-daemon/src/routes/exec.ts
6442
- import * as fs14 from "node:fs";
6443
- import * as path13 from "node:path";
6595
+ import * as fs15 from "node:fs";
6596
+ import * as path15 from "node:path";
6444
6597
  var ALLOWED_COMMANDS_PATH2 = "/opt/agenshield/config/allowed-commands.json";
6445
6598
  var BIN_DIRS = [
6446
6599
  "/usr/bin",
@@ -6453,22 +6606,22 @@ var binCache = null;
6453
6606
  var BIN_CACHE_TTL = 6e4;
6454
6607
  var VALID_NAME = /^[a-zA-Z0-9_-]+$/;
6455
6608
  function loadConfig2() {
6456
- if (!fs14.existsSync(ALLOWED_COMMANDS_PATH2)) {
6609
+ if (!fs15.existsSync(ALLOWED_COMMANDS_PATH2)) {
6457
6610
  return { version: "1.0.0", commands: [] };
6458
6611
  }
6459
6612
  try {
6460
- const content = fs14.readFileSync(ALLOWED_COMMANDS_PATH2, "utf-8");
6613
+ const content = fs15.readFileSync(ALLOWED_COMMANDS_PATH2, "utf-8");
6461
6614
  return JSON.parse(content);
6462
6615
  } catch {
6463
6616
  return { version: "1.0.0", commands: [] };
6464
6617
  }
6465
6618
  }
6466
6619
  function saveConfig2(config) {
6467
- const dir = path13.dirname(ALLOWED_COMMANDS_PATH2);
6468
- if (!fs14.existsSync(dir)) {
6469
- fs14.mkdirSync(dir, { recursive: true });
6620
+ const dir = path15.dirname(ALLOWED_COMMANDS_PATH2);
6621
+ if (!fs15.existsSync(dir)) {
6622
+ fs15.mkdirSync(dir, { recursive: true });
6470
6623
  }
6471
- fs14.writeFileSync(ALLOWED_COMMANDS_PATH2, JSON.stringify(config, null, 2) + "\n", "utf-8");
6624
+ fs15.writeFileSync(ALLOWED_COMMANDS_PATH2, JSON.stringify(config, null, 2) + "\n", "utf-8");
6472
6625
  }
6473
6626
  function scanSystemBins() {
6474
6627
  const pathDirs = (process.env.PATH ?? "").split(":").filter(Boolean);
@@ -6477,13 +6630,13 @@ function scanSystemBins() {
6477
6630
  const results = [];
6478
6631
  for (const dir of allDirs) {
6479
6632
  try {
6480
- if (!fs14.existsSync(dir)) continue;
6481
- const entries = fs14.readdirSync(dir);
6633
+ if (!fs15.existsSync(dir)) continue;
6634
+ const entries = fs15.readdirSync(dir);
6482
6635
  for (const entry of entries) {
6483
6636
  if (seen.has(entry)) continue;
6484
- const fullPath = path13.join(dir, entry);
6637
+ const fullPath = path15.join(dir, entry);
6485
6638
  try {
6486
- const stat = fs14.statSync(fullPath);
6639
+ const stat = fs15.statSync(fullPath);
6487
6640
  if (stat.isFile() && (stat.mode & 73) !== 0) {
6488
6641
  seen.add(entry);
6489
6642
  results.push({ name: entry, path: fullPath });
@@ -6536,7 +6689,7 @@ async function execRoutes(app) {
6536
6689
  };
6537
6690
  }
6538
6691
  for (const p of paths) {
6539
- if (!path13.isAbsolute(p)) {
6692
+ if (!path15.isAbsolute(p)) {
6540
6693
  return {
6541
6694
  success: false,
6542
6695
  error: {
@@ -6963,8 +7116,8 @@ async function secretsRoutes(app) {
6963
7116
  }
6964
7117
 
6965
7118
  // libs/shield-daemon/src/routes/marketplace.ts
6966
- import * as fs15 from "node:fs";
6967
- import * as path14 from "node:path";
7119
+ import * as fs16 from "node:fs";
7120
+ import * as path16 from "node:path";
6968
7121
  async function marketplaceRoutes(app) {
6969
7122
  app.get(
6970
7123
  "/marketplace/search",
@@ -7160,9 +7313,9 @@ async function marketplaceRoutes(app) {
7160
7313
  return reply.code(500).send({ error: "Skills directory not configured" });
7161
7314
  }
7162
7315
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
7163
- const binDir = path14.join(agentHome, "bin");
7316
+ const binDir = path16.join(agentHome, "bin");
7164
7317
  const socketGroup = process.env["AGENSHIELD_SOCKET_GROUP"] || "clawshield";
7165
- skillDir = path14.join(skillsDir2, slug);
7318
+ skillDir = path16.join(skillsDir2, slug);
7166
7319
  emitSkillInstallProgress(slug, "approve", "Pre-approving skill");
7167
7320
  addToApprovedList(slug, publisher);
7168
7321
  logs.push("Skill pre-approved");
@@ -7205,8 +7358,8 @@ async function marketplaceRoutes(app) {
7205
7358
  });
7206
7359
  } catch (err) {
7207
7360
  try {
7208
- if (skillDir && fs15.existsSync(skillDir)) {
7209
- fs15.rmSync(skillDir, { recursive: true, force: true });
7361
+ if (skillDir && fs16.existsSync(skillDir)) {
7362
+ fs16.rmSync(skillDir, { recursive: true, force: true });
7210
7363
  }
7211
7364
  removeFromApprovedList(slug);
7212
7365
  } catch {
@@ -7229,18 +7382,18 @@ async function marketplaceRoutes(app) {
7229
7382
  }
7230
7383
 
7231
7384
  // libs/shield-daemon/src/routes/fs.ts
7232
- import * as fs16 from "node:fs";
7233
- import * as path15 from "node:path";
7385
+ import * as fs17 from "node:fs";
7386
+ import * as path17 from "node:path";
7234
7387
  import * as os5 from "node:os";
7235
7388
  var MAX_ENTRIES = 200;
7236
7389
  async function fsRoutes(app) {
7237
7390
  app.get("/fs/browse", async (request) => {
7238
7391
  const dirPath = request.query.path || os5.homedir();
7239
7392
  const showHidden = request.query.showHidden === "true";
7240
- const resolvedPath = path15.resolve(dirPath);
7393
+ const resolvedPath = path17.resolve(dirPath);
7241
7394
  let dirents;
7242
7395
  try {
7243
- dirents = fs16.readdirSync(resolvedPath, { withFileTypes: true });
7396
+ dirents = fs17.readdirSync(resolvedPath, { withFileTypes: true });
7244
7397
  } catch {
7245
7398
  return { success: true, data: { entries: [] } };
7246
7399
  }
@@ -7249,7 +7402,7 @@ async function fsRoutes(app) {
7249
7402
  if (!showHidden && dirent.name.startsWith(".")) continue;
7250
7403
  entries.push({
7251
7404
  name: dirent.name,
7252
- path: path15.join(resolvedPath, dirent.name),
7405
+ path: path17.join(resolvedPath, dirent.name),
7253
7406
  type: dirent.isDirectory() ? "directory" : "file"
7254
7407
  });
7255
7408
  if (entries.length >= MAX_ENTRIES) break;
@@ -7263,8 +7416,8 @@ async function fsRoutes(app) {
7263
7416
  }
7264
7417
 
7265
7418
  // libs/shield-daemon/src/services/activity-log.ts
7266
- import * as fs17 from "node:fs";
7267
- import * as path16 from "node:path";
7419
+ import * as fs18 from "node:fs";
7420
+ import * as path18 from "node:path";
7268
7421
  var ACTIVITY_FILE = "activity.jsonl";
7269
7422
  var MAX_SIZE_BYTES = 100 * 1024 * 1024;
7270
7423
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -7281,12 +7434,12 @@ var ActivityLog = class {
7281
7434
  writeCount = 0;
7282
7435
  unsubscribe;
7283
7436
  constructor() {
7284
- this.filePath = path16.join(getConfigDir(), ACTIVITY_FILE);
7437
+ this.filePath = path18.join(getConfigDir(), ACTIVITY_FILE);
7285
7438
  }
7286
7439
  /** Read historical events from the JSONL file, newest first */
7287
7440
  getHistory(limit = 500) {
7288
- if (!fs17.existsSync(this.filePath)) return [];
7289
- const content = fs17.readFileSync(this.filePath, "utf-8");
7441
+ if (!fs18.existsSync(this.filePath)) return [];
7442
+ const content = fs18.readFileSync(this.filePath, "utf-8");
7290
7443
  const lines = content.split("\n").filter(Boolean);
7291
7444
  const events = [];
7292
7445
  for (const line of lines) {
@@ -7311,7 +7464,7 @@ var ActivityLog = class {
7311
7464
  }
7312
7465
  append(event) {
7313
7466
  const line = JSON.stringify(event) + "\n";
7314
- fs17.appendFileSync(this.filePath, line, "utf-8");
7467
+ fs18.appendFileSync(this.filePath, line, "utf-8");
7315
7468
  this.writeCount++;
7316
7469
  if (this.writeCount % PRUNE_INTERVAL === 0) {
7317
7470
  this.rotate();
@@ -7319,7 +7472,7 @@ var ActivityLog = class {
7319
7472
  }
7320
7473
  rotate() {
7321
7474
  try {
7322
- const stat = fs17.statSync(this.filePath);
7475
+ const stat = fs18.statSync(this.filePath);
7323
7476
  if (stat.size > MAX_SIZE_BYTES) {
7324
7477
  this.truncateBySize();
7325
7478
  }
@@ -7329,15 +7482,15 @@ var ActivityLog = class {
7329
7482
  }
7330
7483
  /** Keep newest half of lines when file exceeds size limit */
7331
7484
  truncateBySize() {
7332
- const content = fs17.readFileSync(this.filePath, "utf-8");
7485
+ const content = fs18.readFileSync(this.filePath, "utf-8");
7333
7486
  const lines = content.split("\n").filter(Boolean);
7334
7487
  const keep = lines.slice(Math.floor(lines.length / 2));
7335
- fs17.writeFileSync(this.filePath, keep.join("\n") + "\n", "utf-8");
7488
+ fs18.writeFileSync(this.filePath, keep.join("\n") + "\n", "utf-8");
7336
7489
  }
7337
7490
  /** Remove entries older than 24 hours */
7338
7491
  pruneOldEntries() {
7339
- if (!fs17.existsSync(this.filePath)) return;
7340
- const content = fs17.readFileSync(this.filePath, "utf-8");
7492
+ if (!fs18.existsSync(this.filePath)) return;
7493
+ const content = fs18.readFileSync(this.filePath, "utf-8");
7341
7494
  const lines = content.split("\n").filter(Boolean);
7342
7495
  const cutoff = Date.now() - MAX_AGE_MS;
7343
7496
  const kept = lines.filter((line) => {
@@ -7349,7 +7502,7 @@ var ActivityLog = class {
7349
7502
  }
7350
7503
  });
7351
7504
  if (kept.length < lines.length) {
7352
- fs17.writeFileSync(this.filePath, kept.join("\n") + "\n", "utf-8");
7505
+ fs18.writeFileSync(this.filePath, kept.join("\n") + "\n", "utf-8");
7353
7506
  }
7354
7507
  }
7355
7508
  };
@@ -7396,11 +7549,11 @@ function normalizeUrlTarget(url) {
7396
7549
  const trimmed = url.trim();
7397
7550
  try {
7398
7551
  const parsed = new URL(trimmed);
7399
- let path18 = parsed.pathname;
7400
- if (path18.length > 1) {
7401
- path18 = path18.replace(/\/+$/, "");
7552
+ let path20 = parsed.pathname;
7553
+ if (path20.length > 1) {
7554
+ path20 = path20.replace(/\/+$/, "");
7402
7555
  }
7403
- return `${parsed.protocol}//${parsed.host}${path18}${parsed.search}`;
7556
+ return `${parsed.protocol}//${parsed.host}${path20}${parsed.search}`;
7404
7557
  } catch {
7405
7558
  return trimmed.replace(/\/+$/, "");
7406
7559
  }
@@ -7634,22 +7787,22 @@ async function registerRoutes(app) {
7634
7787
  }
7635
7788
 
7636
7789
  // libs/shield-daemon/src/static.ts
7637
- import * as fs18 from "node:fs";
7638
- import * as path17 from "node:path";
7790
+ import * as fs19 from "node:fs";
7791
+ import * as path19 from "node:path";
7639
7792
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7640
7793
  var __filename = fileURLToPath2(import.meta.url);
7641
- var __dirname = path17.dirname(__filename);
7794
+ var __dirname = path19.dirname(__filename);
7642
7795
  function getUiAssetsPath() {
7643
- const pkgRootPath = path17.join(__dirname, "..", "ui-assets");
7644
- if (fs18.existsSync(pkgRootPath)) {
7796
+ const pkgRootPath = path19.join(__dirname, "..", "ui-assets");
7797
+ if (fs19.existsSync(pkgRootPath)) {
7645
7798
  return pkgRootPath;
7646
7799
  }
7647
- const bundledPath = path17.join(__dirname, "ui-assets");
7648
- if (fs18.existsSync(bundledPath)) {
7800
+ const bundledPath = path19.join(__dirname, "ui-assets");
7801
+ if (fs19.existsSync(bundledPath)) {
7649
7802
  return bundledPath;
7650
7803
  }
7651
- const devPath = path17.join(__dirname, "..", "..", "..", "dist", "apps", "shield-ui");
7652
- if (fs18.existsSync(devPath)) {
7804
+ const devPath = path19.join(__dirname, "..", "..", "..", "dist", "apps", "shield-ui");
7805
+ if (fs19.existsSync(devPath)) {
7653
7806
  return devPath;
7654
7807
  }
7655
7808
  return null;
@@ -7738,8 +7891,8 @@ async function startServer(config) {
7738
7891
  startSecurityWatcher(1e4);
7739
7892
  const agentHome = process.env["AGENSHIELD_AGENT_HOME"] || "/Users/ash_default_agent";
7740
7893
  const skillsDir2 = `${agentHome}/.openclaw/skills`;
7741
- if (!fs19.existsSync(skillsDir2)) {
7742
- fs19.mkdirSync(skillsDir2, { recursive: true, mode: 493 });
7894
+ if (!fs20.existsSync(skillsDir2)) {
7895
+ fs20.mkdirSync(skillsDir2, { recursive: true, mode: 493 });
7743
7896
  console.log(`[Daemon] Created skills directory: ${skillsDir2}`);
7744
7897
  }
7745
7898
  startSkillsWatcher(skillsDir2, {
@@ -7775,10 +7928,10 @@ async function main() {
7775
7928
  ensureConfigDir();
7776
7929
  const config = loadConfig();
7777
7930
  const pidPath = getPidPath();
7778
- fs20.writeFileSync(pidPath, process.pid.toString(), "utf-8");
7931
+ fs21.writeFileSync(pidPath, process.pid.toString(), "utf-8");
7779
7932
  const cleanup = () => {
7780
- if (fs20.existsSync(pidPath)) {
7781
- fs20.unlinkSync(pidPath);
7933
+ if (fs21.existsSync(pidPath)) {
7934
+ fs21.unlinkSync(pidPath);
7782
7935
  }
7783
7936
  process.exit(0);
7784
7937
  };