cclawd 2026.3.27 → 2026.3.28

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.
Files changed (51) hide show
  1. package/dist/.buildstamp +1 -1
  2. package/dist/build-info.json +3 -3
  3. package/dist/extensions/cclawd-guard/dashboard-launcher.js +1 -1
  4. package/dist/extensions/cclawd-guard/index.js +55 -376
  5. package/dist/extensions/discord/node_modules/.package-lock.json +3 -3
  6. package/dist/extensions/feishu/node_modules/.package-lock.json +7 -7
  7. package/dist/extensions/feishu/node_modules/qs/CHANGELOG.md +6 -0
  8. package/dist/extensions/feishu/node_modules/qs/dist/qs.js +16 -16
  9. package/dist/extensions/feishu/node_modules/qs/lib/parse.js +2 -2
  10. package/dist/extensions/feishu/node_modules/qs/package.json +3 -3
  11. package/dist/extensions/feishu/node_modules/qs/test/parse.js +86 -0
  12. package/dist/extensions/feishu/node_modules/qs/test/stringify.js +9 -0
  13. package/dist/extensions/feishu/node_modules/qs/test/utils.js +31 -3
  14. package/dist/extensions/feishu/node_modules/side-channel-list/CHANGELOG.md +25 -4
  15. package/dist/extensions/feishu/node_modules/side-channel-list/index.js +1 -3
  16. package/dist/extensions/feishu/node_modules/side-channel-list/package.json +8 -8
  17. package/dist/extensions/feishu/node_modules/side-channel-list/test/index.js +50 -0
  18. package/dist/extensions/slack/node_modules/.package-lock.json +10 -10
  19. package/dist/extensions/slack/node_modules/axios/CHANGELOG.md +1 -1
  20. package/dist/extensions/slack/node_modules/axios/README.md +90 -17
  21. package/dist/extensions/slack/node_modules/axios/dist/axios.js +47 -7
  22. package/dist/extensions/slack/node_modules/axios/dist/axios.js.map +1 -1
  23. package/dist/extensions/slack/node_modules/axios/dist/axios.min.js +3 -3
  24. package/dist/extensions/slack/node_modules/axios/dist/axios.min.js.map +1 -1
  25. package/dist/extensions/slack/node_modules/axios/dist/browser/axios.cjs +56 -8
  26. package/dist/extensions/slack/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  27. package/dist/extensions/slack/node_modules/axios/dist/esm/axios.js +56 -8
  28. package/dist/extensions/slack/node_modules/axios/dist/esm/axios.js.map +1 -1
  29. package/dist/extensions/slack/node_modules/axios/dist/esm/axios.min.js +2 -2
  30. package/dist/extensions/slack/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  31. package/dist/extensions/slack/node_modules/axios/dist/node/axios.cjs +123 -9
  32. package/dist/extensions/slack/node_modules/axios/dist/node/axios.cjs.map +1 -1
  33. package/dist/extensions/slack/node_modules/axios/lib/adapters/http.js +4 -2
  34. package/dist/extensions/slack/node_modules/axios/lib/core/Axios.js +19 -3
  35. package/dist/extensions/slack/node_modules/axios/lib/core/AxiosHeaders.js +35 -3
  36. package/dist/extensions/slack/node_modules/axios/lib/env/data.js +1 -1
  37. package/dist/extensions/slack/node_modules/axios/lib/helpers/shouldBypassProxy.js +106 -0
  38. package/dist/extensions/slack/node_modules/axios/package.json +4 -1
  39. package/dist/extensions/slack/node_modules/qs/CHANGELOG.md +6 -0
  40. package/dist/extensions/slack/node_modules/qs/dist/qs.js +16 -16
  41. package/dist/extensions/slack/node_modules/qs/lib/parse.js +2 -2
  42. package/dist/extensions/slack/node_modules/qs/package.json +3 -3
  43. package/dist/extensions/slack/node_modules/qs/test/parse.js +86 -0
  44. package/dist/extensions/slack/node_modules/qs/test/stringify.js +9 -0
  45. package/dist/extensions/slack/node_modules/qs/test/utils.js +31 -3
  46. package/dist/extensions/slack/node_modules/side-channel-list/CHANGELOG.md +25 -4
  47. package/dist/extensions/slack/node_modules/side-channel-list/index.js +1 -3
  48. package/dist/extensions/slack/node_modules/side-channel-list/package.json +8 -8
  49. package/dist/extensions/slack/node_modules/side-channel-list/test/index.js +50 -0
  50. package/dist/{gateway-manager-D_f5cQVk.js → gateway-manager-D66ezIC1.js} +2 -6
  51. package/package.json +1 -1
package/dist/.buildstamp CHANGED
@@ -1 +1 @@
1
- {"builtAt":1775637451867,"head":"843e6a14abe65fe2a4a053fdc32d029755e1bb67"}
1
+ {"builtAt":1775727523888,"head":"eb993539ed3bdef773db4ffc7adb3e6399a0f57d"}
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.3.27",
3
- "commit": "843e6a14abe65fe2a4a053fdc32d029755e1bb67",
4
- "builtAt": "2026-04-08T08:40:38.891Z"
2
+ "version": "2026.3.28",
3
+ "commit": "eb993539ed3bdef773db4ffc7adb3e6399a0f57d",
4
+ "builtAt": "2026-04-09T09:39:10.419Z"
5
5
  }
@@ -1,5 +1,5 @@
1
1
  import { a as openclawHome } from "../../env-CcGPS0ln.js";
2
- import { i as setDashboardPort, l as loadJsonSync } from "../../gateway-manager-D_f5cQVk.js";
2
+ import { c as loadJsonSync, i as setDashboardPort } from "../../gateway-manager-D66ezIC1.js";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { a as openclawHome, n as envApiKey, t as defaultCoreUrl } from "../../env-CcGPS0ln.js";
2
- import { a as setGatewayActivityCallback, c as loadJsonSafe, d as loadTextSync, i as setDashboardPort, l as loadJsonSync, n as enableGateway, o as startGateway, r as getGatewayStatus, s as stopGateway, t as disableGateway, u as loadTextSafe } from "../../gateway-manager-D_f5cQVk.js";
2
+ import { a as startGateway, c as loadJsonSync, i as setDashboardPort, l as loadTextSafe, n as enableGateway, o as stopGateway, r as getGatewayStatus, s as loadJsonSafe, t as disableGateway, u as loadTextSync } from "../../gateway-manager-D66ezIC1.js";
3
3
  import fs, { existsSync, mkdirSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
4
4
  import path from "node:path";
5
5
  import os, { networkInterfaces } from "node:os";
@@ -379,6 +379,33 @@ function sanitizeContent(content) {
379
379
  };
380
380
  }
381
381
  //#endregion
382
+ //#region extensions/cclawd-guard/agent/machine-id.ts
383
+ let cachedMachineInfo = null;
384
+ /**
385
+ * Build a stable per-device ID from hostname + first non-internal MAC.
386
+ * Hashing avoids sending raw MAC addresses.
387
+ */
388
+ function getMachineInfo() {
389
+ if (cachedMachineInfo) return cachedMachineInfo;
390
+ const machineName = os.hostname();
391
+ const interfaces = networkInterfaces();
392
+ let mac = "";
393
+ for (const iface of Object.values(interfaces)) {
394
+ if (!iface) continue;
395
+ for (const info of iface) if (!info.internal && info.mac && info.mac !== "00:00:00:00:00:00") {
396
+ mac = info.mac;
397
+ break;
398
+ }
399
+ if (mac) break;
400
+ }
401
+ const input = `${machineName}:${mac || "unknown"}`;
402
+ cachedMachineInfo = {
403
+ machineId: createHash("sha256").update(input).digest("hex").slice(0, 16),
404
+ machineName
405
+ };
406
+ return cachedMachineInfo;
407
+ }
408
+ //#endregion
382
409
  //#region extensions/cclawd-guard/agent/behavior-detector.ts
383
410
  /**
384
411
  * Behavioral anomaly detector — runs at before_tool_call.
@@ -389,28 +416,9 @@ function sanitizeContent(content) {
389
416
  * 3. Core does all classification, signal computation, and risk decisions
390
417
  * 4. Fail-open: if Core is unavailable, allow execution
391
418
  */
392
- const FILE_READ_TOOLS = new Set([
393
- "Read",
394
- "read_file",
395
- "read",
396
- "cat",
397
- "head",
398
- "tail",
399
- "view",
400
- "get_file_contents",
401
- "open_file"
402
- ]);
403
- const WEB_FETCH_TOOLS = new Set([
404
- "WebFetch",
405
- "web_fetch",
406
- "fetch",
407
- "http_request",
408
- "get_url",
409
- "browser_navigate",
410
- "navigate"
411
- ]);
412
419
  /** Module-level secret detection callback (set by BehaviorDetector) */
413
420
  let secretDetectionCallback = null;
421
+ const machineInfo$1 = getMachineInfo();
414
422
  function sanitizeParams(params) {
415
423
  const result = {};
416
424
  const allRedactions = {};
@@ -495,7 +503,9 @@ var BehaviorDetector = class {
495
503
  },
496
504
  meta: {
497
505
  pluginVersion: this.config.pluginVersion,
498
- clientTimestamp: (/* @__PURE__ */ new Date()).toISOString()
506
+ clientTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
507
+ machineId: machineInfo$1.machineId,
508
+ machineName: machineInfo$1.machineName
499
509
  }
500
510
  };
501
511
  const verdict = await this.callAssessApi(req);
@@ -537,6 +547,7 @@ var BehaviorDetector = class {
537
547
  */
538
548
  async scanContent(sessionKey, toolName, content) {
539
549
  if (!this.coreCredentials) return null;
550
+ const state = this.getOrCreate(sessionKey);
540
551
  const maxSize = 100 * 1024;
541
552
  const truncatedContent = content.length > maxSize ? content.slice(0, maxSize) : content;
542
553
  const controller = new AbortController();
@@ -551,7 +562,15 @@ var BehaviorDetector = class {
551
562
  body: JSON.stringify({
552
563
  content: truncatedContent,
553
564
  toolName,
554
- sessionKey
565
+ sessionKey,
566
+ runId: state.runId,
567
+ userIntent: state.userIntent,
568
+ meta: {
569
+ machineId: machineInfo$1.machineId,
570
+ machineName: machineInfo$1.machineName,
571
+ pluginVersion: this.config.pluginVersion,
572
+ clientTimestamp: (/* @__PURE__ */ new Date()).toISOString()
573
+ }
555
574
  }),
556
575
  signal: controller.signal
557
576
  });
@@ -663,7 +682,8 @@ const BATCH_FLUSH_INTERVAL_MS = 100;
663
682
  /** Maximum events per batch */
664
683
  const MAX_BATCH_SIZE = 50;
665
684
  /** Timeout for Core API calls */
666
- const API_TIMEOUT_MS$2 = 3e3;
685
+ const API_TIMEOUT_MS$1 = 3e3;
686
+ const machineInfo = getMachineInfo();
667
687
  var EventReporter = class {
668
688
  constructor(config, log) {
669
689
  this.credentials = null;
@@ -675,7 +695,7 @@ var EventReporter = class {
675
695
  this.config = {
676
696
  coreUrl: config.coreUrl,
677
697
  pluginVersion: config.pluginVersion,
678
- timeoutMs: config.timeoutMs ?? API_TIMEOUT_MS$2,
698
+ timeoutMs: config.timeoutMs ?? API_TIMEOUT_MS$1,
679
699
  enableBatching: config.enableBatching ?? true
680
700
  };
681
701
  this.log = log;
@@ -726,7 +746,9 @@ var EventReporter = class {
726
746
  events: [event],
727
747
  meta: {
728
748
  pluginVersion: this.config.pluginVersion,
729
- clientTimestamp: (/* @__PURE__ */ new Date()).toISOString()
749
+ clientTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
750
+ machineId: machineInfo.machineId,
751
+ machineName: machineInfo.machineName
730
752
  }
731
753
  };
732
754
  const controller = new AbortController();
@@ -830,7 +852,9 @@ var EventReporter = class {
830
852
  events,
831
853
  meta: {
832
854
  pluginVersion: this.config.pluginVersion,
833
- clientTimestamp: (/* @__PURE__ */ new Date()).toISOString()
855
+ clientTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
856
+ machineId: machineInfo.machineId,
857
+ machineName: machineInfo.machineName
834
858
  }
835
859
  };
836
860
  const controller = new AbortController();
@@ -897,285 +921,6 @@ var EventReporter = class {
897
921
  }
898
922
  };
899
923
  //#endregion
900
- //#region extensions/cclawd-guard/agent/business-reporter.ts
901
- /**
902
- * BusinessReporter - Reports telemetry data to Core's Business Dashboard.
903
- *
904
- * Only active when the agent's account is on the "business" plan.
905
- * Accumulates events and agentic hours locally, then flushes to Core
906
- * every 60 seconds via POST /api/v1/business/telemetry.
907
- */
908
- function debugLog$1(msg) {
909
- try {
910
- const logPath = path.join(openclawHome, "logs", "cclawd-guard-debug.log");
911
- fs.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [BusinessReporter] ${msg}\n`);
912
- } catch {}
913
- }
914
- /** Flush interval in ms (60 seconds) */
915
- const FLUSH_INTERVAL_MS = 6e4;
916
- /** Maximum events to buffer before forced flush */
917
- const MAX_BUFFERED_EVENTS = 500;
918
- /** Timeout for Core API calls */
919
- const API_TIMEOUT_MS$1 = 5e3;
920
- var BusinessReporter = class {
921
- constructor(config, log) {
922
- this.enabled = false;
923
- this.credentials = null;
924
- this.ownerName = "";
925
- this.agentName = "";
926
- this.provider = "";
927
- this.model = "";
928
- this.pendingEvents = [];
929
- this.hoursAccum = this.emptyAccum();
930
- this.scanAccum = [];
931
- this.gatewayAccum = this.emptyGatewayAccum();
932
- this.secretAccum = this.emptySecretAccum();
933
- this.flushInterval = null;
934
- this.flushing = false;
935
- this.config = config;
936
- this.log = log;
937
- this.machineName = os.hostname();
938
- this.machineId = generateMachineId();
939
- }
940
- /**
941
- * Initialize the reporter. Only enables if the account plan is "business".
942
- * Call this after fetching the account info from Core.
943
- */
944
- initialize(plan) {
945
- if (plan !== "business") {
946
- this.log.debug?.(`BusinessReporter: plan is "${plan}", not enabling`);
947
- return;
948
- }
949
- this.enabled = true;
950
- this.startPeriodicFlush();
951
- this.log.info(`BusinessReporter: enabled for business plan (machine: ${this.machineName})`);
952
- }
953
- /** Set Core credentials */
954
- setCredentials(credentials) {
955
- this.credentials = credentials;
956
- }
957
- /** Update agent profile info (called when profile changes) */
958
- setProfile(profile) {
959
- if (profile.ownerName !== void 0) this.ownerName = profile.ownerName;
960
- if (profile.agentName !== void 0) this.agentName = profile.agentName;
961
- if (profile.provider !== void 0) this.provider = profile.provider;
962
- if (profile.model !== void 0) this.model = profile.model;
963
- }
964
- /** Whether the reporter is active */
965
- isEnabled() {
966
- return this.enabled;
967
- }
968
- /** Stop the reporter and flush remaining data */
969
- async stop() {
970
- if (this.flushInterval) {
971
- clearInterval(this.flushInterval);
972
- this.flushInterval = null;
973
- }
974
- if (this.enabled) await this.flush();
975
- this.enabled = false;
976
- }
977
- /** Record a tool call */
978
- recordToolCall(toolName, category, durationMs, blocked) {
979
- if (!this.enabled) return;
980
- this.pendingEvents.push({
981
- type: blocked ? "block" : "tool_call",
982
- toolName,
983
- category,
984
- durationMs,
985
- blocked
986
- });
987
- this.hoursAccum.toolCallDurationMs += durationMs;
988
- this.hoursAccum.toolCallCount += 1;
989
- this.hoursAccum.totalDurationMs += durationMs;
990
- if (blocked) this.hoursAccum.blockCount += 1;
991
- this.maybeFlush();
992
- }
993
- /** Record an LLM call */
994
- recordLlmCall(durationMs, model) {
995
- if (!this.enabled) return;
996
- if (model) this.model = model;
997
- this.hoursAccum.llmDurationMs += durationMs;
998
- this.hoursAccum.llmCallCount += 1;
999
- this.hoursAccum.totalDurationMs += durationMs;
1000
- }
1001
- /** Record a detection event */
1002
- recordDetection(riskLevel, blocked, summary) {
1003
- if (!this.enabled) return;
1004
- this.pendingEvents.push({
1005
- type: "detection",
1006
- riskLevel,
1007
- blocked,
1008
- summary
1009
- });
1010
- if (riskLevel !== "no_risk" && riskLevel !== "low") this.hoursAccum.riskEventCount += 1;
1011
- if (blocked) this.hoursAccum.blockCount += 1;
1012
- this.maybeFlush();
1013
- }
1014
- /** Record a session start/end */
1015
- recordSession(type, durationMs) {
1016
- if (!this.enabled) return;
1017
- this.pendingEvents.push({
1018
- type: type === "start" ? "session_start" : "session_end",
1019
- durationMs
1020
- });
1021
- if (type === "start") this.hoursAccum.sessionCount += 1;
1022
- if (durationMs) this.hoursAccum.totalDurationMs += durationMs;
1023
- }
1024
- /** Record a scan result (static or dynamic) */
1025
- recordScanResult(scanType, categories, risky) {
1026
- if (!this.enabled) return;
1027
- let accum = this.scanAccum.find((s) => s.scanType === scanType);
1028
- if (!accum) {
1029
- accum = {
1030
- scanType,
1031
- totalScans: 0,
1032
- riskyScans: 0,
1033
- categoryCounts: {}
1034
- };
1035
- this.scanAccum.push(accum);
1036
- }
1037
- accum.totalScans += 1;
1038
- if (risky) accum.riskyScans += 1;
1039
- for (const cat of categories) accum.categoryCounts[cat] = (accum.categoryCounts[cat] ?? 0) + 1;
1040
- }
1041
- /** Record gateway sanitization activity */
1042
- recordGatewayActivity(redactionCount, typeCounts) {
1043
- if (!this.enabled) return;
1044
- this.gatewayAccum.totalRequests += 1;
1045
- this.gatewayAccum.totalRedactions += redactionCount;
1046
- for (const [k, v] of Object.entries(typeCounts)) this.gatewayAccum.typeCounts[k] = (this.gatewayAccum.typeCounts[k] ?? 0) + v;
1047
- }
1048
- /** Record secret detection */
1049
- recordSecretDetection(typeCounts) {
1050
- if (!this.enabled) return;
1051
- const total = Object.values(typeCounts).reduce((a, b) => a + b, 0);
1052
- this.secretAccum.totalDetections += total;
1053
- for (const [k, v] of Object.entries(typeCounts)) this.secretAccum.typeCounts[k] = (this.secretAccum.typeCounts[k] ?? 0) + v;
1054
- }
1055
- startPeriodicFlush() {
1056
- if (this.flushInterval) return;
1057
- this.flushInterval = setInterval(() => {
1058
- this.flush().catch((err) => {
1059
- this.log.debug?.(`BusinessReporter: flush error: ${err}`);
1060
- });
1061
- }, FLUSH_INTERVAL_MS);
1062
- this.flushInterval.unref();
1063
- }
1064
- maybeFlush() {
1065
- if (this.pendingEvents.length >= MAX_BUFFERED_EVENTS) this.flush().catch((err) => {
1066
- this.log.debug?.(`BusinessReporter: forced flush error: ${err}`);
1067
- });
1068
- }
1069
- async flush() {
1070
- if (this.flushing || !this.enabled || !this.credentials) return;
1071
- const hasEvents = this.pendingEvents.length > 0;
1072
- const hasHours = this.hoursAccum.totalDurationMs > 0 || this.hoursAccum.toolCallCount > 0 || this.hoursAccum.llmCallCount > 0 || this.hoursAccum.sessionCount > 0;
1073
- const hasScans = this.scanAccum.length > 0;
1074
- const hasGateway = this.gatewayAccum.totalRequests > 0;
1075
- const hasSecrets = this.secretAccum.totalDetections > 0;
1076
- if (!hasEvents && !hasHours && !hasScans && !hasGateway && !hasSecrets) return;
1077
- this.flushing = true;
1078
- const events = this.pendingEvents.splice(0);
1079
- const hours = { ...this.hoursAccum };
1080
- this.hoursAccum = this.emptyAccum();
1081
- const scans = this.scanAccum.splice(0);
1082
- const gateway = { ...this.gatewayAccum };
1083
- this.gatewayAccum = this.emptyGatewayAccum();
1084
- const secrets = { ...this.secretAccum };
1085
- this.secretAccum = this.emptySecretAccum();
1086
- const controller = new AbortController();
1087
- const timer = setTimeout(() => controller.abort(), API_TIMEOUT_MS$1);
1088
- try {
1089
- const body = {
1090
- agentId: this.credentials.agentId,
1091
- ownerName: this.ownerName || void 0,
1092
- machineName: this.machineName,
1093
- machineId: this.machineId,
1094
- agentName: this.agentName || void 0,
1095
- provider: this.provider || void 0,
1096
- model: this.model || void 0,
1097
- events: events.length > 0 ? events : void 0,
1098
- agenticHours: hasHours ? hours : void 0,
1099
- heartbeat: true,
1100
- scanSummary: scans.length > 0 ? scans : void 0,
1101
- gatewaySummary: hasGateway ? gateway : void 0,
1102
- secretSummary: hasSecrets ? secrets : void 0
1103
- };
1104
- debugLog$1(`flush: POSTing to ${this.config.coreUrl}/api/v1/business/telemetry events=${events.length} hours=${JSON.stringify(hours)}`);
1105
- const response = await fetch(`${this.config.coreUrl}/api/v1/business/telemetry`, {
1106
- method: "POST",
1107
- headers: {
1108
- "Content-Type": "application/json",
1109
- Authorization: `Bearer ${this.credentials.apiKey}`
1110
- },
1111
- body: JSON.stringify(body),
1112
- signal: controller.signal
1113
- });
1114
- if (!response.ok) {
1115
- debugLog$1(`flush: POST failed with ${response.status}`);
1116
- this.log.debug?.(`BusinessReporter: telemetry request failed with ${response.status}`);
1117
- this.pendingEvents.unshift(...events);
1118
- if (this.pendingEvents.length > MAX_BUFFERED_EVENTS) this.pendingEvents.length = MAX_BUFFERED_EVENTS;
1119
- } else {
1120
- debugLog$1(`flush: POST success`);
1121
- this.log.debug?.(`BusinessReporter: flushed ${events.length} events`);
1122
- }
1123
- } catch (err) {
1124
- debugLog$1(`flush: POST error: ${err}`);
1125
- if (err.name !== "AbortError") this.log.debug?.(`BusinessReporter: telemetry error: ${err}`);
1126
- this.pendingEvents.unshift(...events);
1127
- if (this.pendingEvents.length > MAX_BUFFERED_EVENTS) this.pendingEvents.length = MAX_BUFFERED_EVENTS;
1128
- } finally {
1129
- clearTimeout(timer);
1130
- this.flushing = false;
1131
- }
1132
- }
1133
- emptyAccum() {
1134
- return {
1135
- toolCallDurationMs: 0,
1136
- llmDurationMs: 0,
1137
- totalDurationMs: 0,
1138
- toolCallCount: 0,
1139
- llmCallCount: 0,
1140
- sessionCount: 0,
1141
- blockCount: 0,
1142
- riskEventCount: 0
1143
- };
1144
- }
1145
- emptyGatewayAccum() {
1146
- return {
1147
- totalRequests: 0,
1148
- totalRedactions: 0,
1149
- typeCounts: {}
1150
- };
1151
- }
1152
- emptySecretAccum() {
1153
- return {
1154
- totalDetections: 0,
1155
- typeCounts: {}
1156
- };
1157
- }
1158
- };
1159
- /**
1160
- * Generate a stable machine ID from hostname + first MAC address.
1161
- * This identifies a specific machine across restarts.
1162
- */
1163
- function generateMachineId() {
1164
- const hostname = os.hostname();
1165
- const interfaces = networkInterfaces();
1166
- let mac = "";
1167
- for (const iface of Object.values(interfaces)) {
1168
- if (!iface) continue;
1169
- for (const info of iface) if (!info.internal && info.mac && info.mac !== "00:00:00:00:00:00") {
1170
- mac = info.mac;
1171
- break;
1172
- }
1173
- if (mac) break;
1174
- }
1175
- const input = `${hostname}:${mac || "unknown"}`;
1176
- return createHash("sha256").update(input).digest("hex").slice(0, 16);
1177
- }
1178
- //#endregion
1179
924
  //#region extensions/cclawd-guard/agent/config-sync.ts
1180
925
  /** Poll interval in ms (5 minutes) */
1181
926
  const POLL_INTERVAL_MS = 5 * 6e4;
@@ -1638,26 +1383,6 @@ function debugLog(msg) {
1638
1383
  fs.appendFileSync(DEBUG_LOG_PATH, `[${ts}] ${msg}\n`);
1639
1384
  } catch {}
1640
1385
  }
1641
- /** Infer tool category from tool name for business reporting */
1642
- function inferToolCategory(toolName) {
1643
- const name = toolName.toLowerCase();
1644
- if (FILE_READ_TOOLS.has(toolName) || FILE_READ_TOOLS.has(name)) return "file_read";
1645
- if (WEB_FETCH_TOOLS.has(toolName) || WEB_FETCH_TOOLS.has(name)) return "web_fetch";
1646
- if ([
1647
- "bash",
1648
- "shell",
1649
- "run_command",
1650
- "execute"
1651
- ].some((t) => name.includes(t))) return "shell";
1652
- if ([
1653
- "write",
1654
- "edit",
1655
- "create_file",
1656
- "delete"
1657
- ].some((t) => name.includes(t))) return "file_write";
1658
- if (name.includes("agent") || name.includes("subagent")) return "agent";
1659
- return "other";
1660
- }
1661
1386
  /**
1662
1387
  * Replace all injection matches in `text` with `__REDACTED_BY_CCLAWD_GUARD_DUE_TO_{riskType}__`.
1663
1388
  */
@@ -1733,7 +1458,6 @@ function createLogger(baseLogger) {
1733
1458
  let globalCoreCredentials = null;
1734
1459
  let globalBehaviorDetector = null;
1735
1460
  let globalEventReporter = null;
1736
- let globalBusinessReporter = null;
1737
1461
  let globalConfigSync = null;
1738
1462
  let globalDashboardClient = null;
1739
1463
  let globalFileWatcher = null;
@@ -1969,30 +1693,6 @@ const openClawGuardPlugin = {
1969
1693
  log.debug?.(`Account plan is "${plan}", business features not enabled`);
1970
1694
  return;
1971
1695
  }
1972
- if (!globalBusinessReporter) {
1973
- globalBusinessReporter = new BusinessReporter({
1974
- coreUrl,
1975
- pluginVersion: PLUGIN_VERSION
1976
- }, log);
1977
- globalBusinessReporter.setCredentials(globalCoreCredentials);
1978
- const profile = readAgentProfile();
1979
- globalBusinessReporter.setProfile({
1980
- ownerName: profile.ownerName,
1981
- agentName: config.agentName,
1982
- provider: profile.provider,
1983
- model: profile.model
1984
- });
1985
- globalBusinessReporter.initialize(plan);
1986
- debugLog(`BusinessReporter initialized, enabled=${globalBusinessReporter.isEnabled()}`);
1987
- if (globalBusinessReporter.isEnabled()) {
1988
- setGatewayActivityCallback((redactionCount, typeCounts) => {
1989
- globalBusinessReporter?.recordGatewayActivity(redactionCount, typeCounts);
1990
- });
1991
- globalBehaviorDetector?.setOnSecretDetected((typeCounts) => {
1992
- globalBusinessReporter?.recordSecretDetection(typeCounts);
1993
- });
1994
- }
1995
- }
1996
1696
  if (!globalConfigSync) {
1997
1697
  globalConfigSync = new ConfigSync({
1998
1698
  coreUrl,
@@ -2057,7 +1757,6 @@ const openClawGuardPlugin = {
2057
1757
  sessionId: event.sessionId ?? sessionKey,
2058
1758
  durationMs: event.durationMs
2059
1759
  });
2060
- globalBusinessReporter?.recordSession("end", event.durationMs);
2061
1760
  globalBehaviorDetector?.clearSession(sessionKey);
2062
1761
  globalEventReporter?.clearSession(sessionKey);
2063
1762
  });
@@ -2091,7 +1790,6 @@ const openClawGuardPlugin = {
2091
1790
  log.debug?.(`Dashboard: report failed (before ${event.toolName}) — ${err}`);
2092
1791
  });
2093
1792
  if (blocked) {
2094
- globalBusinessReporter?.recordToolCall(event.toolName, inferToolCategory(event.toolName), 0, true);
2095
1793
  globalDashboardClient?.recordToolCallDuration(0, true);
2096
1794
  return {
2097
1795
  block: true,
@@ -2150,8 +1848,6 @@ const openClawGuardPlugin = {
2150
1848
  const scanResult = await globalBehaviorDetector.scanContent(ctx.sessionKey ?? "", event.toolName, resultText);
2151
1849
  if (scanResult?.detected) {
2152
1850
  log.warn(`Core: injection detected in "${event.toolName}" result: ${scanResult.summary}`);
2153
- globalBusinessReporter?.recordDetection(scanResult.detected ? "high" : "no_risk", false, scanResult.summary);
2154
- globalBusinessReporter?.recordScanResult("dynamic", scanResult.categories ?? [], true);
2155
1851
  globalDashboardClient?.recordRiskEvent();
2156
1852
  }
2157
1853
  if (scanResult && globalDashboardClient) {
@@ -2194,8 +1890,7 @@ const openClawGuardPlugin = {
2194
1890
  }).catch((err) => {
2195
1891
  log.debug?.(`Dashboard: report failed (after ${event.toolName}) — ${err}`);
2196
1892
  });
2197
- debugLog(`after_tool_call: tool=${event.toolName} durationMs=${event.durationMs} dashboardClient=${!!globalDashboardClient} businessReporter=${!!globalBusinessReporter} businessEnabled=${globalBusinessReporter?.isEnabled()}`);
2198
- globalBusinessReporter?.recordToolCall(event.toolName, inferToolCategory(event.toolName), event.durationMs ?? 0, false);
1893
+ debugLog(`after_tool_call: tool=${event.toolName} durationMs=${event.durationMs} dashboardClient=${!!globalDashboardClient}`);
2199
1894
  globalDashboardClient?.recordToolCallDuration(event.durationMs ?? 0);
2200
1895
  });
2201
1896
  const apiAny = api;
@@ -2220,8 +1915,7 @@ const openClawGuardPlugin = {
2220
1915
  sessionId,
2221
1916
  isNew: event?.isNew ?? true
2222
1917
  });
2223
- debugLog(`session_start: sessionKey=${sessionKey} dashboardClient=${!!globalDashboardClient} businessReporter=${!!globalBusinessReporter}`);
2224
- globalBusinessReporter?.recordSession("start");
1918
+ debugLog(`session_start: sessionKey=${sessionKey} dashboardClient=${!!globalDashboardClient}`);
2225
1919
  globalDashboardClient?.recordSessionStart();
2226
1920
  });
2227
1921
  apiAny.on("before_model_resolve", async (event, ctx) => {
@@ -2269,11 +1963,8 @@ const openClawGuardPlugin = {
2269
1963
  latencyMs: llmDuration,
2270
1964
  stopReason: event?.stopReason ?? event?.stop_reason
2271
1965
  });
2272
- debugLog(`llm_output: model=${event?.model} latencyMs=${event?.latencyMs} durationMs=${event?.durationMs} computed=${llmDuration} dashboardClient=${!!globalDashboardClient} businessReporter=${!!globalBusinessReporter}`);
2273
- if (llmDuration > 0) {
2274
- globalBusinessReporter?.recordLlmCall(llmDuration, event?.model);
2275
- globalDashboardClient?.recordLlmDuration(llmDuration);
2276
- }
1966
+ debugLog(`llm_output: model=${event?.model} latencyMs=${event?.latencyMs} durationMs=${event?.durationMs} computed=${llmDuration} dashboardClient=${!!globalDashboardClient}`);
1967
+ if (llmDuration > 0) globalDashboardClient?.recordLlmDuration(llmDuration);
2277
1968
  });
2278
1969
  api.on("message_sending", async (event, ctx) => {
2279
1970
  const sessionKey = ctx.sessionKey ?? "";
@@ -2791,10 +2482,6 @@ const openClawGuardPlugin = {
2791
2482
  log.warn(`Failed to report detection to dashboard: ${err}`);
2792
2483
  });
2793
2484
  } else if (!globalDashboardClient) log.warn("Dashboard client not initialized - scan results not reported to dashboard");
2794
- if (globalBusinessReporter && batchResult.results) for (const fileResult of batchResult.results) {
2795
- const categories = fileResult.findings?.map((f) => f.scanner) ?? [];
2796
- globalBusinessReporter.recordScanResult("static", categories, fileResult.riskLevel !== "safe");
2797
- }
2798
2485
  }
2799
2486
  const result = {
2800
2487
  filesScanned: totalFilesScanned,
@@ -2896,10 +2583,6 @@ const openClawGuardPlugin = {
2896
2583
  const riskCount = result.results.filter((r) => r.riskLevel !== "safe").length;
2897
2584
  if (riskCount > 0) log.info(`Auto-scan found ${riskCount} file(s) with security risks`);
2898
2585
  }
2899
- if (globalBusinessReporter && result.results) for (const fileResult of result.results) {
2900
- const categories = fileResult.findings?.map((f) => f.scanner) ?? [];
2901
- globalBusinessReporter.recordScanResult("static", categories, fileResult.riskLevel !== "safe");
2902
- }
2903
2586
  } catch (err) {
2904
2587
  log.debug?.(`Auto-scan failed: ${err}`);
2905
2588
  }
@@ -3028,10 +2711,6 @@ const openClawGuardPlugin = {
3028
2711
  await globalEventReporter.stop();
3029
2712
  globalEventReporter = null;
3030
2713
  }
3031
- if (globalBusinessReporter) {
3032
- await globalBusinessReporter.stop();
3033
- globalBusinessReporter = null;
3034
- }
3035
2714
  if (globalConfigSync) {
3036
2715
  globalConfigSync.stop();
3037
2716
  globalConfigSync = null;
@@ -90,9 +90,9 @@
90
90
  }
91
91
  },
92
92
  "node_modules/@napi-rs/wasm-runtime": {
93
- "version": "1.1.2",
94
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz",
95
- "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==",
93
+ "version": "1.1.3",
94
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz",
95
+ "integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==",
96
96
  "ideallyInert": true,
97
97
  "license": "MIT",
98
98
  "optional": true,
@@ -497,9 +497,9 @@
497
497
  "license": "MIT"
498
498
  },
499
499
  "node_modules/qs": {
500
- "version": "6.15.0",
501
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
502
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
500
+ "version": "6.15.1",
501
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
502
+ "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
503
503
  "license": "BSD-3-Clause",
504
504
  "dependencies": {
505
505
  "side-channel": "^1.1.0"
@@ -531,13 +531,13 @@
531
531
  }
532
532
  },
533
533
  "node_modules/side-channel-list": {
534
- "version": "1.0.0",
535
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
536
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
534
+ "version": "1.0.1",
535
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
536
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
537
537
  "license": "MIT",
538
538
  "dependencies": {
539
539
  "es-errors": "^1.3.0",
540
- "object-inspect": "^1.13.3"
540
+ "object-inspect": "^1.13.4"
541
541
  },
542
542
  "engines": {
543
543
  "node": ">= 0.4"
@@ -1,3 +1,9 @@
1
+ ## **6.15.1**
2
+ - [Fix] `parse`: `parameterLimit: Infinity` with `throwOnLimitExceeded: true` silently drops all parameters
3
+ - [Deps] update `@ljharb/eslint-config`
4
+ - [Dev Deps] update `@ljharb/eslint-config`, `iconv-lite`
5
+ - [Tests] increase coverage
6
+
1
7
  ## **6.15.0**
2
8
  - [New] `parse`: add `strictMerge` option to wrap object/primitive conflicts in an array (#425, #122)
3
9
  - [Fix] `duplicates` option should not apply to bracket notation keys (#514)