@omnixal/openclaw-nats-plugin 0.2.2 → 0.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/cli/docker-setup.ts +38 -2
- package/cli/paths.ts +1 -0
- package/cli/setup.ts +22 -6
- package/package.json +1 -1
- package/plugins/nats-context-engine/http-handler.ts +8 -2
package/cli/docker-setup.ts
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
import { mkdirSync, cpSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { execFileSync } from 'node:child_process';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
|
-
import { PLUGIN_DIR, DOCKER_DIR, STATE_FILE, type PluginState } from './paths';
|
|
4
|
+
import { PLUGIN_DIR, DOCKER_DIR, DASHBOARD_DIR, STATE_FILE, type PluginState } from './paths';
|
|
5
5
|
import { generateApiKey, writeEnvVariables } from './env-writer';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Try to copy dashboard dist into a running OpenClaw container's volume.
|
|
9
|
+
* This handles the case where setup runs on the host but OpenClaw is in Docker.
|
|
10
|
+
*/
|
|
11
|
+
function copyDashboardToContainer(dashboardDir: string): void {
|
|
12
|
+
if (!existsSync(join(dashboardDir, 'index.html'))) return;
|
|
13
|
+
|
|
14
|
+
const candidates = ['openclaw-gateway', 'openclaw-cli'];
|
|
15
|
+
for (const container of candidates) {
|
|
16
|
+
try {
|
|
17
|
+
const status = execFileSync(
|
|
18
|
+
'docker', ['inspect', '--format={{.State.Running}}', container],
|
|
19
|
+
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },
|
|
20
|
+
).trim();
|
|
21
|
+
if (status !== 'true') continue;
|
|
22
|
+
|
|
23
|
+
const home = execFileSync(
|
|
24
|
+
'docker', ['exec', container, 'sh', '-c', 'echo $HOME'],
|
|
25
|
+
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },
|
|
26
|
+
).trim();
|
|
27
|
+
|
|
28
|
+
const remotePath = `${home}/.openclaw/nats-plugin/dashboard`;
|
|
29
|
+
execFileSync('docker', ['exec', container, 'mkdir', '-p', remotePath]);
|
|
30
|
+
execFileSync('docker', ['cp', `${dashboardDir}/.`, `${container}:${remotePath}/`]);
|
|
31
|
+
console.log(`Dashboard copied into container '${container}' at ${remotePath}`);
|
|
32
|
+
return;
|
|
33
|
+
} catch {
|
|
34
|
+
// Container not found or not running, try next
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
console.log('Note: No running OpenClaw container found. Dashboard will be served after setup runs inside the container.');
|
|
38
|
+
}
|
|
39
|
+
|
|
7
40
|
export async function dockerSetup(): Promise<void> {
|
|
8
41
|
console.log('Setting up NATS plugin (Docker mode)...\n');
|
|
9
42
|
|
|
@@ -40,7 +73,10 @@ export async function dockerSetup(): Promise<void> {
|
|
|
40
73
|
NATS_SERVERS: 'nats://127.0.0.1:4222',
|
|
41
74
|
});
|
|
42
75
|
|
|
43
|
-
// 5.
|
|
76
|
+
// 5. Copy dashboard dist into OpenClaw container (host→container bridge)
|
|
77
|
+
copyDashboardToContainer(DASHBOARD_DIR);
|
|
78
|
+
|
|
79
|
+
// 6. Save state
|
|
44
80
|
const state: PluginState = {
|
|
45
81
|
runtime: 'docker',
|
|
46
82
|
installedAt: new Date().toISOString(),
|
package/cli/paths.ts
CHANGED
|
@@ -9,6 +9,7 @@ export const DATA_DIR = join(PLUGIN_DIR, 'data');
|
|
|
9
9
|
export const JETSTREAM_DIR = join(DATA_DIR, 'jetstream');
|
|
10
10
|
export const NATS_SERVER_BIN = join(BIN_DIR, 'nats-server');
|
|
11
11
|
export const NATS_CONF = join(PLUGIN_DIR, 'nats-server.conf');
|
|
12
|
+
export const DASHBOARD_DIR = join(PLUGIN_DIR, 'dashboard');
|
|
12
13
|
export const DOCKER_DIR = join(PLUGIN_DIR, 'docker');
|
|
13
14
|
export const OPENCLAW_ENV = join(OPENCLAW_DIR, '.env');
|
|
14
15
|
export const STATE_FILE = join(PLUGIN_DIR, 'state.json');
|
package/cli/setup.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, cpSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { execFileSync } from 'node:child_process';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
|
-
import { STATE_FILE, type PluginState } from './paths';
|
|
4
|
+
import { STATE_FILE, DASHBOARD_DIR, type PluginState } from './paths';
|
|
5
5
|
import { detectRuntime, type Runtime } from './detect-runtime';
|
|
6
6
|
import { bunSetup } from './bun-setup';
|
|
7
7
|
import { dockerSetup } from './docker-setup';
|
|
@@ -10,9 +10,10 @@ const PLUGIN_ROOT = join(dirname(new URL(import.meta.url).pathname), '..');
|
|
|
10
10
|
|
|
11
11
|
export function buildDashboard(): void {
|
|
12
12
|
const dashboardDir = join(PLUGIN_ROOT, 'dashboard');
|
|
13
|
-
const
|
|
13
|
+
const stableDist = DASHBOARD_DIR; // ~/.openclaw/nats-plugin/dashboard/
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// Already installed to stable location
|
|
16
|
+
if (existsSync(join(stableDist, 'index.html'))) {
|
|
16
17
|
console.log('Dashboard already built, skipping.');
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
@@ -23,8 +24,23 @@ export function buildDashboard(): void {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
console.log('Building dashboard...');
|
|
26
|
-
execFileSync('bun', ['
|
|
27
|
-
|
|
27
|
+
const hasBun = (() => { try { execFileSync('bun', ['--version'], { stdio: 'pipe' }); return true; } catch { return false; } })();
|
|
28
|
+
if (hasBun) {
|
|
29
|
+
execFileSync('bun', ['install', '--frozen-lockfile'], { cwd: dashboardDir, stdio: 'inherit' });
|
|
30
|
+
execFileSync('bun', ['run', 'build'], { cwd: dashboardDir, stdio: 'inherit' });
|
|
31
|
+
} else {
|
|
32
|
+
execFileSync('npm', ['install'], { cwd: dashboardDir, stdio: 'inherit' });
|
|
33
|
+
execFileSync('npx', ['vite', 'build'], { cwd: dashboardDir, stdio: 'inherit' });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Copy built dist to stable location so the plugin can find it at runtime
|
|
37
|
+
const builtDist = join(dashboardDir, 'dist');
|
|
38
|
+
if (existsSync(builtDist)) {
|
|
39
|
+
mkdirSync(stableDist, { recursive: true });
|
|
40
|
+
cpSync(builtDist, stableDist, { recursive: true });
|
|
41
|
+
console.log(`Dashboard installed to ${stableDist}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
console.log('Dashboard built successfully.\n');
|
|
29
45
|
}
|
|
30
46
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
3
5
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
4
6
|
|
|
5
7
|
const ROUTE_PREFIX = '/nats-dashboard';
|
|
6
|
-
const DIST_DIR = path.resolve(__dirname, '../../dashboard/dist');
|
|
7
8
|
const SIDECAR_URL = process.env.NATS_SIDECAR_URL || 'http://127.0.0.1:3104';
|
|
8
9
|
const API_KEY = process.env.NATS_PLUGIN_API_KEY || 'dev-nats-plugin-key';
|
|
9
10
|
|
|
11
|
+
// Stable location (copied during setup) takes priority over in-package dist
|
|
12
|
+
const STABLE_DIST = path.join(homedir(), '.openclaw', 'nats-plugin', 'dashboard');
|
|
13
|
+
const PACKAGE_DIST = path.resolve(__dirname, '../../dashboard/dist');
|
|
14
|
+
const DIST_DIR = existsSync(path.join(STABLE_DIST, 'index.html')) ? STABLE_DIST : PACKAGE_DIST;
|
|
15
|
+
|
|
10
16
|
const MIME_TYPES: Record<string, string> = {
|
|
11
17
|
'.html': 'text/html; charset=utf-8',
|
|
12
18
|
'.js': 'application/javascript; charset=utf-8',
|
|
@@ -124,7 +130,7 @@ async function serveStatic(subPath: string, res: ServerResponse): Promise<boolea
|
|
|
124
130
|
res.end(indexHtml);
|
|
125
131
|
} catch {
|
|
126
132
|
res.statusCode = 404;
|
|
127
|
-
res.end('Dashboard not built. Run:
|
|
133
|
+
res.end('Dashboard not built. Run: npx @omnixal/openclaw-nats-plugin setup');
|
|
128
134
|
}
|
|
129
135
|
}
|
|
130
136
|
return true;
|