shieldcortex 3.2.1 → 3.2.3
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/README.md +59 -1
- package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
- package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +47 -6
- package/dist/service/install.d.ts +9 -4
- package/dist/service/install.js +74 -22
- package/dist/service/templates.d.ts +3 -1
- package/dist/service/templates.js +15 -5
- package/package.json +1 -1
- /package/dashboard/.next/standalone/dashboard/.next/static/{Oi8lTcFeUV-igSMtPHAG- → S6fGQSuQ43LV2sjEMNTwk}/_buildManifest.js +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{Oi8lTcFeUV-igSMtPHAG- → S6fGQSuQ43LV2sjEMNTwk}/_clientMiddlewareManifest.json +0 -0
- /package/dashboard/.next/standalone/dashboard/.next/static/{Oi8lTcFeUV-igSMtPHAG- → S6fGQSuQ43LV2sjEMNTwk}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* shieldcortex --mode mcp # Start MCP server
|
|
11
11
|
* shieldcortex --mode api # Start visualization API server
|
|
12
12
|
* shieldcortex --mode both # Start both servers
|
|
13
|
+
* shieldcortex --mode worker # Start headless background worker
|
|
13
14
|
* shieldcortex --dashboard # Start API + Dashboard (admin panel)
|
|
14
15
|
* shieldcortex --db /path/to.db # Custom database path
|
|
15
16
|
* shieldcortex scan "text" # Quick content scan (no MCP/ML)
|
|
@@ -24,9 +25,10 @@
|
|
|
24
25
|
* shieldcortex hook pre-compact # Run pre-compact hook (for settings.json)
|
|
25
26
|
* shieldcortex hook session-start # Run session-start hook (for settings.json)
|
|
26
27
|
* shieldcortex hook session-end # Run session-end hook (for settings.json)
|
|
27
|
-
* shieldcortex service install #
|
|
28
|
-
* shieldcortex service
|
|
29
|
-
* shieldcortex service
|
|
28
|
+
* shieldcortex service install # Install persistent ShieldCortex service
|
|
29
|
+
* shieldcortex service install --headless # Recommended for always-on servers
|
|
30
|
+
* shieldcortex service repair # Rebuild persistent service with current install path
|
|
31
|
+
* shieldcortex service uninstall # Remove persistent service
|
|
30
32
|
* shieldcortex service status # Check service status
|
|
31
33
|
* shieldcortex openclaw install # Install OpenClaw hook
|
|
32
34
|
* shieldcortex openclaw uninstall # Remove OpenClaw hook
|
|
@@ -107,12 +109,18 @@ function parseArgs() {
|
|
|
107
109
|
}
|
|
108
110
|
else if (args[i] === '--mode' && args[i + 1]) {
|
|
109
111
|
const mode = args[i + 1].toLowerCase();
|
|
110
|
-
if (mode === 'mcp' || mode === 'api' || mode === 'both' || mode === 'dashboard') {
|
|
112
|
+
if (mode === 'mcp' || mode === 'api' || mode === 'both' || mode === 'dashboard' || mode === 'worker') {
|
|
111
113
|
result.mode = mode;
|
|
112
114
|
}
|
|
113
115
|
i++;
|
|
114
116
|
}
|
|
115
117
|
}
|
|
118
|
+
if (args[0] === 'dashboard')
|
|
119
|
+
result.mode = 'dashboard';
|
|
120
|
+
if (args[0] === 'api')
|
|
121
|
+
result.mode = 'api';
|
|
122
|
+
if (args[0] === 'worker')
|
|
123
|
+
result.mode = 'worker';
|
|
116
124
|
return result;
|
|
117
125
|
}
|
|
118
126
|
/**
|
|
@@ -298,6 +306,33 @@ function startDashboard() {
|
|
|
298
306
|
});
|
|
299
307
|
return dashboard;
|
|
300
308
|
}
|
|
309
|
+
async function startWorkerMode(dbPath) {
|
|
310
|
+
const { initDatabase } = await import('./database/init.js');
|
|
311
|
+
const { startDefaultWorker } = await import('./worker/brain-worker.js');
|
|
312
|
+
initDatabase(dbPath);
|
|
313
|
+
startDefaultWorker();
|
|
314
|
+
console.log(`
|
|
315
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
316
|
+
║ ShieldCortex Worker Service ║
|
|
317
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
318
|
+
║ Running headless background worker ║
|
|
319
|
+
║ Heartbeats keep this device online in ShieldCortex Cloud ║
|
|
320
|
+
║ Sync retries and graph maintenance remain active ║
|
|
321
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
322
|
+
`);
|
|
323
|
+
const keepAlive = setInterval(() => {
|
|
324
|
+
// Intentionally empty. BrainWorker timers are unref()'d, so the service
|
|
325
|
+
// needs one referenced timer to remain alive as a daemon.
|
|
326
|
+
}, 60 * 60 * 1000);
|
|
327
|
+
const shutdown = (signal) => {
|
|
328
|
+
console.log(`\nReceived ${signal}, stopping ShieldCortex worker...`);
|
|
329
|
+
clearInterval(keepAlive);
|
|
330
|
+
stopDefaultWorker();
|
|
331
|
+
process.exit(0);
|
|
332
|
+
};
|
|
333
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
334
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
335
|
+
}
|
|
301
336
|
function checkLocalHttp(url, expectedStatus = [200], timeoutMs = 1200) {
|
|
302
337
|
return new Promise((resolve) => {
|
|
303
338
|
const req = http.get(url, { timeout: timeoutMs }, (res) => {
|
|
@@ -339,6 +374,7 @@ ${bold}COMMANDS${reset}
|
|
|
339
374
|
${cyan}scan-skill${reset} <path> Scan an agent instruction file for threats
|
|
340
375
|
${cyan}scan-skills${reset} Scan all installed skills/hooks
|
|
341
376
|
${cyan}dashboard${reset} Open the local security dashboard
|
|
377
|
+
${cyan}worker${reset} Run headless background sync + heartbeat worker
|
|
342
378
|
${cyan}status${reset} Show current protection status
|
|
343
379
|
${cyan}doctor${reset} Diagnose installation issues
|
|
344
380
|
${cyan}quickstart${reset} [target] Detect the fastest setup path
|
|
@@ -364,6 +400,7 @@ ${bold}EXAMPLES${reset}
|
|
|
364
400
|
shieldcortex scan "ignore previous instructions"
|
|
365
401
|
shieldcortex scan-skill ~/.claude/skills/my-skill/SKILL.md
|
|
366
402
|
shieldcortex dashboard
|
|
403
|
+
shieldcortex worker
|
|
367
404
|
shieldcortex license activate sc_pro_...
|
|
368
405
|
shieldcortex config --cloud-enable --cloud-api-key <key>
|
|
369
406
|
shieldcortex cloud sync --full
|
|
@@ -438,7 +475,7 @@ ${bold}DOCS${reset}
|
|
|
438
475
|
}
|
|
439
476
|
// Handle "service" subcommand before normal mode parsing
|
|
440
477
|
if (process.argv[2] === 'service') {
|
|
441
|
-
await handleServiceCommand(process.argv[3] || '');
|
|
478
|
+
await handleServiceCommand(process.argv[3] || '', process.argv.slice(4));
|
|
442
479
|
return;
|
|
443
480
|
}
|
|
444
481
|
// Handle "config" subcommand (cloud sync configuration)
|
|
@@ -633,7 +670,7 @@ ${bold}DOCS${reset}
|
|
|
633
670
|
'doctor', 'quickstart', 'setup', 'install', 'migrate', 'uninstall', 'hook',
|
|
634
671
|
'openclaw', 'clawdbot', 'copilot', 'service', 'config', 'status',
|
|
635
672
|
'graph', 'license', 'licence', 'audit', 'iron-dome', 'scan', 'cloud',
|
|
636
|
-
'scan-skill', 'scan-skills', 'dashboard', 'api',
|
|
673
|
+
'scan-skill', 'scan-skills', 'dashboard', 'api', 'worker',
|
|
637
674
|
]);
|
|
638
675
|
const arg = process.argv[2];
|
|
639
676
|
if (arg && !arg.startsWith('-') && !knownCommands.has(arg)) {
|
|
@@ -708,6 +745,10 @@ ${bold}DOCS${reset}
|
|
|
708
745
|
}
|
|
709
746
|
await startMcpServer(dbPath);
|
|
710
747
|
}
|
|
748
|
+
else if (mode === 'worker') {
|
|
749
|
+
console.log('Starting ShieldCortex in headless worker mode...');
|
|
750
|
+
await startWorkerMode(dbPath);
|
|
751
|
+
}
|
|
711
752
|
else {
|
|
712
753
|
// MCP mode (default) - for Claude Code integration
|
|
713
754
|
await startMcpServer(dbPath);
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Cross-platform service installer for ShieldCortex
|
|
2
|
+
* Cross-platform service installer for persistent ShieldCortex background service.
|
|
3
3
|
*
|
|
4
4
|
* Supports:
|
|
5
5
|
* - macOS: LaunchAgent plist
|
|
6
6
|
* - Linux: systemd user service
|
|
7
7
|
* - Windows: VBS script in Startup folder
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import { type ServiceMode } from './templates.js';
|
|
10
|
+
interface ServiceOptions {
|
|
11
|
+
mode?: ServiceMode;
|
|
12
|
+
}
|
|
13
|
+
export declare function installService(options?: ServiceOptions): Promise<void>;
|
|
14
|
+
export declare function repairService(options?: ServiceOptions): Promise<void>;
|
|
11
15
|
export declare function uninstallService(options?: {
|
|
12
16
|
cleanLogs?: boolean;
|
|
13
17
|
}): Promise<void>;
|
|
14
18
|
export declare function serviceStatus(): Promise<void>;
|
|
15
|
-
export declare function handleServiceCommand(subcommand: string): Promise<void>;
|
|
19
|
+
export declare function handleServiceCommand(subcommand: string, args?: string[]): Promise<void>;
|
|
20
|
+
export {};
|
package/dist/service/install.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Cross-platform service installer for ShieldCortex
|
|
2
|
+
* Cross-platform service installer for persistent ShieldCortex background service.
|
|
3
3
|
*
|
|
4
4
|
* Supports:
|
|
5
5
|
* - macOS: LaunchAgent plist
|
|
@@ -21,7 +21,13 @@ function detectPlatform() {
|
|
|
21
21
|
default: return 'linux';
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function detectDefaultServiceMode(platform) {
|
|
25
|
+
if (platform === 'linux' && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) {
|
|
26
|
+
return 'worker';
|
|
27
|
+
}
|
|
28
|
+
return 'dashboard';
|
|
29
|
+
}
|
|
30
|
+
function getServiceConfig(mode) {
|
|
25
31
|
const logsDir = path.join(os.homedir(), '.shieldcortex', 'logs');
|
|
26
32
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
27
33
|
return {
|
|
@@ -29,33 +35,40 @@ function getServiceConfig() {
|
|
|
29
35
|
nodeBinDir: path.dirname(process.execPath),
|
|
30
36
|
entryPoint: path.resolve(__dirname, '..', 'index.js'),
|
|
31
37
|
logsDir,
|
|
38
|
+
mode,
|
|
32
39
|
};
|
|
33
40
|
}
|
|
34
41
|
function inspectServiceEntryPoint(platform, servicePath) {
|
|
35
42
|
if (!fs.existsSync(servicePath)) {
|
|
36
|
-
return { entryPoint: null, stale: false };
|
|
43
|
+
return { entryPoint: null, stale: false, mode: null };
|
|
37
44
|
}
|
|
38
45
|
try {
|
|
39
46
|
const content = fs.readFileSync(servicePath, 'utf-8');
|
|
40
47
|
let entryPoint = null;
|
|
48
|
+
let mode = null;
|
|
41
49
|
if (platform === 'macos') {
|
|
42
50
|
const matches = [...content.matchAll(/<string>([^<]+)<\/string>/g)].map((match) => match[1]);
|
|
43
51
|
entryPoint = matches.find((value) => value.endsWith('index.js')) ?? null;
|
|
52
|
+
mode = matches.find((value) => value === 'dashboard' || value === 'api' || value === 'worker') ?? null;
|
|
44
53
|
}
|
|
45
54
|
else if (platform === 'linux') {
|
|
46
55
|
const match = content.match(/ExecStart=\S+\s+(\S+index\.js)/);
|
|
47
56
|
entryPoint = match?.[1] ?? null;
|
|
57
|
+
const modeMatch = content.match(/ExecStart=\S+\s+\S+index\.js\s+--mode\s+(dashboard|api|worker)/);
|
|
58
|
+
mode = modeMatch?.[1] ?? null;
|
|
48
59
|
}
|
|
49
60
|
else {
|
|
50
61
|
const match = content.match(/Run\s+\"\"[^\"]+\"\"\s+\"\"([^\"]+index\.js)\"\"/);
|
|
51
62
|
entryPoint = match?.[1] ?? null;
|
|
63
|
+
const modeMatch = content.match(/--mode\s+(dashboard|api|worker)/);
|
|
64
|
+
mode = modeMatch?.[1] ?? null;
|
|
52
65
|
}
|
|
53
|
-
const currentEntryPoint = getServiceConfig().entryPoint;
|
|
66
|
+
const currentEntryPoint = getServiceConfig(detectDefaultServiceMode(platform)).entryPoint;
|
|
54
67
|
const stale = !!entryPoint && (entryPoint.includes('/.npm/_npx/') || entryPoint !== currentEntryPoint);
|
|
55
|
-
return { entryPoint, stale };
|
|
68
|
+
return { entryPoint, stale, mode };
|
|
56
69
|
}
|
|
57
70
|
catch {
|
|
58
|
-
return { entryPoint: null, stale: false };
|
|
71
|
+
return { entryPoint: null, stale: false, mode: null };
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
74
|
function getServicePath(platform) {
|
|
@@ -70,13 +83,33 @@ function getServicePath(platform) {
|
|
|
70
83
|
}
|
|
71
84
|
}
|
|
72
85
|
}
|
|
73
|
-
|
|
86
|
+
function summarizeServiceMode(mode) {
|
|
87
|
+
switch (mode) {
|
|
88
|
+
case 'worker':
|
|
89
|
+
return 'headless worker (recommended for servers and always-on cloud devices)';
|
|
90
|
+
case 'api':
|
|
91
|
+
return 'API service';
|
|
92
|
+
default:
|
|
93
|
+
return 'dashboard + API';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function tryEnableLinuxLinger() {
|
|
97
|
+
const username = process.env.USER || os.userInfo().username;
|
|
98
|
+
try {
|
|
99
|
+
execSync(`loginctl enable-linger "${username}"`, { stdio: 'ignore' });
|
|
100
|
+
console.log('Enabled systemd linger for persistent background service.');
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
console.log('Note: systemd linger was not enabled automatically.');
|
|
104
|
+
console.log(` On headless Linux servers, run: sudo loginctl enable-linger ${username}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export async function installService(options = {}) {
|
|
74
108
|
const platform = detectPlatform();
|
|
75
|
-
const
|
|
109
|
+
const mode = options.mode ?? detectDefaultServiceMode(platform);
|
|
110
|
+
const config = getServiceConfig(mode);
|
|
76
111
|
const servicePath = getServicePath(platform);
|
|
77
|
-
// Ensure parent directory exists
|
|
78
112
|
fs.mkdirSync(path.dirname(servicePath), { recursive: true });
|
|
79
|
-
// Generate and write service file
|
|
80
113
|
let content;
|
|
81
114
|
switch (platform) {
|
|
82
115
|
case 'macos':
|
|
@@ -91,7 +124,6 @@ export async function installService() {
|
|
|
91
124
|
}
|
|
92
125
|
fs.writeFileSync(servicePath, content, 'utf-8');
|
|
93
126
|
console.log(`Service file written to: ${servicePath}`);
|
|
94
|
-
// Enable and start the service
|
|
95
127
|
try {
|
|
96
128
|
switch (platform) {
|
|
97
129
|
case 'macos':
|
|
@@ -101,6 +133,9 @@ export async function installService() {
|
|
|
101
133
|
case 'linux':
|
|
102
134
|
execSync('systemctl --user daemon-reload', { stdio: 'inherit' });
|
|
103
135
|
execSync('systemctl --user enable --now shieldcortex-dashboard.service', { stdio: 'inherit' });
|
|
136
|
+
if (mode === 'worker' || mode === 'api') {
|
|
137
|
+
tryEnableLinuxLinger();
|
|
138
|
+
}
|
|
104
139
|
console.log('Service enabled via systemd.');
|
|
105
140
|
break;
|
|
106
141
|
case 'windows':
|
|
@@ -114,13 +149,22 @@ export async function installService() {
|
|
|
114
149
|
console.log(`The service file was written to ${servicePath} — you can enable it manually.`);
|
|
115
150
|
return;
|
|
116
151
|
}
|
|
117
|
-
console.log(
|
|
118
|
-
|
|
119
|
-
|
|
152
|
+
console.log(`\nShieldCortex ${summarizeServiceMode(mode)} will now auto-start.`);
|
|
153
|
+
if (mode === 'dashboard') {
|
|
154
|
+
console.log(' API: http://localhost:3001');
|
|
155
|
+
console.log(' Dashboard: http://localhost:3030');
|
|
156
|
+
}
|
|
157
|
+
else if (mode === 'api') {
|
|
158
|
+
console.log(' API: http://localhost:3001');
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
console.log(' Heartbeat: keeps the device online in ShieldCortex Cloud');
|
|
162
|
+
console.log(' Sync: processes background memory/graph sync retries');
|
|
163
|
+
}
|
|
120
164
|
}
|
|
121
|
-
export async function repairService() {
|
|
165
|
+
export async function repairService(options = {}) {
|
|
122
166
|
await uninstallService();
|
|
123
|
-
await installService();
|
|
167
|
+
await installService(options);
|
|
124
168
|
}
|
|
125
169
|
function cleanLogsDirectory() {
|
|
126
170
|
const logsDir = path.join(os.homedir(), '.shieldcortex', 'logs');
|
|
@@ -145,7 +189,6 @@ export async function uninstallService(options) {
|
|
|
145
189
|
execSync('systemctl --user disable --now shieldcortex-dashboard.service', { stdio: 'inherit' });
|
|
146
190
|
break;
|
|
147
191
|
case 'windows':
|
|
148
|
-
// Just delete the file — no daemon to stop
|
|
149
192
|
break;
|
|
150
193
|
}
|
|
151
194
|
}
|
|
@@ -168,11 +211,11 @@ export async function serviceStatus() {
|
|
|
168
211
|
console.log(`Path: ${servicePath}`);
|
|
169
212
|
if (inspection.entryPoint) {
|
|
170
213
|
console.log(`Entry: ${inspection.entryPoint}`);
|
|
214
|
+
console.log(`Mode: ${inspection.mode ?? 'unknown'}`);
|
|
171
215
|
console.log(`Healthy: ${inspection.stale ? 'no (repair recommended)' : 'yes'}`);
|
|
172
216
|
}
|
|
173
217
|
if (!installed)
|
|
174
218
|
return;
|
|
175
|
-
// Check if running
|
|
176
219
|
try {
|
|
177
220
|
switch (platform) {
|
|
178
221
|
case 'macos': {
|
|
@@ -198,13 +241,22 @@ export async function serviceStatus() {
|
|
|
198
241
|
console.log('Repair: shieldcortex service repair');
|
|
199
242
|
}
|
|
200
243
|
}
|
|
201
|
-
|
|
244
|
+
function parseServiceModeArgs(args) {
|
|
245
|
+
if (args.includes('--dashboard'))
|
|
246
|
+
return 'dashboard';
|
|
247
|
+
if (args.includes('--api'))
|
|
248
|
+
return 'api';
|
|
249
|
+
if (args.includes('--headless') || args.includes('--worker'))
|
|
250
|
+
return 'worker';
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
export async function handleServiceCommand(subcommand, args = []) {
|
|
202
254
|
switch (subcommand) {
|
|
203
255
|
case 'install':
|
|
204
|
-
await installService();
|
|
256
|
+
await installService({ mode: parseServiceModeArgs(args) });
|
|
205
257
|
break;
|
|
206
258
|
case 'repair':
|
|
207
|
-
await repairService();
|
|
259
|
+
await repairService({ mode: parseServiceModeArgs(args) });
|
|
208
260
|
break;
|
|
209
261
|
case 'uninstall':
|
|
210
262
|
await uninstallService({ cleanLogs: process.argv.includes('--clean-logs') });
|
|
@@ -213,7 +265,7 @@ export async function handleServiceCommand(subcommand) {
|
|
|
213
265
|
await serviceStatus();
|
|
214
266
|
break;
|
|
215
267
|
default:
|
|
216
|
-
console.log('Usage: shieldcortex service <install|repair|uninstall|status>');
|
|
268
|
+
console.log('Usage: shieldcortex service <install|repair|uninstall|status> [--dashboard|--api|--headless]');
|
|
217
269
|
process.exit(1);
|
|
218
270
|
}
|
|
219
271
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Platform-specific service file templates for auto-starting ShieldCortex
|
|
2
|
+
* Platform-specific service file templates for auto-starting ShieldCortex.
|
|
3
3
|
*/
|
|
4
|
+
export type ServiceMode = 'dashboard' | 'api' | 'worker';
|
|
4
5
|
export interface ServiceConfig {
|
|
5
6
|
nodePath: string;
|
|
6
7
|
nodeBinDir: string;
|
|
7
8
|
entryPoint: string;
|
|
8
9
|
logsDir: string;
|
|
10
|
+
mode: ServiceMode;
|
|
9
11
|
}
|
|
10
12
|
export declare function launchdPlist(config: ServiceConfig): string;
|
|
11
13
|
export declare function systemdUnit(config: ServiceConfig): string;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Platform-specific service file templates for auto-starting ShieldCortex
|
|
2
|
+
* Platform-specific service file templates for auto-starting ShieldCortex.
|
|
3
3
|
*/
|
|
4
|
+
function modeLabel(mode) {
|
|
5
|
+
switch (mode) {
|
|
6
|
+
case 'worker':
|
|
7
|
+
return 'Worker';
|
|
8
|
+
case 'api':
|
|
9
|
+
return 'API';
|
|
10
|
+
default:
|
|
11
|
+
return 'Dashboard';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
4
14
|
export function launchdPlist(config) {
|
|
5
15
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
6
16
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -13,7 +23,7 @@ export function launchdPlist(config) {
|
|
|
13
23
|
<string>${config.nodePath}</string>
|
|
14
24
|
<string>${config.entryPoint}</string>
|
|
15
25
|
<string>--mode</string>
|
|
16
|
-
<string
|
|
26
|
+
<string>${config.mode}</string>
|
|
17
27
|
</array>
|
|
18
28
|
<key>RunAtLoad</key>
|
|
19
29
|
<true/>
|
|
@@ -33,12 +43,12 @@ export function launchdPlist(config) {
|
|
|
33
43
|
}
|
|
34
44
|
export function systemdUnit(config) {
|
|
35
45
|
return `[Unit]
|
|
36
|
-
Description=ShieldCortex
|
|
46
|
+
Description=ShieldCortex ${modeLabel(config.mode)}
|
|
37
47
|
After=network.target
|
|
38
48
|
|
|
39
49
|
[Service]
|
|
40
50
|
Type=simple
|
|
41
|
-
ExecStart=${config.nodePath} ${config.entryPoint} --mode
|
|
51
|
+
ExecStart=${config.nodePath} ${config.entryPoint} --mode ${config.mode}
|
|
42
52
|
Restart=on-failure
|
|
43
53
|
RestartSec=5
|
|
44
54
|
StandardOutput=append:${config.logsDir}/dashboard-stdout.log
|
|
@@ -53,5 +63,5 @@ export function windowsVbs(config) {
|
|
|
53
63
|
const nodePath = config.nodePath.replace(/\//g, '\\');
|
|
54
64
|
const entryPoint = config.entryPoint.replace(/\//g, '\\');
|
|
55
65
|
return `Set WshShell = CreateObject("WScript.Shell")
|
|
56
|
-
WshShell.Run """${nodePath}"" ""${entryPoint}"" --mode
|
|
66
|
+
WshShell.Run """${nodePath}"" ""${entryPoint}"" --mode ${config.mode}", 0, False`;
|
|
57
67
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shieldcortex",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.3",
|
|
4
4
|
"description": "Trustworthy memory and security for AI agents. Recall debugging, review queue, OpenClaw session capture, and memory poisoning defence for Claude Code, OpenClaw, LangChain, and MCP agents.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
File without changes
|
|
File without changes
|