@karmaniverous/jeeves-watcher-openclaw 0.3.6 → 0.3.8
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/dist/cli.js +44 -8
- package/dist/index.js +60 -25
- package/dist/src/cli.d.ts +11 -2
- package/dist/src/helpers.d.ts +12 -1
- package/dist/src/memoryTools.d.ts +8 -0
- package/openclaw.plugin.json +1 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8,9 +8,13 @@ import { fileURLToPath } from 'url';
|
|
|
8
8
|
* CLI for installing/uninstalling the jeeves-watcher OpenClaw plugin.
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
|
-
* npx \@karmaniverous/jeeves-watcher-openclaw install
|
|
11
|
+
* npx \@karmaniverous/jeeves-watcher-openclaw install [--memory]
|
|
12
12
|
* npx \@karmaniverous/jeeves-watcher-openclaw uninstall
|
|
13
13
|
*
|
|
14
|
+
* The --memory flag claims the OpenClaw memory slot, replacing memory-core
|
|
15
|
+
* with the plugin's Qdrant-backed memory_search and memory_get tools.
|
|
16
|
+
* Without --memory, only watcher admin tools are registered.
|
|
17
|
+
*
|
|
14
18
|
* Bypasses OpenClaw's `plugins install` command, which has a known
|
|
15
19
|
* spawn EINVAL bug on Windows (https://github.com/openclaw/openclaw/issues/9224).
|
|
16
20
|
*
|
|
@@ -79,7 +83,7 @@ function patchAllowList(parent, key, label, mode) {
|
|
|
79
83
|
return undefined;
|
|
80
84
|
}
|
|
81
85
|
/** Patch OpenClaw config for install or uninstall. Returns log messages. */
|
|
82
|
-
function patchConfig(config, mode) {
|
|
86
|
+
function patchConfig(config, mode, options = {}) {
|
|
83
87
|
const messages = [];
|
|
84
88
|
// Ensure plugins section
|
|
85
89
|
if (!config.plugins || typeof config.plugins !== 'object') {
|
|
@@ -110,13 +114,20 @@ function patchConfig(config, mode) {
|
|
|
110
114
|
plugins.slots = {};
|
|
111
115
|
}
|
|
112
116
|
const slots = plugins.slots;
|
|
113
|
-
if (mode === 'add') {
|
|
117
|
+
if (mode === 'add' && options.memory) {
|
|
114
118
|
const prev = slots.memory;
|
|
115
119
|
slots.memory = PLUGIN_ID;
|
|
116
120
|
if (prev !== PLUGIN_ID) {
|
|
117
121
|
messages.push(`Set plugins.slots.memory to "${PLUGIN_ID}"${prev ? ` (was "${prev}")` : ''}`);
|
|
118
122
|
}
|
|
119
123
|
}
|
|
124
|
+
else if (mode === 'add' && !options.memory) {
|
|
125
|
+
// Non-memory install: revert slot if we held it
|
|
126
|
+
if (slots.memory === PLUGIN_ID) {
|
|
127
|
+
slots.memory = 'memory-core';
|
|
128
|
+
messages.push(`Reverted plugins.slots.memory to "memory-core" (non-memory install)`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
120
131
|
else if (slots.memory === PLUGIN_ID) {
|
|
121
132
|
slots.memory = 'memory-core';
|
|
122
133
|
messages.push(`Reverted plugins.slots.memory to "memory-core"`);
|
|
@@ -129,7 +140,7 @@ function patchConfig(config, mode) {
|
|
|
129
140
|
return messages;
|
|
130
141
|
}
|
|
131
142
|
/** Install the plugin into OpenClaw's extensions directory. */
|
|
132
|
-
function install() {
|
|
143
|
+
function install(memoryMode) {
|
|
133
144
|
const home = resolveOpenClawHome();
|
|
134
145
|
const configPath = resolveConfigPath(home);
|
|
135
146
|
const extDir = join(home, 'extensions', PLUGIN_ID);
|
|
@@ -138,6 +149,7 @@ function install() {
|
|
|
138
149
|
console.log(`Config: ${configPath}`);
|
|
139
150
|
console.log(`Extensions dir: ${extDir}`);
|
|
140
151
|
console.log(`Package root: ${pkgRoot}`);
|
|
152
|
+
console.log(`Memory mode: ${memoryMode ? 'yes (claiming memory slot)' : 'no (watcher tools only)'}`);
|
|
141
153
|
console.log();
|
|
142
154
|
if (!existsSync(home)) {
|
|
143
155
|
console.error(`Error: OpenClaw home directory not found at ${home}`);
|
|
@@ -173,6 +185,20 @@ function install() {
|
|
|
173
185
|
cpSync(nodeModulesSrc, join(extDir, 'node_modules'), { recursive: true });
|
|
174
186
|
console.log(' ✓ node_modules');
|
|
175
187
|
}
|
|
188
|
+
// Patch manifest based on memory mode
|
|
189
|
+
const installedManifestPath = join(extDir, 'openclaw.plugin.json');
|
|
190
|
+
const manifest = readJson(installedManifestPath);
|
|
191
|
+
if (manifest) {
|
|
192
|
+
if (memoryMode) {
|
|
193
|
+
manifest.kind = 'memory';
|
|
194
|
+
console.log(' ✓ Set kind: "memory" in manifest');
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
delete manifest.kind;
|
|
198
|
+
console.log(' ✓ Removed kind from manifest (non-memory mode)');
|
|
199
|
+
}
|
|
200
|
+
writeJson(installedManifestPath, manifest);
|
|
201
|
+
}
|
|
176
202
|
// Patch config
|
|
177
203
|
console.log();
|
|
178
204
|
console.log('Patching OpenClaw config...');
|
|
@@ -181,13 +207,19 @@ function install() {
|
|
|
181
207
|
console.error(`Error: Could not parse ${configPath}`);
|
|
182
208
|
process.exit(1);
|
|
183
209
|
}
|
|
184
|
-
for (const msg of patchConfig(config, 'add')) {
|
|
210
|
+
for (const msg of patchConfig(config, 'add', { memory: memoryMode })) {
|
|
185
211
|
console.log(` ✓ ${msg}`);
|
|
186
212
|
}
|
|
187
213
|
writeJson(configPath, config);
|
|
188
214
|
console.log();
|
|
189
215
|
console.log('✅ Plugin installed successfully.');
|
|
190
216
|
console.log(' Restart the OpenClaw gateway to load the plugin.');
|
|
217
|
+
if (memoryMode) {
|
|
218
|
+
console.log(' Memory slot claimed — memory_search and memory_get tools will be available.');
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
console.log(' Watcher tools available. Run with --memory after bootstrapping to enable memory features.');
|
|
222
|
+
}
|
|
191
223
|
}
|
|
192
224
|
/** Uninstall the plugin from OpenClaw's extensions directory. */
|
|
193
225
|
function uninstall() {
|
|
@@ -221,9 +253,10 @@ function uninstall() {
|
|
|
221
253
|
}
|
|
222
254
|
// Main
|
|
223
255
|
const command = process.argv[2];
|
|
256
|
+
const memoryFlag = process.argv.includes('--memory');
|
|
224
257
|
switch (command) {
|
|
225
258
|
case 'install':
|
|
226
|
-
install();
|
|
259
|
+
install(memoryFlag);
|
|
227
260
|
break;
|
|
228
261
|
case 'uninstall':
|
|
229
262
|
uninstall();
|
|
@@ -232,8 +265,11 @@ switch (command) {
|
|
|
232
265
|
console.log(`@karmaniverous/jeeves-watcher-openclaw — OpenClaw plugin installer`);
|
|
233
266
|
console.log();
|
|
234
267
|
console.log('Usage:');
|
|
235
|
-
console.log(' npx @karmaniverous/jeeves-watcher-openclaw install
|
|
236
|
-
console.log(' npx @karmaniverous/jeeves-watcher-openclaw uninstall
|
|
268
|
+
console.log(' npx @karmaniverous/jeeves-watcher-openclaw install [--memory] Install plugin');
|
|
269
|
+
console.log(' npx @karmaniverous/jeeves-watcher-openclaw uninstall Remove plugin');
|
|
270
|
+
console.log();
|
|
271
|
+
console.log('Options:');
|
|
272
|
+
console.log(' --memory Claim memory slot (replaces memory-core with Qdrant-backed search)');
|
|
237
273
|
console.log();
|
|
238
274
|
console.log('Environment variables:');
|
|
239
275
|
console.log(' OPENCLAW_CONFIG Path to openclaw.json (overrides all)');
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ function normalizePath(p) {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Resolve the workspace path from gateway config.
|
|
18
|
-
* Priority: agent-specific
|
|
18
|
+
* Priority: agent-specific \> defaults \> fallback (~/.openclaw/workspace).
|
|
19
19
|
*/
|
|
20
20
|
function getWorkspacePath(api) {
|
|
21
21
|
const agentWorkspace = api.config?.agents?.entries?.['main']?.workspace ??
|
|
@@ -27,6 +27,26 @@ function getApiUrl(api) {
|
|
|
27
27
|
const url = api.config?.plugins?.entries?.['jeeves-watcher-openclaw']?.config?.apiUrl;
|
|
28
28
|
return typeof url === 'string' ? url : DEFAULT_API_URL;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve user-supplied schemas from plugin config.
|
|
32
|
+
* Returns a map of rule name → schema array (always normalized to array).
|
|
33
|
+
*/
|
|
34
|
+
function getPluginSchemas(api) {
|
|
35
|
+
const config = api.config?.plugins?.entries?.['jeeves-watcher-openclaw']?.config;
|
|
36
|
+
const raw = config?.schemas;
|
|
37
|
+
if (!raw || typeof raw !== 'object')
|
|
38
|
+
return {};
|
|
39
|
+
const result = {};
|
|
40
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
41
|
+
if (Array.isArray(value)) {
|
|
42
|
+
result[name] = value;
|
|
43
|
+
}
|
|
44
|
+
else if (typeof value === 'object' || typeof value === 'string') {
|
|
45
|
+
result[name] = [value];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
30
50
|
/** Format a successful tool result. */
|
|
31
51
|
function ok(data) {
|
|
32
52
|
return {
|
|
@@ -90,12 +110,42 @@ async function postJson(url, body) {
|
|
|
90
110
|
* memory_search call. Re-attempts on failure. memory_get reads files
|
|
91
111
|
* directly from the filesystem with path validation.
|
|
92
112
|
*/
|
|
93
|
-
/**
|
|
94
|
-
|
|
113
|
+
/** Private property prefix — namespaces plugin metadata to avoid collisions. */
|
|
114
|
+
const PROP_PREFIX = '_jeeves_watcher_openclaw_';
|
|
115
|
+
/** Private property keys used by the plugin for filtering. */
|
|
116
|
+
const PROP_SOURCE = `${PROP_PREFIX}source_`;
|
|
117
|
+
const PROP_KIND = `${PROP_PREFIX}kind_`;
|
|
118
|
+
/** Memory source value for filter queries. */
|
|
119
|
+
const SOURCE_MEMORY = 'memory';
|
|
120
|
+
/** Virtual rule names (exported for testing and config reference). */
|
|
121
|
+
const RULE_LONGTERM = 'openclaw-memory-longterm';
|
|
122
|
+
const RULE_DAILY = 'openclaw-memory-daily';
|
|
123
|
+
/**
|
|
124
|
+
* Build virtual inference rules for a workspace path.
|
|
125
|
+
*
|
|
126
|
+
* Each rule's schema is composed of:
|
|
127
|
+
* 1. Plugin-internal schema (private namespaced properties, no uiHint)
|
|
128
|
+
* 2. User-supplied schemas from plugin config (optional, owner-controlled)
|
|
129
|
+
*/
|
|
130
|
+
function buildVirtualRules(workspace, userSchemas) {
|
|
95
131
|
const ws = normalizePath(workspace);
|
|
132
|
+
const longtermInternal = {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
[PROP_SOURCE]: { type: 'string', set: SOURCE_MEMORY },
|
|
136
|
+
[PROP_KIND]: { type: 'string', set: 'long-term' },
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
const dailyInternal = {
|
|
140
|
+
type: 'object',
|
|
141
|
+
properties: {
|
|
142
|
+
[PROP_SOURCE]: { type: 'string', set: SOURCE_MEMORY },
|
|
143
|
+
[PROP_KIND]: { type: 'string', set: 'daily-log' },
|
|
144
|
+
},
|
|
145
|
+
};
|
|
96
146
|
return [
|
|
97
147
|
{
|
|
98
|
-
name:
|
|
148
|
+
name: RULE_LONGTERM,
|
|
99
149
|
description: 'OpenClaw long-term memory file',
|
|
100
150
|
match: {
|
|
101
151
|
properties: {
|
|
@@ -106,18 +156,10 @@ function buildVirtualRules(workspace) {
|
|
|
106
156
|
},
|
|
107
157
|
},
|
|
108
158
|
},
|
|
109
|
-
schema: [
|
|
110
|
-
{
|
|
111
|
-
type: 'object',
|
|
112
|
-
properties: {
|
|
113
|
-
domain: { type: 'string', set: 'memory' },
|
|
114
|
-
kind: { type: 'string', set: 'long-term' },
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
],
|
|
159
|
+
schema: [longtermInternal, ...(userSchemas[RULE_LONGTERM] ?? [])],
|
|
118
160
|
},
|
|
119
161
|
{
|
|
120
|
-
name:
|
|
162
|
+
name: RULE_DAILY,
|
|
121
163
|
description: 'OpenClaw daily memory logs',
|
|
122
164
|
match: {
|
|
123
165
|
properties: {
|
|
@@ -128,15 +170,7 @@ function buildVirtualRules(workspace) {
|
|
|
128
170
|
},
|
|
129
171
|
},
|
|
130
172
|
},
|
|
131
|
-
schema: [
|
|
132
|
-
{
|
|
133
|
-
type: 'object',
|
|
134
|
-
properties: {
|
|
135
|
-
domain: { type: 'string', set: 'memory' },
|
|
136
|
-
kind: { type: 'string', set: 'daily-log' },
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
],
|
|
173
|
+
schema: [dailyInternal, ...(userSchemas[RULE_DAILY] ?? [])],
|
|
140
174
|
},
|
|
141
175
|
];
|
|
142
176
|
}
|
|
@@ -158,6 +192,7 @@ function isAllowedMemoryPath(filePath, workspace) {
|
|
|
158
192
|
*/
|
|
159
193
|
function createMemoryTools(api, baseUrl) {
|
|
160
194
|
const workspace = getWorkspacePath(api);
|
|
195
|
+
const userSchemas = getPluginSchemas(api);
|
|
161
196
|
const state = {
|
|
162
197
|
initialized: false,
|
|
163
198
|
lastWatcherUptime: 0,
|
|
@@ -180,7 +215,7 @@ function createMemoryTools(api, baseUrl) {
|
|
|
180
215
|
body: JSON.stringify({ source: PLUGIN_SOURCE }),
|
|
181
216
|
});
|
|
182
217
|
// Register virtual rules
|
|
183
|
-
const virtualRules = buildVirtualRules(state.workspace);
|
|
218
|
+
const virtualRules = buildVirtualRules(state.workspace, userSchemas);
|
|
184
219
|
await postJson(`${state.baseUrl}/rules/register`, {
|
|
185
220
|
source: PLUGIN_SOURCE,
|
|
186
221
|
rules: virtualRules,
|
|
@@ -208,7 +243,7 @@ function createMemoryTools(api, baseUrl) {
|
|
|
208
243
|
const body = {
|
|
209
244
|
query: params.query,
|
|
210
245
|
filter: {
|
|
211
|
-
must: [{ key:
|
|
246
|
+
must: [{ key: PROP_SOURCE, match: { value: SOURCE_MEMORY } }],
|
|
212
247
|
},
|
|
213
248
|
};
|
|
214
249
|
if (params.maxResults !== undefined)
|
package/dist/src/cli.d.ts
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* CLI for installing/uninstalling the jeeves-watcher OpenClaw plugin.
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
* npx \@karmaniverous/jeeves-watcher-openclaw install
|
|
5
|
+
* npx \@karmaniverous/jeeves-watcher-openclaw install [--memory]
|
|
6
6
|
* npx \@karmaniverous/jeeves-watcher-openclaw uninstall
|
|
7
7
|
*
|
|
8
|
+
* The --memory flag claims the OpenClaw memory slot, replacing memory-core
|
|
9
|
+
* with the plugin's Qdrant-backed memory_search and memory_get tools.
|
|
10
|
+
* Without --memory, only watcher admin tools are registered.
|
|
11
|
+
*
|
|
8
12
|
* Bypasses OpenClaw's `plugins install` command, which has a known
|
|
9
13
|
* spawn EINVAL bug on Windows (https://github.com/openclaw/openclaw/issues/9224).
|
|
10
14
|
*
|
|
@@ -13,5 +17,10 @@
|
|
|
13
17
|
* - OPENCLAW_HOME env var (path to .openclaw directory)
|
|
14
18
|
* - Default: ~/.openclaw/openclaw.json
|
|
15
19
|
*/
|
|
20
|
+
/** Options for patchConfig. */
|
|
21
|
+
export interface PatchConfigOptions {
|
|
22
|
+
/** Whether to claim the memory slot (--memory flag). */
|
|
23
|
+
memory?: boolean;
|
|
24
|
+
}
|
|
16
25
|
/** Patch OpenClaw config for install or uninstall. Returns log messages. */
|
|
17
|
-
export declare function patchConfig(config: Record<string, unknown>, mode: 'add' | 'remove'): string[];
|
|
26
|
+
export declare function patchConfig(config: Record<string, unknown>, mode: 'add' | 'remove', options?: PatchConfigOptions): string[];
|
package/dist/src/helpers.d.ts
CHANGED
|
@@ -42,11 +42,22 @@ export declare const PLUGIN_SOURCE = "jeeves-watcher-openclaw";
|
|
|
42
42
|
export declare function normalizePath(p: string): string;
|
|
43
43
|
/**
|
|
44
44
|
* Resolve the workspace path from gateway config.
|
|
45
|
-
* Priority: agent-specific
|
|
45
|
+
* Priority: agent-specific \> defaults \> fallback (~/.openclaw/workspace).
|
|
46
46
|
*/
|
|
47
47
|
export declare function getWorkspacePath(api: PluginApi): string;
|
|
48
48
|
/** Resolve the watcher API base URL from plugin config. */
|
|
49
49
|
export declare function getApiUrl(api: PluginApi): string;
|
|
50
|
+
/**
|
|
51
|
+
* Schema value type — matches watcher inference rule schema conventions.
|
|
52
|
+
* Can be an inline JSON Schema object, a file reference string,
|
|
53
|
+
* a named schema reference, or a composable array of these.
|
|
54
|
+
*/
|
|
55
|
+
export type SchemaValue = Record<string, unknown> | string | Array<Record<string, unknown> | string>;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve user-supplied schemas from plugin config.
|
|
58
|
+
* Returns a map of rule name → schema array (always normalized to array).
|
|
59
|
+
*/
|
|
60
|
+
export declare function getPluginSchemas(api: PluginApi): Record<string, Array<Record<string, unknown> | string>>;
|
|
50
61
|
/** Format a successful tool result. */
|
|
51
62
|
export declare function ok(data: unknown): ToolResult;
|
|
52
63
|
/** Format an error tool result. */
|
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
* directly from the filesystem with path validation.
|
|
8
8
|
*/
|
|
9
9
|
import { type PluginApi, type ToolResult } from './helpers.js';
|
|
10
|
+
/** Private property keys used by the plugin for filtering. */
|
|
11
|
+
export declare const PROP_SOURCE = "_jeeves_watcher_openclaw_source_";
|
|
12
|
+
export declare const PROP_KIND = "_jeeves_watcher_openclaw_kind_";
|
|
13
|
+
/** Memory source value for filter queries. */
|
|
14
|
+
export declare const SOURCE_MEMORY = "memory";
|
|
15
|
+
/** Virtual rule names (exported for testing and config reference). */
|
|
16
|
+
export declare const RULE_LONGTERM = "openclaw-memory-longterm";
|
|
17
|
+
export declare const RULE_DAILY = "openclaw-memory-daily";
|
|
10
18
|
/**
|
|
11
19
|
* Create memory tool registrations for the plugin.
|
|
12
20
|
* Returns register functions for memory_search and memory_get.
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
"id": "jeeves-watcher-openclaw",
|
|
3
3
|
"name": "Jeeves Watcher",
|
|
4
4
|
"description": "Semantic search, metadata enrichment, and instance administration for a jeeves-watcher deployment.",
|
|
5
|
-
"version": "0.3.
|
|
6
|
-
"kind": "memory",
|
|
5
|
+
"version": "0.3.8",
|
|
7
6
|
"skills": [
|
|
8
7
|
"dist/skills/jeeves-watcher"
|
|
9
8
|
],
|
package/package.json
CHANGED