@opentrust/cli 7.0.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/README.md +68 -0
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +35 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.js +57 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/commands/start.js +24 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +23 -0
- package/dist/commands/stop.d.ts +2 -0
- package/dist/commands/stop.js +22 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -0
- package/dist/lib/paths.d.ts +15 -0
- package/dist/lib/paths.js +63 -0
- package/dist/lib/process-manager.d.ts +19 -0
- package/dist/lib/process-manager.js +146 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @opentrust/cli
|
|
2
|
+
|
|
3
|
+
CLI tool to manage [OpenTrust](https://github.com/opentrust-dev/opentrust) — an open-source AI Agent Runtime Security Platform.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @opentrust/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or run directly with `npx`:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @opentrust/cli <command>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- **Node.js** >= 18
|
|
20
|
+
- **pnpm** >= 9 (Dashboard uses pnpm monorepo)
|
|
21
|
+
- Clone the [opentrust](https://github.com/opentrust-dev/opentrust) repo first
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Navigate to your opentrust project directory, then:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Install all dependencies, build, and initialize databases
|
|
29
|
+
opentrust setup
|
|
30
|
+
|
|
31
|
+
# Start all services (core + dashboard + gateway)
|
|
32
|
+
opentrust start
|
|
33
|
+
|
|
34
|
+
# Start a single service
|
|
35
|
+
opentrust start core
|
|
36
|
+
|
|
37
|
+
# Check status of all services
|
|
38
|
+
opentrust status
|
|
39
|
+
|
|
40
|
+
# Stop all services
|
|
41
|
+
opentrust stop
|
|
42
|
+
|
|
43
|
+
# Stop a single service
|
|
44
|
+
opentrust stop gateway
|
|
45
|
+
|
|
46
|
+
# View logs
|
|
47
|
+
opentrust logs core
|
|
48
|
+
opentrust logs dashboard -f # follow mode
|
|
49
|
+
opentrust logs gateway -n 100 # last 100 lines
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Services
|
|
53
|
+
|
|
54
|
+
| Service | Port | Description |
|
|
55
|
+
|---------|------|-------------|
|
|
56
|
+
| **Core** | 53666 | Security engine — content detection (S01-S10), behavior assessment, Agent registry |
|
|
57
|
+
| **Dashboard** | 53667/53668 | Management panel — Agent assets, risk graph, policy management, detection logs |
|
|
58
|
+
| **Gateway** | 8900 | AI security gateway — LLM API proxy with automatic PII/credential sanitization |
|
|
59
|
+
|
|
60
|
+
## Environment Variables
|
|
61
|
+
|
|
62
|
+
| Variable | Description |
|
|
63
|
+
|----------|-------------|
|
|
64
|
+
| `OPENTRUST_HOME` | Override the project root directory (defaults to `cwd`) |
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
Apache-2.0
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { SERVICES, getAllServiceKeys } from "../lib/process-manager.js";
|
|
4
|
+
export function registerLogsCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command("logs <service>")
|
|
7
|
+
.description("Tail logs for a service (core, dashboard, gateway)")
|
|
8
|
+
.option("-n, --lines <n>", "Number of lines to show", "50")
|
|
9
|
+
.option("-f, --follow", "Follow log output", false)
|
|
10
|
+
.action(async (service, options) => {
|
|
11
|
+
const svc = SERVICES[service];
|
|
12
|
+
if (!svc) {
|
|
13
|
+
console.error(`Unknown service: ${service}`);
|
|
14
|
+
console.error(`Available: ${getAllServiceKeys().join(", ")}`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
if (!fs.existsSync(svc.logFile)) {
|
|
18
|
+
console.log(`No log file found for ${svc.name}.`);
|
|
19
|
+
console.log(`Start it first: opentrust start ${service}`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const args = ["-n", options.lines];
|
|
23
|
+
if (options.follow)
|
|
24
|
+
args.push("-f");
|
|
25
|
+
args.push(svc.logFile);
|
|
26
|
+
const tail = spawn("tail", args, { stdio: "inherit" });
|
|
27
|
+
tail.on("error", (err) => {
|
|
28
|
+
console.error(`Failed to tail logs: ${err.message}`);
|
|
29
|
+
});
|
|
30
|
+
process.on("SIGINT", () => {
|
|
31
|
+
tail.kill();
|
|
32
|
+
process.exit(0);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { paths } from "../lib/paths.js";
|
|
4
|
+
export function registerSetupCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command("setup")
|
|
7
|
+
.description("Install dependencies, build, and initialize databases")
|
|
8
|
+
.action(async () => {
|
|
9
|
+
console.log("OpenTrust Setup\n");
|
|
10
|
+
const steps = [
|
|
11
|
+
{
|
|
12
|
+
label: "Core",
|
|
13
|
+
cwd: paths.core,
|
|
14
|
+
commands: ["npm install"],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: "Dashboard",
|
|
18
|
+
cwd: paths.dashboard,
|
|
19
|
+
commands: [
|
|
20
|
+
"pnpm install",
|
|
21
|
+
"pnpm build",
|
|
22
|
+
"pnpm db:generate",
|
|
23
|
+
"pnpm db:migrate",
|
|
24
|
+
"pnpm db:seed",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: "Gateway",
|
|
29
|
+
cwd: paths.gateway,
|
|
30
|
+
commands: ["npm install"],
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
for (const step of steps) {
|
|
34
|
+
if (!fs.existsSync(step.cwd)) {
|
|
35
|
+
console.log(` ⚠ ${step.label}: directory not found, skipping`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
console.log(`Setting up ${step.label}...`);
|
|
39
|
+
for (const cmd of step.commands) {
|
|
40
|
+
try {
|
|
41
|
+
console.log(` $ ${cmd}`);
|
|
42
|
+
execSync(cmd, { cwd: step.cwd, stdio: "inherit" });
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error(` Failed: ${cmd}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
console.log(` ${step.label} ready.\n`);
|
|
50
|
+
}
|
|
51
|
+
console.log("-------------------------------------------");
|
|
52
|
+
console.log("Setup complete!");
|
|
53
|
+
console.log("-------------------------------------------");
|
|
54
|
+
console.log("\nRun 'opentrust start' to launch all services.");
|
|
55
|
+
console.log("Or start individually: 'opentrust start core'");
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { startService, getAllServiceKeys, SERVICES } from "../lib/process-manager.js";
|
|
2
|
+
export function registerStartCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("start [service]")
|
|
5
|
+
.description("Start services (core, dashboard, gateway, or all)")
|
|
6
|
+
.action(async (service) => {
|
|
7
|
+
const keys = service ? [service] : getAllServiceKeys();
|
|
8
|
+
for (const key of keys) {
|
|
9
|
+
if (!SERVICES[key]) {
|
|
10
|
+
console.error(`Unknown service: ${key}`);
|
|
11
|
+
console.error(`Available: ${getAllServiceKeys().join(", ")}`);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
console.log(service
|
|
16
|
+
? `Starting ${SERVICES[service].name}...`
|
|
17
|
+
: "Starting all OpenTrust services...");
|
|
18
|
+
for (const key of keys) {
|
|
19
|
+
startService(key);
|
|
20
|
+
}
|
|
21
|
+
console.log("\nUse 'opentrust status' to check health.");
|
|
22
|
+
console.log("Use 'opentrust logs <service>' to view output.");
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getStatus, checkHealth, getAllServiceKeys, SERVICES } from "../lib/process-manager.js";
|
|
2
|
+
export function registerStatusCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("status")
|
|
5
|
+
.description("Show status of all OpenTrust services")
|
|
6
|
+
.action(async () => {
|
|
7
|
+
console.log("OpenTrust Service Status\n");
|
|
8
|
+
const keys = getAllServiceKeys();
|
|
9
|
+
for (const key of keys) {
|
|
10
|
+
const svc = SERVICES[key];
|
|
11
|
+
const { running, pid } = getStatus(key);
|
|
12
|
+
const healthy = running ? await checkHealth(key) : false;
|
|
13
|
+
const statusIcon = running ? (healthy ? "\x1b[32m●\x1b[0m" : "\x1b[33m●\x1b[0m") : "\x1b[31m●\x1b[0m";
|
|
14
|
+
const statusText = running
|
|
15
|
+
? healthy
|
|
16
|
+
? `running (PID ${pid})`
|
|
17
|
+
: `running, not healthy yet (PID ${pid})`
|
|
18
|
+
: "stopped";
|
|
19
|
+
console.log(` ${statusIcon} ${svc.name.padEnd(12)} ${statusText.padEnd(35)} port ${svc.port}`);
|
|
20
|
+
}
|
|
21
|
+
console.log("");
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { stopService, getAllServiceKeys, SERVICES } from "../lib/process-manager.js";
|
|
2
|
+
export function registerStopCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("stop [service]")
|
|
5
|
+
.description("Stop services (core, dashboard, gateway, or all)")
|
|
6
|
+
.action(async (service) => {
|
|
7
|
+
const keys = service ? [service] : getAllServiceKeys();
|
|
8
|
+
for (const key of keys) {
|
|
9
|
+
if (!SERVICES[key]) {
|
|
10
|
+
console.error(`Unknown service: ${key}`);
|
|
11
|
+
console.error(`Available: ${getAllServiceKeys().join(", ")}`);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
console.log(service
|
|
16
|
+
? `Stopping ${SERVICES[service].name}...`
|
|
17
|
+
: "Stopping all OpenTrust services...");
|
|
18
|
+
for (const key of keys) {
|
|
19
|
+
stopService(key);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { registerStartCommand } from "./commands/start.js";
|
|
7
|
+
import { registerStopCommand } from "./commands/stop.js";
|
|
8
|
+
import { registerStatusCommand } from "./commands/status.js";
|
|
9
|
+
import { registerSetupCommand } from "./commands/setup.js";
|
|
10
|
+
import { registerLogsCommand } from "./commands/logs.js";
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name("opentrust")
|
|
16
|
+
.description("OpenTrust — manage local AI security services")
|
|
17
|
+
.version(pkg.version);
|
|
18
|
+
registerStartCommand(program);
|
|
19
|
+
registerStopCommand(program);
|
|
20
|
+
registerStatusCommand(program);
|
|
21
|
+
registerSetupCommand(program);
|
|
22
|
+
registerLogsCommand(program);
|
|
23
|
+
program.parse();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const paths: {
|
|
2
|
+
projectRoot: string;
|
|
3
|
+
runtime: string;
|
|
4
|
+
logs: string;
|
|
5
|
+
core: string;
|
|
6
|
+
dashboard: string;
|
|
7
|
+
gateway: string;
|
|
8
|
+
guards: string;
|
|
9
|
+
corePid: string;
|
|
10
|
+
dashboardPid: string;
|
|
11
|
+
gatewayPid: string;
|
|
12
|
+
coreLog: string;
|
|
13
|
+
dashboardLog: string;
|
|
14
|
+
gatewayLog: string;
|
|
15
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
function findProjectRoot() {
|
|
7
|
+
// 1. OPENTRUST_HOME env var takes priority
|
|
8
|
+
if (process.env.OPENTRUST_HOME) {
|
|
9
|
+
return path.resolve(process.env.OPENTRUST_HOME);
|
|
10
|
+
}
|
|
11
|
+
// 2. Check if cwd looks like the opentrust project root
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
if (isOpenTrustRoot(cwd)) {
|
|
14
|
+
return cwd;
|
|
15
|
+
}
|
|
16
|
+
// 3. Walk up from cwd looking for the project root
|
|
17
|
+
let dir = cwd;
|
|
18
|
+
while (true) {
|
|
19
|
+
const parent = path.dirname(dir);
|
|
20
|
+
if (parent === dir)
|
|
21
|
+
break;
|
|
22
|
+
dir = parent;
|
|
23
|
+
if (isOpenTrustRoot(dir))
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
26
|
+
// 4. Fallback: resolve relative to __dirname (works inside monorepo)
|
|
27
|
+
const fallback = path.resolve(__dirname, "../../..");
|
|
28
|
+
if (isOpenTrustRoot(fallback)) {
|
|
29
|
+
return fallback;
|
|
30
|
+
}
|
|
31
|
+
// 5. Last resort: use cwd and let commands fail with meaningful errors
|
|
32
|
+
return cwd;
|
|
33
|
+
}
|
|
34
|
+
function isOpenTrustRoot(dir) {
|
|
35
|
+
try {
|
|
36
|
+
const pkgPath = path.join(dir, "package.json");
|
|
37
|
+
if (!fs.existsSync(pkgPath))
|
|
38
|
+
return false;
|
|
39
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
40
|
+
return pkg.name === "opentrust";
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const projectRoot = findProjectRoot();
|
|
47
|
+
/** ~/.opentrust/ — runtime data (pid files, logs) */
|
|
48
|
+
const runtimeDir = path.join(os.homedir(), ".opentrust");
|
|
49
|
+
export const paths = {
|
|
50
|
+
projectRoot,
|
|
51
|
+
runtime: runtimeDir,
|
|
52
|
+
logs: path.join(runtimeDir, "logs"),
|
|
53
|
+
core: path.join(projectRoot, "core"),
|
|
54
|
+
dashboard: path.join(projectRoot, "dashboard"),
|
|
55
|
+
gateway: path.join(projectRoot, "gateway"),
|
|
56
|
+
guards: path.join(projectRoot, "guards"),
|
|
57
|
+
corePid: path.join(runtimeDir, "core.pid"),
|
|
58
|
+
dashboardPid: path.join(runtimeDir, "dashboard.pid"),
|
|
59
|
+
gatewayPid: path.join(runtimeDir, "gateway.pid"),
|
|
60
|
+
coreLog: path.join(runtimeDir, "logs", "core.log"),
|
|
61
|
+
dashboardLog: path.join(runtimeDir, "logs", "dashboard.log"),
|
|
62
|
+
gatewayLog: path.join(runtimeDir, "logs", "gateway.log"),
|
|
63
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ServiceDef {
|
|
2
|
+
name: string;
|
|
3
|
+
cwd: string;
|
|
4
|
+
command: string;
|
|
5
|
+
args: string[];
|
|
6
|
+
pidFile: string;
|
|
7
|
+
logFile: string;
|
|
8
|
+
port: number;
|
|
9
|
+
healthUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const SERVICES: Record<string, ServiceDef>;
|
|
12
|
+
export declare function startService(key: string): boolean;
|
|
13
|
+
export declare function stopService(key: string): boolean;
|
|
14
|
+
export declare function getStatus(key: string): {
|
|
15
|
+
running: boolean;
|
|
16
|
+
pid?: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function checkHealth(key: string): Promise<boolean>;
|
|
19
|
+
export declare function getAllServiceKeys(): string[];
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { paths } from "./paths.js";
|
|
4
|
+
export const SERVICES = {
|
|
5
|
+
core: {
|
|
6
|
+
name: "Core",
|
|
7
|
+
cwd: paths.core,
|
|
8
|
+
command: "npx",
|
|
9
|
+
args: ["tsx", "src/index.ts"],
|
|
10
|
+
pidFile: paths.corePid,
|
|
11
|
+
logFile: paths.coreLog,
|
|
12
|
+
port: 53666,
|
|
13
|
+
healthUrl: "http://localhost:53666/health",
|
|
14
|
+
},
|
|
15
|
+
dashboard: {
|
|
16
|
+
name: "Dashboard",
|
|
17
|
+
cwd: paths.dashboard,
|
|
18
|
+
command: "npx",
|
|
19
|
+
args: ["turbo", "dev"],
|
|
20
|
+
pidFile: paths.dashboardPid,
|
|
21
|
+
logFile: paths.dashboardLog,
|
|
22
|
+
port: 53667,
|
|
23
|
+
healthUrl: "http://localhost:53667/health",
|
|
24
|
+
},
|
|
25
|
+
gateway: {
|
|
26
|
+
name: "Gateway",
|
|
27
|
+
cwd: paths.gateway,
|
|
28
|
+
command: "npx",
|
|
29
|
+
args: ["tsx", "src/index.ts"],
|
|
30
|
+
pidFile: paths.gatewayPid,
|
|
31
|
+
logFile: paths.gatewayLog,
|
|
32
|
+
port: 8900,
|
|
33
|
+
healthUrl: "http://localhost:8900/health",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
function ensureDirs() {
|
|
37
|
+
for (const dir of [paths.runtime, paths.logs]) {
|
|
38
|
+
if (!fs.existsSync(dir))
|
|
39
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function startService(key) {
|
|
43
|
+
const svc = SERVICES[key];
|
|
44
|
+
if (!svc) {
|
|
45
|
+
console.error(`Unknown service: ${key}`);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (!fs.existsSync(svc.cwd)) {
|
|
49
|
+
console.error(` ${svc.name}: directory not found at ${svc.cwd}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const status = getStatus(key);
|
|
53
|
+
if (status.running) {
|
|
54
|
+
console.log(` ${svc.name}: already running (PID ${status.pid})`);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
ensureDirs();
|
|
58
|
+
const logFd = fs.openSync(svc.logFile, "a");
|
|
59
|
+
const child = spawn(svc.command, svc.args, {
|
|
60
|
+
cwd: svc.cwd,
|
|
61
|
+
env: { ...process.env, FORCE_COLOR: "0" },
|
|
62
|
+
stdio: ["ignore", logFd, logFd],
|
|
63
|
+
detached: true,
|
|
64
|
+
});
|
|
65
|
+
if (child.pid) {
|
|
66
|
+
fs.writeFileSync(svc.pidFile, String(child.pid), "utf-8");
|
|
67
|
+
child.unref();
|
|
68
|
+
console.log(` ${svc.name}: started (PID ${child.pid}, port ${svc.port})`);
|
|
69
|
+
fs.closeSync(logFd);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
fs.closeSync(logFd);
|
|
73
|
+
console.error(` ${svc.name}: failed to start`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
export function stopService(key) {
|
|
77
|
+
const svc = SERVICES[key];
|
|
78
|
+
if (!svc) {
|
|
79
|
+
console.error(`Unknown service: ${key}`);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
const status = getStatus(key);
|
|
83
|
+
if (!status.running) {
|
|
84
|
+
console.log(` ${svc.name}: not running`);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
// Kill the process group (negative PID) to stop all children
|
|
89
|
+
process.kill(-status.pid, "SIGTERM");
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
try {
|
|
93
|
+
process.kill(status.pid, "SIGTERM");
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// already dead
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
fs.unlinkSync(svc.pidFile);
|
|
101
|
+
}
|
|
102
|
+
catch { }
|
|
103
|
+
console.log(` ${svc.name}: stopped (was PID ${status.pid})`);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
export function getStatus(key) {
|
|
107
|
+
const svc = SERVICES[key];
|
|
108
|
+
if (!svc)
|
|
109
|
+
return { running: false };
|
|
110
|
+
if (!fs.existsSync(svc.pidFile))
|
|
111
|
+
return { running: false };
|
|
112
|
+
const pid = parseInt(fs.readFileSync(svc.pidFile, "utf-8").trim(), 10);
|
|
113
|
+
if (isNaN(pid)) {
|
|
114
|
+
try {
|
|
115
|
+
fs.unlinkSync(svc.pidFile);
|
|
116
|
+
}
|
|
117
|
+
catch { }
|
|
118
|
+
return { running: false };
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
process.kill(pid, 0);
|
|
122
|
+
return { running: true, pid };
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
try {
|
|
126
|
+
fs.unlinkSync(svc.pidFile);
|
|
127
|
+
}
|
|
128
|
+
catch { }
|
|
129
|
+
return { running: false };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export async function checkHealth(key) {
|
|
133
|
+
const svc = SERVICES[key];
|
|
134
|
+
if (!svc?.healthUrl)
|
|
135
|
+
return false;
|
|
136
|
+
try {
|
|
137
|
+
const res = await fetch(svc.healthUrl);
|
|
138
|
+
return res.ok;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export function getAllServiceKeys() {
|
|
145
|
+
return Object.keys(SERVICES);
|
|
146
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opentrust/cli",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "CLI tool to manage OpenTrust AI Agent Runtime Security Platform — setup, start, stop, status, logs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"opentrust": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"dev": "tsx src/index.ts",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"commander": "^12.1.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.0.0",
|
|
23
|
+
"tsx": "^4.19.0",
|
|
24
|
+
"typescript": "^5.7.0"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"opentrust",
|
|
28
|
+
"ai-security",
|
|
29
|
+
"agent-security",
|
|
30
|
+
"cli",
|
|
31
|
+
"pii",
|
|
32
|
+
"prompt-injection",
|
|
33
|
+
"llm-security",
|
|
34
|
+
"ai-agent"
|
|
35
|
+
],
|
|
36
|
+
"homepage": "https://github.com/opentrust-dev/opentrust#readme",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/opentrust-dev/opentrust.git",
|
|
40
|
+
"directory": "cli"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/opentrust-dev/opentrust/issues"
|
|
44
|
+
},
|
|
45
|
+
"author": "OpenTrust",
|
|
46
|
+
"license": "Apache-2.0",
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|