openclaw-safeclaw-plugin 0.4.0 → 0.5.1
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/cli.tsx +43 -1
- package/dist/cli.js +39 -1
- package/dist/tui/App.js +6 -1
- package/package.json +1 -1
- package/tui/App.tsx +7 -1
package/cli.tsx
CHANGED
|
@@ -2,12 +2,53 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { render } from 'ink';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
+
import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { homedir } from 'os';
|
|
5
8
|
import App from './tui/App.js';
|
|
6
9
|
|
|
7
10
|
const args = process.argv.slice(2);
|
|
8
11
|
const command = args[0];
|
|
9
12
|
|
|
10
|
-
if (command === '
|
|
13
|
+
if (command === 'connect') {
|
|
14
|
+
const apiKey = args[1];
|
|
15
|
+
const serviceUrlIdx = args.indexOf('--service-url');
|
|
16
|
+
const serviceUrl = serviceUrlIdx !== -1 && args[serviceUrlIdx + 1]
|
|
17
|
+
? args[serviceUrlIdx + 1]
|
|
18
|
+
: 'https://api.safeclaw.eu/api/v1';
|
|
19
|
+
|
|
20
|
+
if (!apiKey || apiKey.startsWith('--')) {
|
|
21
|
+
console.error('Usage: safeclaw connect <api-key> [--service-url <url>]');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const configDir = join(homedir(), '.safeclaw');
|
|
26
|
+
const configPath = join(configDir, 'config.json');
|
|
27
|
+
|
|
28
|
+
// Load existing config or start fresh
|
|
29
|
+
let config: Record<string, unknown> = {};
|
|
30
|
+
if (existsSync(configPath)) {
|
|
31
|
+
try {
|
|
32
|
+
config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
33
|
+
} catch {
|
|
34
|
+
// Start fresh
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Set remote config
|
|
39
|
+
if (!config.remote || typeof config.remote !== 'object') {
|
|
40
|
+
config.remote = {};
|
|
41
|
+
}
|
|
42
|
+
(config.remote as Record<string, string>).apiKey = apiKey;
|
|
43
|
+
(config.remote as Record<string, string>).serviceUrl = serviceUrl;
|
|
44
|
+
|
|
45
|
+
// Write config with owner-only permissions
|
|
46
|
+
mkdirSync(configDir, { recursive: true });
|
|
47
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
48
|
+
chmodSync(configPath, 0o600);
|
|
49
|
+
|
|
50
|
+
console.log(`Connected! Your API key has been saved to ${configPath}`);
|
|
51
|
+
} else if (command === 'tui') {
|
|
11
52
|
render(React.createElement(App));
|
|
12
53
|
} else if (command === 'restart-openclaw') {
|
|
13
54
|
try {
|
|
@@ -23,6 +64,7 @@ if (command === 'tui') {
|
|
|
23
64
|
console.log('Usage: safeclaw <command>');
|
|
24
65
|
console.log('');
|
|
25
66
|
console.log('Commands:');
|
|
67
|
+
console.log(' connect <api-key> Save your API key to ~/.safeclaw/config.json');
|
|
26
68
|
console.log(' tui Open the interactive SafeClaw settings TUI');
|
|
27
69
|
console.log(' restart-openclaw Restart the OpenClaw daemon');
|
|
28
70
|
process.exit(0);
|
package/dist/cli.js
CHANGED
|
@@ -2,10 +2,47 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { render } from 'ink';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
+
import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { homedir } from 'os';
|
|
5
8
|
import App from './tui/App.js';
|
|
6
9
|
const args = process.argv.slice(2);
|
|
7
10
|
const command = args[0];
|
|
8
|
-
if (command === '
|
|
11
|
+
if (command === 'connect') {
|
|
12
|
+
const apiKey = args[1];
|
|
13
|
+
const serviceUrlIdx = args.indexOf('--service-url');
|
|
14
|
+
const serviceUrl = serviceUrlIdx !== -1 && args[serviceUrlIdx + 1]
|
|
15
|
+
? args[serviceUrlIdx + 1]
|
|
16
|
+
: 'https://api.safeclaw.eu/api/v1';
|
|
17
|
+
if (!apiKey || apiKey.startsWith('--')) {
|
|
18
|
+
console.error('Usage: safeclaw connect <api-key> [--service-url <url>]');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const configDir = join(homedir(), '.safeclaw');
|
|
22
|
+
const configPath = join(configDir, 'config.json');
|
|
23
|
+
// Load existing config or start fresh
|
|
24
|
+
let config = {};
|
|
25
|
+
if (existsSync(configPath)) {
|
|
26
|
+
try {
|
|
27
|
+
config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Start fresh
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Set remote config
|
|
34
|
+
if (!config.remote || typeof config.remote !== 'object') {
|
|
35
|
+
config.remote = {};
|
|
36
|
+
}
|
|
37
|
+
config.remote.apiKey = apiKey;
|
|
38
|
+
config.remote.serviceUrl = serviceUrl;
|
|
39
|
+
// Write config with owner-only permissions
|
|
40
|
+
mkdirSync(configDir, { recursive: true });
|
|
41
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
42
|
+
chmodSync(configPath, 0o600);
|
|
43
|
+
console.log(`Connected! Your API key has been saved to ${configPath}`);
|
|
44
|
+
}
|
|
45
|
+
else if (command === 'tui') {
|
|
9
46
|
render(React.createElement(App));
|
|
10
47
|
}
|
|
11
48
|
else if (command === 'restart-openclaw') {
|
|
@@ -24,6 +61,7 @@ else {
|
|
|
24
61
|
console.log('Usage: safeclaw <command>');
|
|
25
62
|
console.log('');
|
|
26
63
|
console.log('Commands:');
|
|
64
|
+
console.log(' connect <api-key> Save your API key to ~/.safeclaw/config.json');
|
|
27
65
|
console.log(' tui Open the interactive SafeClaw settings TUI');
|
|
28
66
|
console.log(' restart-openclaw Restart the OpenClaw daemon');
|
|
29
67
|
process.exit(0);
|
package/dist/tui/App.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { Text, Box, useInput, useApp } from 'ink';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { dirname, join } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
4
7
|
import { loadConfig } from './config.js';
|
|
5
8
|
import Status from './Status.js';
|
|
6
9
|
import Settings from './Settings.js';
|
|
7
10
|
import About from './About.js';
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const PKG_VERSION = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8')).version;
|
|
8
13
|
const TABS = ['Status', 'Settings', 'About'];
|
|
9
14
|
export default function App() {
|
|
10
15
|
const { exit } = useApp();
|
|
@@ -28,5 +33,5 @@ export default function App() {
|
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
35
|
});
|
|
31
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { borderStyle: "single", borderColor: "green", paddingX: 1, children: [_jsx(Text, { bold: true, color: "green", children: "SafeClaw " }),
|
|
36
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { borderStyle: "single", borderColor: "green", paddingX: 1, children: [_jsx(Text, { bold: true, color: "green", children: "SafeClaw " }), _jsxs(Text, { dimColor: true, children: ["v", PKG_VERSION] })] }), _jsxs(Box, { paddingX: 1, gap: 2, children: [TABS.map((t, i) => (_jsx(Text, { bold: tab === t, color: tab === t ? 'cyan' : 'white', dimColor: tab !== t, children: `${i + 1}:${t}` }, t))), _jsx(Text, { dimColor: true, children: " tab/1-3 to switch" })] }), _jsxs(Box, { marginTop: 1, children: [tab === 'Status' && _jsx(Status, { config: config }), tab === 'Settings' && (_jsx(Settings, { config: config, onConfigChange: setConfig })), tab === 'About' && _jsx(About, {})] })] }));
|
|
32
37
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-safeclaw-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "SafeClaw Neurosymbolic Governance plugin for OpenClaw — validates AI agent actions against OWL ontologies and SHACL constraints",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/tui/App.tsx
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { Text, Box, useInput, useApp } from 'ink';
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
3
6
|
import { loadConfig, type SafeClawConfig } from './config.js';
|
|
4
7
|
import Status from './Status.js';
|
|
5
8
|
import Settings from './Settings.js';
|
|
6
9
|
import About from './About.js';
|
|
7
10
|
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const PKG_VERSION = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8')).version as string;
|
|
13
|
+
|
|
8
14
|
const TABS = ['Status', 'Settings', 'About'] as const;
|
|
9
15
|
type Tab = typeof TABS[number];
|
|
10
16
|
|
|
@@ -34,7 +40,7 @@ export default function App() {
|
|
|
34
40
|
{/* Header */}
|
|
35
41
|
<Box borderStyle="single" borderColor="green" paddingX={1}>
|
|
36
42
|
<Text bold color="green">SafeClaw </Text>
|
|
37
|
-
<Text dimColor>
|
|
43
|
+
<Text dimColor>v{PKG_VERSION}</Text>
|
|
38
44
|
</Box>
|
|
39
45
|
|
|
40
46
|
{/* Tab bar */}
|