shieldcortex 3.0.3 → 3.0.4

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 (91) hide show
  1. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  2. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  3. package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
  4. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +2 -2
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +3 -3
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +3 -3
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +2 -2
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/page/react-loadable-manifest.json +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_3051539d._.js +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  32. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/static/chunks/313c0d327bbf244a.js +9 -0
  35. package/dashboard/.next/standalone/dashboard/.next/static/chunks/{fa5217550a8ab9a6.js → 49c1cec591af1460.js} +2 -2
  36. package/dashboard/.next/standalone/dashboard/.next/static/chunks/{f69fd1c5e71fbbfd.js → ca21f348cb163905.js} +1 -1
  37. package/dashboard/.next/standalone/dashboard/.next/static/chunks/f4ca424319f58dc7.css +3 -0
  38. package/dist/api/routes/admin.d.ts +12 -0
  39. package/dist/api/routes/admin.js +502 -0
  40. package/dist/api/routes/graph.d.ts +4 -0
  41. package/dist/api/routes/graph.js +333 -0
  42. package/dist/api/routes/incidents.d.ts +2 -0
  43. package/dist/api/routes/incidents.js +32 -0
  44. package/dist/api/routes/memories.d.ts +4 -0
  45. package/dist/api/routes/memories.js +659 -0
  46. package/dist/api/routes/recall.d.ts +4 -0
  47. package/dist/api/routes/recall.js +36 -0
  48. package/dist/api/routes/system.d.ts +9 -0
  49. package/dist/api/routes/system.js +201 -0
  50. package/dist/api/visualization-server.js +31 -1913
  51. package/dist/memory/search.d.ts +37 -0
  52. package/dist/memory/search.js +143 -0
  53. package/dist/memory/store.js +2 -166
  54. package/dist/tools/forget.d.ts +2 -2
  55. package/dist/tools/recall.d.ts +2 -2
  56. package/hooks/openclaw/cortex-memory/handler.ts +5 -141
  57. package/hooks/openclaw/cortex-memory/runtime.mjs +129 -0
  58. package/package.json +8 -4
  59. package/plugins/openclaw/dist/index.js +5 -39
  60. package/scripts/run-jest.mjs +25 -1
  61. package/dashboard/.next/standalone/dashboard/.next/static/chunks/be6970da20a17c0b.js +0 -9
  62. package/dashboard/.next/standalone/dashboard/.next/static/chunks/e63d2228780629dd.css +0 -3
  63. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/_tsc.js +0 -133818
  64. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/_tsserver.js +0 -659
  65. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/_typingsInstaller.js +0 -222
  66. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +0 -2122
  67. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/de/diagnosticMessages.generated.json +0 -2122
  68. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/es/diagnosticMessages.generated.json +0 -2122
  69. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +0 -2122
  70. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/it/diagnosticMessages.generated.json +0 -2122
  71. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +0 -2122
  72. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +0 -2122
  73. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +0 -2122
  74. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +0 -2122
  75. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +0 -2122
  76. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +0 -2122
  77. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/tsc.js +0 -8
  78. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/tsserver.js +0 -8
  79. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/tsserverlibrary.js +0 -21
  80. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/typesMap.json +0 -497
  81. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/typescript.js +0 -200276
  82. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/typingsInstaller.js +0 -8
  83. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/watchGuard.js +0 -53
  84. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +0 -2122
  85. package/dashboard/.next/standalone/dashboard/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +0 -2122
  86. package/dashboard/.next/standalone/dashboard/node_modules/typescript/package.json +0 -120
  87. package/scripts/start-dashboard.sh +0 -41
  88. package/scripts/stop-dashboard.sh +0 -21
  89. /package/dashboard/.next/standalone/dashboard/.next/static/{THy6JENQ0c1sq6jQhvIDp → BEvyMAX62LQMyt5iSb-F9}/_buildManifest.js +0 -0
  90. /package/dashboard/.next/standalone/dashboard/.next/static/{THy6JENQ0c1sq6jQhvIDp → BEvyMAX62LQMyt5iSb-F9}/_clientMiddlewareManifest.json +0 -0
  91. /package/dashboard/.next/standalone/dashboard/.next/static/{THy6JENQ0c1sq6jQhvIDp → BEvyMAX62LQMyt5iSb-F9}/_ssgManifest.js +0 -0
@@ -0,0 +1,129 @@
1
+ import { execFile } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import path from "node:path";
5
+
6
+ export function createOpenClawRuntime({ logPrefix = "[shieldcortex]" } = {}) {
7
+ let shieldConfig = null;
8
+ let resolvedServerCmd = null;
9
+ let lastCallErrorType = null;
10
+
11
+ async function loadShieldConfig() {
12
+ if (shieldConfig) return shieldConfig;
13
+
14
+ try {
15
+ const configPath = path.join(homedir(), ".shieldcortex", "config.json");
16
+ shieldConfig = JSON.parse(await fs.readFile(configPath, "utf-8"));
17
+ } catch {
18
+ shieldConfig = {};
19
+ }
20
+
21
+ return shieldConfig;
22
+ }
23
+
24
+ function isOpenClawAutoMemoryEnabled(config) {
25
+ return config?.openclawAutoMemory === true;
26
+ }
27
+
28
+ function classifyCallError(err) {
29
+ if (err.killed || err.code === "ETIMEDOUT" || err.signal === "SIGTERM") return "timeout";
30
+ if (/ENOENT|not found|command not found/i.test(err.message || "")) return "not-found";
31
+ if (/mcporter/i.test(err.message || "")) return "mcporter";
32
+ return "unknown";
33
+ }
34
+
35
+ async function resolveServerCmd() {
36
+ if (resolvedServerCmd) return resolvedServerCmd;
37
+
38
+ try {
39
+ const config = await loadShieldConfig();
40
+ if (config?.binaryPath) {
41
+ await fs.access(config.binaryPath);
42
+ resolvedServerCmd = config.binaryPath;
43
+ console.log(`${logPrefix} Using configured binary: ${config.binaryPath}`);
44
+ return resolvedServerCmd;
45
+ }
46
+ } catch {}
47
+
48
+ try {
49
+ const { execFileSync } = await import("node:child_process");
50
+ const bin = execFileSync("which", ["shieldcortex"], {
51
+ encoding: "utf-8",
52
+ timeout: 3000,
53
+ }).trim();
54
+ if (bin) {
55
+ resolvedServerCmd = bin;
56
+ console.log(`${logPrefix} Using global install: ${bin}`);
57
+ return resolvedServerCmd;
58
+ }
59
+ } catch {}
60
+
61
+ resolvedServerCmd = "npx -y shieldcortex";
62
+ console.log(`${logPrefix} Falling back to npx -y shieldcortex (slow path)`);
63
+ return resolvedServerCmd;
64
+ }
65
+
66
+ async function callCortex(tool, args = {}, options = { retries: 0, timeout: 15000 }) {
67
+ const serverCmd = await resolveServerCmd();
68
+
69
+ return new Promise((resolve) => {
70
+ const cmdArgs = ["mcporter", "call", "--stdio", serverCmd, tool];
71
+ for (const [key, value] of Object.entries(args)) {
72
+ cmdArgs.push(`${key}:${String(value).replace(/'/g, "''")}`);
73
+ }
74
+
75
+ let attempts = 0;
76
+ const maxAttempts = (options.retries || 0) + 1;
77
+
78
+ function attempt() {
79
+ attempts++;
80
+ execFile("npx", cmdArgs, {
81
+ timeout: options.timeout || 15000,
82
+ maxBuffer: 256 * 1024,
83
+ }, (err, stdout) => {
84
+ if (err) {
85
+ const isTimeout = err.killed || err.code === "ETIMEDOUT" || err.signal === "SIGTERM";
86
+ const errorType = isTimeout ? "TIMEOUT" : "ERROR";
87
+
88
+ if (attempts < maxAttempts) {
89
+ console.warn(`${logPrefix} ${errorType} on ${tool} (attempt ${attempts}/${maxAttempts}), retrying...`);
90
+ setTimeout(attempt, 1000);
91
+ return;
92
+ }
93
+
94
+ const category = classifyCallError(err);
95
+ if (category !== lastCallErrorType) {
96
+ lastCallErrorType = category;
97
+ switch (category) {
98
+ case "timeout":
99
+ console.warn(`${logPrefix} ShieldCortex call timed out (15s). Memory may be under heavy load.`);
100
+ break;
101
+ case "not-found":
102
+ console.warn(`${logPrefix} ShieldCortex binary not found. Run: npm install -g shieldcortex`);
103
+ break;
104
+ case "mcporter":
105
+ console.warn(`${logPrefix} mcporter failed to reach ShieldCortex MCP server. Is it configured?`);
106
+ break;
107
+ default:
108
+ console.warn(`${logPrefix} ShieldCortex call failed: ${err.message}`);
109
+ }
110
+ }
111
+ resolve(null);
112
+ return;
113
+ }
114
+
115
+ resolve(stdout?.trim() || null);
116
+ });
117
+ }
118
+
119
+ attempt();
120
+ });
121
+ }
122
+
123
+ return {
124
+ callCortex,
125
+ isOpenClawAutoMemoryEnabled,
126
+ loadShieldConfig,
127
+ resolveServerCmd,
128
+ };
129
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shieldcortex",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "description": "Persistent brain for AI agents. Knowledge graphs, memory decay, contradiction detection, Iron Dome behaviour protection — plus the only defence pipeline that stops memory poisoning. Works with Claude Code, OpenClaw, LangChain, and any MCP agent.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "scripts": {
40
40
  "postinstall": "node scripts/postinstall.mjs",
41
41
  "build": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.build.json && cp plugins/openclaw/openclaw.plugin.json plugins/openclaw/dist/",
42
- "build:dashboard": "cd dashboard && npm run build && (cp -r .next/static .next/standalone/dashboard/.next/ 2>/dev/null || true) && (cp -r public .next/standalone/dashboard/ 2>/dev/null || true)",
42
+ "build:dashboard": "cd dashboard && npm run build && (cp -r .next/static .next/standalone/dashboard/.next/ 2>/dev/null || true) && (cp -r public .next/standalone/dashboard/ 2>/dev/null || true) && cd .. && node scripts/prune-dashboard-standalone.mjs",
43
43
  "build:all": "npm run build && npm run build:dashboard",
44
44
  "start": "node dist/index.js",
45
45
  "start:api": "node dist/index.js --mode api",
@@ -123,8 +123,12 @@
123
123
  "dist",
124
124
  "hooks/openclaw",
125
125
  "plugins/openclaw/dist",
126
- "scripts/*.mjs",
127
- "scripts/*.sh",
126
+ "scripts/postinstall.mjs",
127
+ "scripts/pre-compact-hook.mjs",
128
+ "scripts/run-jest.mjs",
129
+ "scripts/session-end-hook.mjs",
130
+ "scripts/session-start-hook.mjs",
131
+ "scripts/stop-hook.mjs",
128
132
  "dashboard/.next/standalone"
129
133
  ]
130
134
  }
@@ -4,61 +4,27 @@
4
4
  * Hooks into llm_input/llm_output for real-time defence scanning
5
5
  * and optional memory extraction. All operations are fire-and-forget.
6
6
  */
7
- import { execFile } from "node:child_process";
8
7
  import { createHash } from "node:crypto";
9
8
  import fs from "node:fs/promises";
10
9
  import path from "node:path";
11
10
  import { homedir } from "node:os";
11
+ import { createOpenClawRuntime } from "../../../hooks/openclaw/cortex-memory/runtime.mjs";
12
12
  let _config = null;
13
+ const runtime = createOpenClawRuntime({ logPrefix: "[shieldcortex]" });
13
14
  async function loadConfig() {
14
15
  if (_config)
15
16
  return _config;
16
- try {
17
- _config = JSON.parse(await fs.readFile(path.join(homedir(), ".shieldcortex", "config.json"), "utf-8"));
18
- }
19
- catch {
20
- _config = {};
21
- }
17
+ _config = await runtime.loadShieldConfig();
22
18
  return _config;
23
19
  }
24
20
  function isAutoMemoryEnabled(config) {
25
- return config.openclawAutoMemory === true;
21
+ return runtime.isOpenClawAutoMemoryEnabled(config);
26
22
  }
27
23
  function isAutoMemoryDedupeEnabled(config) {
28
24
  return config.openclawAutoMemoryDedupe !== false;
29
25
  }
30
- // ==================== SERVER CMD ====================
31
- let _serverCmd = null;
32
- async function resolveServerCmd() {
33
- if (_serverCmd)
34
- return _serverCmd;
35
- const config = await loadConfig();
36
- if (config.binaryPath) {
37
- try {
38
- await fs.access(config.binaryPath);
39
- return (_serverCmd = config.binaryPath);
40
- }
41
- catch { }
42
- }
43
- try {
44
- const { execFileSync } = await import("node:child_process");
45
- const bin = execFileSync("which", ["shieldcortex"], { encoding: "utf-8", timeout: 3000 }).trim();
46
- if (bin)
47
- return (_serverCmd = bin);
48
- }
49
- catch { }
50
- return (_serverCmd = "npx -y shieldcortex");
51
- }
52
- // ==================== MCP HELPER ====================
53
26
  function callCortex(tool, args = {}) {
54
- return resolveServerCmd().then(serverCmd => new Promise(resolve => {
55
- const cmdArgs = ["mcporter", "call", "--stdio", serverCmd, tool];
56
- for (const [k, v] of Object.entries(args))
57
- cmdArgs.push(`${k}:${String(v).replace(/'/g, "''")}`);
58
- execFile("npx", cmdArgs, { timeout: 15000, maxBuffer: 256 * 1024 }, (err, stdout) => {
59
- resolve(err ? null : stdout?.trim() || null);
60
- });
61
- }));
27
+ return runtime.callCortex(tool, args);
62
28
  }
63
29
  // ==================== DEFENCE PIPELINE ====================
64
30
  let _pipeline = null;
@@ -4,27 +4,51 @@ import { spawn } from 'child_process';
4
4
  import path from 'path';
5
5
 
6
6
  const jestBin = path.join(process.cwd(), 'node_modules', 'jest', 'bin', 'jest.js');
7
+ const localStorageFile = path.join(process.cwd(), '.jest-localstorage');
7
8
 
8
9
  function sanitizeNodeOptions(value) {
9
10
  if (!value) return undefined;
10
11
 
11
12
  const cleaned = value
12
13
  .replace(/(?:^|\s)--localstorage-file(?:=\S+)?(?=\s|$)/g, ' ')
14
+ .replace(/(?:^|\s)--disable-warning(?:=\S+)?(?=\s|$)/g, ' ')
13
15
  .replace(/\s+/g, ' ')
14
16
  .trim();
15
17
 
16
18
  return cleaned || undefined;
17
19
  }
18
20
 
21
+ function appendNodeOption(existing, option) {
22
+ return existing ? `${existing} ${option}` : option;
23
+ }
24
+
19
25
  const env = { ...process.env, SHIELDCORTEX_SKIP_EMBEDDINGS: '1' };
20
26
  delete env.ELECTRON_RUN_AS_NODE;
21
27
 
22
- const sanitizedNodeOptions = sanitizeNodeOptions(env.NODE_OPTIONS);
28
+ const combinedNodeOptions = [env.NODE_OPTIONS, env.npm_config_node_options]
29
+ .filter(Boolean)
30
+ .join(' ')
31
+ .trim();
32
+
33
+ let sanitizedNodeOptions = sanitizeNodeOptions(combinedNodeOptions);
34
+
35
+ if (process.allowedNodeEnvironmentFlags.has('--localstorage-file')) {
36
+ sanitizedNodeOptions = appendNodeOption(
37
+ sanitizedNodeOptions,
38
+ `--localstorage-file=${JSON.stringify(localStorageFile)}`,
39
+ );
40
+ }
41
+
42
+ if (process.allowedNodeEnvironmentFlags.has('--disable-warning')) {
43
+ sanitizedNodeOptions = appendNodeOption(sanitizedNodeOptions, '--disable-warning=ExperimentalWarning');
44
+ }
45
+
23
46
  if (sanitizedNodeOptions) {
24
47
  env.NODE_OPTIONS = sanitizedNodeOptions;
25
48
  } else {
26
49
  delete env.NODE_OPTIONS;
27
50
  }
51
+ delete env.npm_config_node_options;
28
52
 
29
53
  const child = spawn(
30
54
  process.execPath,