jasper-recall 0.5.11 → 0.6.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/cli/jasper-recall.js +276 -0
- package/package.json +1 -1
package/cli/jasper-recall.js
CHANGED
|
@@ -29,6 +29,10 @@ const SCRIPTS_DIR = path.join(__dirname, '..', 'scripts');
|
|
|
29
29
|
const EXTENSIONS_DIR = path.join(__dirname, '..', 'extensions');
|
|
30
30
|
const OPENCLAW_CONFIG = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
31
31
|
const OPENCLAW_SKILLS = path.join(os.homedir(), '.openclaw', 'workspace', 'skills');
|
|
32
|
+
const BRAIN_PATH = path.join(os.homedir(), '.openclaw', 'brain');
|
|
33
|
+
const BRAIN_CONFIG = path.join(os.homedir(), '.jasper-recall', 'brain.json');
|
|
34
|
+
const DEFAULT_BRAIN_PORT = 8787;
|
|
35
|
+
const DEFAULT_BRAIN_HOST = '127.0.0.1';
|
|
32
36
|
|
|
33
37
|
function log(msg) {
|
|
34
38
|
console.log(`🦊 ${msg}`);
|
|
@@ -137,6 +141,272 @@ function setupOpenClawIntegration() {
|
|
|
137
141
|
return true;
|
|
138
142
|
}
|
|
139
143
|
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Brain (Quartz) Setup - Optional web UI for memory browsing
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
function getBrainConfig() {
|
|
149
|
+
const configDir = path.dirname(BRAIN_CONFIG);
|
|
150
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
151
|
+
|
|
152
|
+
if (fs.existsSync(BRAIN_CONFIG)) {
|
|
153
|
+
try {
|
|
154
|
+
return JSON.parse(fs.readFileSync(BRAIN_CONFIG, 'utf8'));
|
|
155
|
+
} catch {
|
|
156
|
+
return {};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function saveBrainConfig(config) {
|
|
163
|
+
const configDir = path.dirname(BRAIN_CONFIG);
|
|
164
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
165
|
+
fs.writeFileSync(BRAIN_CONFIG, JSON.stringify(config, null, 2));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function setupBrain(options = {}) {
|
|
169
|
+
const port = options.port || DEFAULT_BRAIN_PORT;
|
|
170
|
+
const host = options.host || DEFAULT_BRAIN_HOST;
|
|
171
|
+
|
|
172
|
+
log('Setting up Jasper Brain (Quartz knowledge base)...');
|
|
173
|
+
console.log('');
|
|
174
|
+
|
|
175
|
+
// Check for Node.js and npm
|
|
176
|
+
try {
|
|
177
|
+
execSync('npx --version', { stdio: 'pipe' });
|
|
178
|
+
} catch {
|
|
179
|
+
error('npx not found. Node.js is required for Quartz.');
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Check if Quartz is already installed
|
|
184
|
+
if (fs.existsSync(BRAIN_PATH) && fs.existsSync(path.join(BRAIN_PATH, 'quartz.config.ts'))) {
|
|
185
|
+
console.log(` ✓ Quartz already installed at ${BRAIN_PATH}`);
|
|
186
|
+
} else {
|
|
187
|
+
log('Cloning Quartz...');
|
|
188
|
+
fs.mkdirSync(path.dirname(BRAIN_PATH), { recursive: true });
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
execSync(`git clone https://github.com/jackyzha0/quartz.git "${BRAIN_PATH}"`, {
|
|
192
|
+
stdio: 'inherit',
|
|
193
|
+
timeout: 120000
|
|
194
|
+
});
|
|
195
|
+
console.log(` ✓ Cloned Quartz to ${BRAIN_PATH}`);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
error(`Failed to clone Quartz: ${err.message}`);
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Install dependencies
|
|
202
|
+
log('Installing Quartz dependencies...');
|
|
203
|
+
try {
|
|
204
|
+
execSync('npm install', { cwd: BRAIN_PATH, stdio: 'inherit', timeout: 180000 });
|
|
205
|
+
console.log(' ✓ Dependencies installed');
|
|
206
|
+
} catch (err) {
|
|
207
|
+
error(`Failed to install dependencies: ${err.message}`);
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Link memory folder to Quartz content
|
|
213
|
+
const contentPath = path.join(BRAIN_PATH, 'content');
|
|
214
|
+
const memoryPath = path.join(os.homedir(), '.openclaw', 'workspace', 'memory');
|
|
215
|
+
|
|
216
|
+
if (fs.existsSync(memoryPath)) {
|
|
217
|
+
// Remove default content and symlink memory
|
|
218
|
+
if (fs.existsSync(contentPath)) {
|
|
219
|
+
const stats = fs.lstatSync(contentPath);
|
|
220
|
+
if (stats.isSymbolicLink()) {
|
|
221
|
+
console.log(` ✓ Memory already linked: ${contentPath} -> ${memoryPath}`);
|
|
222
|
+
} else {
|
|
223
|
+
// Backup and replace
|
|
224
|
+
const backupPath = contentPath + '.backup';
|
|
225
|
+
if (!fs.existsSync(backupPath)) {
|
|
226
|
+
fs.renameSync(contentPath, backupPath);
|
|
227
|
+
} else {
|
|
228
|
+
fs.rmSync(contentPath, { recursive: true });
|
|
229
|
+
}
|
|
230
|
+
fs.symlinkSync(memoryPath, contentPath);
|
|
231
|
+
console.log(` ✓ Linked memory to Quartz: ${memoryPath}`);
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
fs.symlinkSync(memoryPath, contentPath);
|
|
235
|
+
console.log(` ✓ Linked memory to Quartz: ${memoryPath}`);
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
console.log(` ⚠ Memory folder not found: ${memoryPath}`);
|
|
239
|
+
console.log(' Create it with: mkdir -p ~/.openclaw/workspace/memory');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Save config
|
|
243
|
+
const config = getBrainConfig();
|
|
244
|
+
config.path = BRAIN_PATH;
|
|
245
|
+
config.port = port;
|
|
246
|
+
config.host = host;
|
|
247
|
+
config.contentPath = memoryPath;
|
|
248
|
+
saveBrainConfig(config);
|
|
249
|
+
|
|
250
|
+
// Create rebuild-brain script
|
|
251
|
+
const rebuildScript = path.join(BIN_PATH, 'rebuild-brain');
|
|
252
|
+
const rebuildContent = `#!/bin/bash
|
|
253
|
+
# Rebuild Jasper Brain (Quartz static site)
|
|
254
|
+
cd "${BRAIN_PATH}" && npx quartz build
|
|
255
|
+
`;
|
|
256
|
+
fs.writeFileSync(rebuildScript, rebuildContent);
|
|
257
|
+
fs.chmodSync(rebuildScript, 0o755);
|
|
258
|
+
console.log(` ✓ Created: ${rebuildScript}`);
|
|
259
|
+
|
|
260
|
+
// Create serve-brain script
|
|
261
|
+
const serveScript = path.join(BIN_PATH, 'serve-brain');
|
|
262
|
+
const serveContent = `#!/bin/bash
|
|
263
|
+
# Start Jasper Brain web server
|
|
264
|
+
cd "${BRAIN_PATH}" && npx quartz build --serve --port ${port} --host ${host}
|
|
265
|
+
`;
|
|
266
|
+
fs.writeFileSync(serveScript, serveContent);
|
|
267
|
+
fs.chmodSync(serveScript, 0o755);
|
|
268
|
+
console.log(` ✓ Created: ${serveScript}`);
|
|
269
|
+
|
|
270
|
+
console.log('');
|
|
271
|
+
log('Brain setup complete!');
|
|
272
|
+
console.log('');
|
|
273
|
+
console.log('Commands:');
|
|
274
|
+
console.log(' rebuild-brain # Build static site from memory files');
|
|
275
|
+
console.log(' serve-brain # Start web server');
|
|
276
|
+
console.log('');
|
|
277
|
+
console.log(`Server will run at: http://${host}:${port}`);
|
|
278
|
+
console.log('');
|
|
279
|
+
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function brainStatus() {
|
|
284
|
+
const config = getBrainConfig();
|
|
285
|
+
|
|
286
|
+
console.log('🧠 Jasper Brain Status');
|
|
287
|
+
console.log('=' .repeat(40));
|
|
288
|
+
|
|
289
|
+
if (!config.path || !fs.existsSync(config.path)) {
|
|
290
|
+
console.log('Status: Not installed');
|
|
291
|
+
console.log('');
|
|
292
|
+
console.log('Run: npx jasper-recall brain setup');
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
console.log(`Path: ${config.path}`);
|
|
297
|
+
console.log(`Port: ${config.port || DEFAULT_BRAIN_PORT}`);
|
|
298
|
+
console.log(`Host: ${config.host || DEFAULT_BRAIN_HOST}`);
|
|
299
|
+
console.log(`Content: ${config.contentPath || 'not linked'}`);
|
|
300
|
+
console.log('');
|
|
301
|
+
|
|
302
|
+
// Check if server is running
|
|
303
|
+
try {
|
|
304
|
+
const host = config.host || DEFAULT_BRAIN_HOST;
|
|
305
|
+
const port = config.port || DEFAULT_BRAIN_PORT;
|
|
306
|
+
execSync(`curl -s -o /dev/null -w "%{http_code}" http://${host}:${port}/ | grep -q 200`, { stdio: 'pipe' });
|
|
307
|
+
console.log(`Server: ✅ Running at http://${host}:${port}`);
|
|
308
|
+
} catch {
|
|
309
|
+
console.log('Server: ❌ Not running');
|
|
310
|
+
console.log(' Start with: serve-brain');
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function brainCommand(args) {
|
|
315
|
+
const subcommand = args[0];
|
|
316
|
+
|
|
317
|
+
switch (subcommand) {
|
|
318
|
+
case 'setup':
|
|
319
|
+
case 'install': {
|
|
320
|
+
const portIdx = args.indexOf('--port');
|
|
321
|
+
const hostIdx = args.indexOf('--host');
|
|
322
|
+
const options = {
|
|
323
|
+
port: portIdx !== -1 ? parseInt(args[portIdx + 1], 10) : DEFAULT_BRAIN_PORT,
|
|
324
|
+
host: hostIdx !== -1 ? args[hostIdx + 1] : DEFAULT_BRAIN_HOST
|
|
325
|
+
};
|
|
326
|
+
setupBrain(options);
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
case 'status':
|
|
330
|
+
brainStatus();
|
|
331
|
+
break;
|
|
332
|
+
case 'serve':
|
|
333
|
+
case 'start': {
|
|
334
|
+
const config = getBrainConfig();
|
|
335
|
+
if (!config.path) {
|
|
336
|
+
error('Brain not installed. Run: npx jasper-recall brain setup');
|
|
337
|
+
process.exit(1);
|
|
338
|
+
}
|
|
339
|
+
const port = config.port || DEFAULT_BRAIN_PORT;
|
|
340
|
+
const host = config.host || DEFAULT_BRAIN_HOST;
|
|
341
|
+
console.log(`Starting brain server at http://${host}:${port}...`);
|
|
342
|
+
spawn('npx', ['quartz', 'build', '--serve', '--port', String(port), '--host', host], {
|
|
343
|
+
cwd: config.path,
|
|
344
|
+
stdio: 'inherit'
|
|
345
|
+
});
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
case 'build':
|
|
349
|
+
case 'rebuild': {
|
|
350
|
+
const config = getBrainConfig();
|
|
351
|
+
if (!config.path) {
|
|
352
|
+
error('Brain not installed. Run: npx jasper-recall brain setup');
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
console.log('Building brain...');
|
|
356
|
+
execSync('npx quartz build', { cwd: config.path, stdio: 'inherit' });
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
case 'port': {
|
|
360
|
+
const newPort = parseInt(args[1], 10);
|
|
361
|
+
if (isNaN(newPort)) {
|
|
362
|
+
const config = getBrainConfig();
|
|
363
|
+
console.log(`Current port: ${config.port || DEFAULT_BRAIN_PORT}`);
|
|
364
|
+
} else {
|
|
365
|
+
const config = getBrainConfig();
|
|
366
|
+
config.port = newPort;
|
|
367
|
+
saveBrainConfig(config);
|
|
368
|
+
console.log(`Port set to: ${newPort}`);
|
|
369
|
+
console.log('Restart serve-brain for changes to take effect.');
|
|
370
|
+
}
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
case 'host': {
|
|
374
|
+
const newHost = args[1];
|
|
375
|
+
if (!newHost) {
|
|
376
|
+
const config = getBrainConfig();
|
|
377
|
+
console.log(`Current host: ${config.host || DEFAULT_BRAIN_HOST}`);
|
|
378
|
+
} else {
|
|
379
|
+
const config = getBrainConfig();
|
|
380
|
+
config.host = newHost;
|
|
381
|
+
saveBrainConfig(config);
|
|
382
|
+
console.log(`Host set to: ${newHost}`);
|
|
383
|
+
console.log('Restart serve-brain for changes to take effect.');
|
|
384
|
+
}
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
default:
|
|
388
|
+
console.log(`
|
|
389
|
+
🧠 Jasper Brain - Web UI for your memory
|
|
390
|
+
|
|
391
|
+
USAGE:
|
|
392
|
+
npx jasper-recall brain <command>
|
|
393
|
+
|
|
394
|
+
COMMANDS:
|
|
395
|
+
setup [--port N] [--host H] Install Quartz and link memory
|
|
396
|
+
status Show brain status
|
|
397
|
+
serve Start the web server
|
|
398
|
+
build Rebuild static site
|
|
399
|
+
port [N] Show or set port (default: ${DEFAULT_BRAIN_PORT})
|
|
400
|
+
host [H] Show or set host (default: ${DEFAULT_BRAIN_HOST})
|
|
401
|
+
|
|
402
|
+
EXAMPLES:
|
|
403
|
+
npx jasper-recall brain setup
|
|
404
|
+
npx jasper-recall brain setup --port 8080 --host 0.0.0.0
|
|
405
|
+
npx jasper-recall brain serve
|
|
406
|
+
`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
140
410
|
function setup() {
|
|
141
411
|
log('Jasper Recall — Setup');
|
|
142
412
|
console.log('=' .repeat(40));
|
|
@@ -291,6 +561,8 @@ COMMANDS:
|
|
|
291
561
|
digest Process session logs (alias for digest-sessions)
|
|
292
562
|
summarize Compress old entries to save tokens (alias for summarize-old)
|
|
293
563
|
serve Start HTTP API server (for sandboxed agents)
|
|
564
|
+
brain Manage Quartz web UI for memory browsing
|
|
565
|
+
Subcommands: setup, status, serve, build, port, host
|
|
294
566
|
config Show or set configuration
|
|
295
567
|
update Check for updates
|
|
296
568
|
sandboxed-setup Configure sandboxed agents (email, social, calendar, etc.)
|
|
@@ -414,6 +686,10 @@ switch (command) {
|
|
|
414
686
|
config.show();
|
|
415
687
|
}
|
|
416
688
|
break;
|
|
689
|
+
case 'brain':
|
|
690
|
+
// Quartz knowledge base management
|
|
691
|
+
brainCommand(process.argv.slice(3));
|
|
692
|
+
break;
|
|
417
693
|
case '--version':
|
|
418
694
|
case '-v':
|
|
419
695
|
console.log(VERSION);
|