@karmaniverous/jeeves-watcher-openclaw 0.1.0 → 0.1.2
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 +21 -1
- package/dist/cli.js +236 -0
- package/dist/rollup.config.d.ts +4 -3
- package/dist/src/cli.d.ts +16 -0
- package/openclaw.plugin.json +6 -3
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -6,12 +6,32 @@
|
|
|
6
6
|
|
|
7
7
|
A running [jeeves-watcher](https://www.npmjs.com/package/@karmaniverous/jeeves-watcher) service with its REST API accessible.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
### Standard (OpenClaw CLI)
|
|
10
12
|
|
|
11
13
|
```bash
|
|
12
14
|
openclaw plugins install @karmaniverous/jeeves-watcher-openclaw
|
|
13
15
|
```
|
|
14
16
|
|
|
17
|
+
### Self-Installer (Windows workaround)
|
|
18
|
+
|
|
19
|
+
OpenClaw's `plugins install` command has a known [`spawn EINVAL`](https://github.com/openclaw/openclaw/issues/9224) bug on Windows. This package includes a self-installer that bypasses the issue:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @karmaniverous/jeeves-watcher-openclaw install
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This copies the plugin into OpenClaw's extensions directory and patches the config. To remove:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @karmaniverous/jeeves-watcher-openclaw uninstall
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Non-default installations:** Set `OPENCLAW_CONFIG` (path to `openclaw.json`) or `OPENCLAW_HOME` (path to `.openclaw` directory) if OpenClaw is not installed at the default location.
|
|
32
|
+
|
|
33
|
+
After install or uninstall, restart the OpenClaw gateway to apply changes.
|
|
34
|
+
|
|
15
35
|
## Configuration
|
|
16
36
|
|
|
17
37
|
Set the `apiUrl` in the plugin configuration to point at your jeeves-watcher service:
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, rmSync, mkdirSync, cpSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { join, dirname, resolve } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* CLI for installing/uninstalling the jeeves-watcher OpenClaw plugin.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* npx \@karmaniverous/jeeves-watcher-openclaw install
|
|
12
|
+
* npx \@karmaniverous/jeeves-watcher-openclaw uninstall
|
|
13
|
+
*
|
|
14
|
+
* Bypasses OpenClaw's `plugins install` command, which has a known
|
|
15
|
+
* spawn EINVAL bug on Windows (https://github.com/openclaw/openclaw/issues/9224).
|
|
16
|
+
*
|
|
17
|
+
* Supports non-default installations via:
|
|
18
|
+
* - OPENCLAW_CONFIG env var (path to openclaw.json)
|
|
19
|
+
* - OPENCLAW_HOME env var (path to .openclaw directory)
|
|
20
|
+
* - Default: ~/.openclaw/openclaw.json
|
|
21
|
+
*/
|
|
22
|
+
const PLUGIN_ID = 'jeeves-watcher-openclaw';
|
|
23
|
+
/** Resolve the OpenClaw home directory. */
|
|
24
|
+
function resolveOpenClawHome() {
|
|
25
|
+
// 1. OPENCLAW_CONFIG points directly to the config file
|
|
26
|
+
if (process.env.OPENCLAW_CONFIG) {
|
|
27
|
+
return dirname(resolve(process.env.OPENCLAW_CONFIG));
|
|
28
|
+
}
|
|
29
|
+
// 2. OPENCLAW_HOME points to the .openclaw directory
|
|
30
|
+
if (process.env.OPENCLAW_HOME) {
|
|
31
|
+
return resolve(process.env.OPENCLAW_HOME);
|
|
32
|
+
}
|
|
33
|
+
// 3. Default location
|
|
34
|
+
return join(homedir(), '.openclaw');
|
|
35
|
+
}
|
|
36
|
+
/** Resolve the config file path. */
|
|
37
|
+
function resolveConfigPath(home) {
|
|
38
|
+
if (process.env.OPENCLAW_CONFIG) {
|
|
39
|
+
return resolve(process.env.OPENCLAW_CONFIG);
|
|
40
|
+
}
|
|
41
|
+
return join(home, 'openclaw.json');
|
|
42
|
+
}
|
|
43
|
+
/** Get the package root (where this CLI lives). */
|
|
44
|
+
function getPackageRoot() {
|
|
45
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
46
|
+
// In dist: dist/cli.js → package root is ..
|
|
47
|
+
// In src: src/cli.ts → package root is ..
|
|
48
|
+
return resolve(dirname(thisFile), '..');
|
|
49
|
+
}
|
|
50
|
+
/** Read and parse JSON, returning null on failure. */
|
|
51
|
+
function readJson(path) {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(readFileSync(path, 'utf8'));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Write JSON with 2-space indent + trailing newline. */
|
|
60
|
+
function writeJson(path, data) {
|
|
61
|
+
writeFileSync(path, JSON.stringify(data, null, 2) + '\n');
|
|
62
|
+
}
|
|
63
|
+
/** Install the plugin into OpenClaw's extensions directory. */
|
|
64
|
+
function install() {
|
|
65
|
+
const home = resolveOpenClawHome();
|
|
66
|
+
const configPath = resolveConfigPath(home);
|
|
67
|
+
const extDir = join(home, 'extensions', PLUGIN_ID);
|
|
68
|
+
const pkgRoot = getPackageRoot();
|
|
69
|
+
console.log(`OpenClaw home: ${home}`);
|
|
70
|
+
console.log(`Config: ${configPath}`);
|
|
71
|
+
console.log(`Extensions dir: ${extDir}`);
|
|
72
|
+
console.log(`Package root: ${pkgRoot}`);
|
|
73
|
+
console.log();
|
|
74
|
+
// Validate OpenClaw home exists
|
|
75
|
+
if (!existsSync(home)) {
|
|
76
|
+
console.error(`Error: OpenClaw home directory not found at ${home}`);
|
|
77
|
+
console.error('Set OPENCLAW_HOME or OPENCLAW_CONFIG if using a non-default installation.');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
// Validate config exists
|
|
81
|
+
if (!existsSync(configPath)) {
|
|
82
|
+
console.error(`Error: OpenClaw config not found at ${configPath}`);
|
|
83
|
+
console.error('Set OPENCLAW_CONFIG if using a non-default config location.');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
// Validate package root has openclaw.plugin.json
|
|
87
|
+
const pluginManifestPath = join(pkgRoot, 'openclaw.plugin.json');
|
|
88
|
+
if (!existsSync(pluginManifestPath)) {
|
|
89
|
+
console.error(`Error: openclaw.plugin.json not found at ${pluginManifestPath}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
// Copy package to extensions directory
|
|
93
|
+
console.log('Copying plugin to extensions directory...');
|
|
94
|
+
if (existsSync(extDir)) {
|
|
95
|
+
rmSync(extDir, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
mkdirSync(extDir, { recursive: true });
|
|
98
|
+
// Copy dist/, openclaw.plugin.json, package.json
|
|
99
|
+
const filesToCopy = ['dist', 'openclaw.plugin.json', 'package.json'];
|
|
100
|
+
for (const file of filesToCopy) {
|
|
101
|
+
const src = join(pkgRoot, file);
|
|
102
|
+
const dest = join(extDir, file);
|
|
103
|
+
if (existsSync(src)) {
|
|
104
|
+
cpSync(src, dest, { recursive: true });
|
|
105
|
+
console.log(` ✓ ${file}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Copy node_modules if present (for runtime dependencies)
|
|
109
|
+
const nodeModulesSrc = join(pkgRoot, 'node_modules');
|
|
110
|
+
if (existsSync(nodeModulesSrc)) {
|
|
111
|
+
cpSync(nodeModulesSrc, join(extDir, 'node_modules'), { recursive: true });
|
|
112
|
+
console.log(' ✓ node_modules');
|
|
113
|
+
}
|
|
114
|
+
// Patch OpenClaw config
|
|
115
|
+
console.log();
|
|
116
|
+
console.log('Patching OpenClaw config...');
|
|
117
|
+
const config = readJson(configPath);
|
|
118
|
+
if (!config) {
|
|
119
|
+
console.error(`Error: Could not parse ${configPath}`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
// Ensure plugins section exists
|
|
123
|
+
if (!config.plugins || typeof config.plugins !== 'object') {
|
|
124
|
+
config.plugins = {};
|
|
125
|
+
}
|
|
126
|
+
const plugins = config.plugins;
|
|
127
|
+
// If plugins.allow exists and is populated, add ourselves to it
|
|
128
|
+
if (Array.isArray(plugins.allow) && plugins.allow.length > 0) {
|
|
129
|
+
const allow = plugins.allow;
|
|
130
|
+
if (!allow.includes(PLUGIN_ID)) {
|
|
131
|
+
allow.push(PLUGIN_ID);
|
|
132
|
+
console.log(` ✓ Added "${PLUGIN_ID}" to plugins.allow`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Add to plugins.entries
|
|
136
|
+
if (!plugins.entries || typeof plugins.entries !== 'object') {
|
|
137
|
+
plugins.entries = {};
|
|
138
|
+
}
|
|
139
|
+
const entries = plugins.entries;
|
|
140
|
+
if (!entries[PLUGIN_ID]) {
|
|
141
|
+
entries[PLUGIN_ID] = { enabled: true };
|
|
142
|
+
console.log(` ✓ Added "${PLUGIN_ID}" to plugins.entries`);
|
|
143
|
+
}
|
|
144
|
+
// If tools.allow exists and is populated, add ourselves to it
|
|
145
|
+
const tools = (config.tools ?? {});
|
|
146
|
+
if (Array.isArray(tools.allow) && tools.allow.length > 0) {
|
|
147
|
+
const toolsAllow = tools.allow;
|
|
148
|
+
if (!toolsAllow.includes(PLUGIN_ID)) {
|
|
149
|
+
toolsAllow.push(PLUGIN_ID);
|
|
150
|
+
console.log(` ✓ Added "${PLUGIN_ID}" to tools.allow`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
writeJson(configPath, config);
|
|
154
|
+
console.log();
|
|
155
|
+
console.log('✅ Plugin installed successfully.');
|
|
156
|
+
console.log(' Restart the OpenClaw gateway to load the plugin.');
|
|
157
|
+
}
|
|
158
|
+
/** Uninstall the plugin from OpenClaw's extensions directory. */
|
|
159
|
+
function uninstall() {
|
|
160
|
+
const home = resolveOpenClawHome();
|
|
161
|
+
const configPath = resolveConfigPath(home);
|
|
162
|
+
const extDir = join(home, 'extensions', PLUGIN_ID);
|
|
163
|
+
console.log(`OpenClaw home: ${home}`);
|
|
164
|
+
console.log(`Config: ${configPath}`);
|
|
165
|
+
console.log(`Extensions dir: ${extDir}`);
|
|
166
|
+
console.log();
|
|
167
|
+
// Remove extensions directory
|
|
168
|
+
if (existsSync(extDir)) {
|
|
169
|
+
rmSync(extDir, { recursive: true, force: true });
|
|
170
|
+
console.log(`✓ Removed ${extDir}`);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
console.log(` (extensions directory not found, skipping)`);
|
|
174
|
+
}
|
|
175
|
+
// Patch OpenClaw config
|
|
176
|
+
if (existsSync(configPath)) {
|
|
177
|
+
console.log('Patching OpenClaw config...');
|
|
178
|
+
const config = readJson(configPath);
|
|
179
|
+
if (config) {
|
|
180
|
+
const plugins = (config.plugins ?? {});
|
|
181
|
+
// Remove from plugins.allow if it exists and is populated
|
|
182
|
+
if (Array.isArray(plugins.allow) && plugins.allow.length > 0) {
|
|
183
|
+
plugins.allow = plugins.allow.filter((id) => id !== PLUGIN_ID);
|
|
184
|
+
console.log(` ✓ Removed "${PLUGIN_ID}" from plugins.allow`);
|
|
185
|
+
}
|
|
186
|
+
// Remove from plugins.entries
|
|
187
|
+
if (plugins.entries && typeof plugins.entries === 'object') {
|
|
188
|
+
const entries = plugins.entries;
|
|
189
|
+
if (PLUGIN_ID in entries) {
|
|
190
|
+
Reflect.deleteProperty(entries, PLUGIN_ID);
|
|
191
|
+
console.log(` ✓ Removed "${PLUGIN_ID}" from plugins.entries`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Remove from tools.allow if it exists and is populated
|
|
195
|
+
const tools = (config.tools ?? {});
|
|
196
|
+
if (Array.isArray(tools.allow) && tools.allow.length > 0) {
|
|
197
|
+
tools.allow = tools.allow.filter((id) => id !== PLUGIN_ID);
|
|
198
|
+
console.log(` ✓ Removed "${PLUGIN_ID}" from tools.allow`);
|
|
199
|
+
}
|
|
200
|
+
writeJson(configPath, config);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
console.log();
|
|
204
|
+
console.log('✅ Plugin uninstalled successfully.');
|
|
205
|
+
console.log(' Restart the OpenClaw gateway to complete removal.');
|
|
206
|
+
}
|
|
207
|
+
// Main
|
|
208
|
+
const command = process.argv[2];
|
|
209
|
+
switch (command) {
|
|
210
|
+
case 'install':
|
|
211
|
+
install();
|
|
212
|
+
break;
|
|
213
|
+
case 'uninstall':
|
|
214
|
+
uninstall();
|
|
215
|
+
break;
|
|
216
|
+
default:
|
|
217
|
+
console.log(`@karmaniverous/jeeves-watcher-openclaw — OpenClaw plugin installer`);
|
|
218
|
+
console.log();
|
|
219
|
+
console.log('Usage:');
|
|
220
|
+
console.log(' npx @karmaniverous/jeeves-watcher-openclaw install Install plugin');
|
|
221
|
+
console.log(' npx @karmaniverous/jeeves-watcher-openclaw uninstall Remove plugin');
|
|
222
|
+
console.log();
|
|
223
|
+
console.log('Environment variables:');
|
|
224
|
+
console.log(' OPENCLAW_CONFIG Path to openclaw.json (overrides all)');
|
|
225
|
+
console.log(' OPENCLAW_HOME Path to .openclaw directory');
|
|
226
|
+
console.log();
|
|
227
|
+
console.log('Default: ~/.openclaw/openclaw.json');
|
|
228
|
+
if (command &&
|
|
229
|
+
command !== 'help' &&
|
|
230
|
+
command !== '--help' &&
|
|
231
|
+
command !== '-h') {
|
|
232
|
+
console.error(`\nUnknown command: ${command}`);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
package/dist/rollup.config.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module rollup.config
|
|
3
|
-
* Rollup configuration for the OpenClaw plugin package.
|
|
3
|
+
* Rollup configuration for the OpenClaw plugin package.
|
|
4
|
+
* Two entry points: plugin (ESM + declarations) and CLI (ESM executable).
|
|
4
5
|
*/
|
|
5
6
|
import type { RollupOptions } from 'rollup';
|
|
6
|
-
declare const
|
|
7
|
-
export default
|
|
7
|
+
declare const _default: RollupOptions[];
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI for installing/uninstalling the jeeves-watcher OpenClaw plugin.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npx \@karmaniverous/jeeves-watcher-openclaw install
|
|
6
|
+
* npx \@karmaniverous/jeeves-watcher-openclaw uninstall
|
|
7
|
+
*
|
|
8
|
+
* Bypasses OpenClaw's `plugins install` command, which has a known
|
|
9
|
+
* spawn EINVAL bug on Windows (https://github.com/openclaw/openclaw/issues/9224).
|
|
10
|
+
*
|
|
11
|
+
* Supports non-default installations via:
|
|
12
|
+
* - OPENCLAW_CONFIG env var (path to openclaw.json)
|
|
13
|
+
* - OPENCLAW_HOME env var (path to .openclaw directory)
|
|
14
|
+
* - Default: ~/.openclaw/openclaw.json
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"id": "jeeves-watcher",
|
|
2
|
+
"id": "jeeves-watcher-openclaw",
|
|
3
3
|
"name": "Jeeves Watcher",
|
|
4
4
|
"description": "Semantic search and metadata enrichment via a jeeves-watcher instance.",
|
|
5
|
-
"version": "0.
|
|
6
|
-
"skills": [
|
|
5
|
+
"version": "0.1.2",
|
|
6
|
+
"skills": [
|
|
7
|
+
"dist/skills/jeeves-watcher",
|
|
8
|
+
"dist/skills/jeeves-watcher-admin"
|
|
9
|
+
],
|
|
7
10
|
"configSchema": {
|
|
8
11
|
"type": "object",
|
|
9
12
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@karmaniverous/jeeves-watcher-openclaw",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"author": "Jason Williscroft",
|
|
5
5
|
"description": "OpenClaw plugin for jeeves-watcher — semantic search and metadata enrichment tools",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
|
+
"bin": {
|
|
11
|
+
"jeeves-watcher-openclaw": "./dist/cli.js"
|
|
12
|
+
},
|
|
10
13
|
"exports": {
|
|
11
14
|
".": {
|
|
12
15
|
"import": {
|
|
@@ -17,8 +20,7 @@
|
|
|
17
20
|
},
|
|
18
21
|
"files": [
|
|
19
22
|
"dist",
|
|
20
|
-
"openclaw.plugin.json"
|
|
21
|
-
"dist/skills"
|
|
23
|
+
"openclaw.plugin.json"
|
|
22
24
|
],
|
|
23
25
|
"publishConfig": {
|
|
24
26
|
"access": "public"
|
|
@@ -77,12 +79,16 @@
|
|
|
77
79
|
"git": {
|
|
78
80
|
"changelog": "npx auto-changelog --unreleased-only --stdout --template https://raw.githubusercontent.com/release-it/release-it/main/templates/changelog-compact.hbs",
|
|
79
81
|
"commitMessage": "chore: release @karmaniverous/jeeves-watcher-openclaw v${version}",
|
|
82
|
+
"tagName": "openclaw/${version}",
|
|
80
83
|
"requireBranch": "main"
|
|
81
84
|
},
|
|
82
85
|
"github": {
|
|
83
86
|
"release": true
|
|
84
87
|
},
|
|
85
88
|
"hooks": {
|
|
89
|
+
"after:bump": [
|
|
90
|
+
"node -e \"const f='openclaw.plugin.json';const j=JSON.parse(require('fs').readFileSync(f,'utf8'));j.version='${version}';require('fs').writeFileSync(f,JSON.stringify(j,null,2)+'\\n')\""
|
|
91
|
+
],
|
|
86
92
|
"after:init": [
|
|
87
93
|
"npm run lint",
|
|
88
94
|
"npm run typecheck",
|