jasper-recall 0.4.2 → 0.5.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 +4 -0
- package/extensions/openclaw-plugin/index.ts +155 -13
- package/package.json +1 -1
package/cli/jasper-recall.js
CHANGED
|
@@ -199,6 +199,10 @@ function setup() {
|
|
|
199
199
|
console.log(' 2. recall "query" # Search your memory');
|
|
200
200
|
console.log(' 3. digest-sessions # Process session logs');
|
|
201
201
|
console.log('');
|
|
202
|
+
console.log('🔄 To set up automatic indexing cron jobs:');
|
|
203
|
+
console.log(' Run /jasper-recall setup in your OpenClaw chat');
|
|
204
|
+
console.log(' Then ask your agent to create the cron jobs for you');
|
|
205
|
+
console.log('');
|
|
202
206
|
|
|
203
207
|
// Check for sandboxed agents
|
|
204
208
|
const sandboxedWorkspaces = findSandboxedWorkspaces();
|
|
@@ -81,13 +81,26 @@ export default function register(api: PluginApi) {
|
|
|
81
81
|
// ============================================================================
|
|
82
82
|
|
|
83
83
|
if (autoRecall) {
|
|
84
|
-
api.on('before_agent_start', async (event: {
|
|
84
|
+
api.on('before_agent_start', async (event: {
|
|
85
|
+
prompt?: string;
|
|
86
|
+
senderId?: string;
|
|
87
|
+
source?: string;
|
|
88
|
+
isNewSession?: boolean;
|
|
89
|
+
messageCount?: number;
|
|
90
|
+
context?: { messages?: any[] };
|
|
91
|
+
}) => {
|
|
85
92
|
// Skip if no prompt or too short
|
|
86
93
|
if (!event.prompt || event.prompt.length < 10) {
|
|
87
94
|
return;
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
const prompt = event.prompt;
|
|
98
|
+
|
|
99
|
+
// Detect fresh session (after /new or first message)
|
|
100
|
+
const isFreshSession = event.isNewSession ||
|
|
101
|
+
event.messageCount === 0 ||
|
|
102
|
+
event.messageCount === 1 ||
|
|
103
|
+
(event.context?.messages?.length ?? 0) <= 1;
|
|
91
104
|
|
|
92
105
|
// Skip heartbeats and system prompts
|
|
93
106
|
if (prompt.startsWith('HEARTBEAT') ||
|
|
@@ -116,6 +129,22 @@ export default function register(api: PluginApi) {
|
|
|
116
129
|
}
|
|
117
130
|
|
|
118
131
|
try {
|
|
132
|
+
let prependParts: string[] = [];
|
|
133
|
+
|
|
134
|
+
// If fresh session, remind agent to read identity files
|
|
135
|
+
if (isFreshSession) {
|
|
136
|
+
api.logger.info('[jasper-recall] Fresh session detected - adding identity reminder');
|
|
137
|
+
prependParts.push(`<session-init>
|
|
138
|
+
🔄 **Fresh session detected.** Before responding, read your identity files:
|
|
139
|
+
\`\`\`bash
|
|
140
|
+
cat ~/.openclaw/workspace/IDENTITY.md
|
|
141
|
+
cat ~/.openclaw/workspace/SOUL.md
|
|
142
|
+
cat ~/.openclaw/workspace/USER.md
|
|
143
|
+
\`\`\`
|
|
144
|
+
This ensures you maintain your persona and context after session reset.
|
|
145
|
+
</session-init>`);
|
|
146
|
+
}
|
|
147
|
+
|
|
119
148
|
const results = runRecall(event.prompt, {
|
|
120
149
|
limit: 3,
|
|
121
150
|
json: true,
|
|
@@ -127,23 +156,43 @@ export default function register(api: PluginApi) {
|
|
|
127
156
|
// Filter by minimum score
|
|
128
157
|
const relevant = parsed.filter((r: any) => r.score >= minScore);
|
|
129
158
|
|
|
130
|
-
if (relevant.length
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
159
|
+
if (relevant.length > 0) {
|
|
160
|
+
// Format memories for context injection
|
|
161
|
+
const memoryContext = relevant
|
|
162
|
+
.map((r: any) => `- [${r.source || 'memory'}] ${r.content.slice(0, 500)}${r.content.length > 500 ? '...' : ''}`)
|
|
163
|
+
.join('\n');
|
|
134
164
|
|
|
135
|
-
|
|
136
|
-
const memoryContext = relevant
|
|
137
|
-
.map((r: any) => `- [${r.source || 'memory'}] ${r.content.slice(0, 500)}${r.content.length > 500 ? '...' : ''}`)
|
|
138
|
-
.join('\n');
|
|
165
|
+
api.logger.info(`[jasper-recall] Auto-injecting ${relevant.length} memories into context`);
|
|
139
166
|
|
|
140
|
-
|
|
167
|
+
prependParts.push(`<relevant-memories>
|
|
168
|
+
The following memories may be relevant to this conversation:
|
|
169
|
+
${memoryContext}
|
|
170
|
+
</relevant-memories>`);
|
|
171
|
+
} else {
|
|
172
|
+
api.logger.debug?.('[jasper-recall] No relevant memories found for auto-recall');
|
|
173
|
+
}
|
|
141
174
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
175
|
+
if (prependParts.length > 0) {
|
|
176
|
+
return {
|
|
177
|
+
prependContext: prependParts.join('\n\n'),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
145
180
|
} catch (err: any) {
|
|
146
181
|
api.logger.warn(`[jasper-recall] Auto-recall failed: ${err.message}`);
|
|
182
|
+
|
|
183
|
+
// Still inject identity reminder on fresh session even if recall fails
|
|
184
|
+
if (isFreshSession) {
|
|
185
|
+
return {
|
|
186
|
+
prependContext: `<session-init>
|
|
187
|
+
🔄 **Fresh session detected.** Before responding, read your identity files:
|
|
188
|
+
\`\`\`bash
|
|
189
|
+
cat ~/.openclaw/workspace/IDENTITY.md
|
|
190
|
+
cat ~/.openclaw/workspace/SOUL.md
|
|
191
|
+
cat ~/.openclaw/workspace/USER.md
|
|
192
|
+
\`\`\`
|
|
193
|
+
</session-init>`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
147
196
|
}
|
|
148
197
|
});
|
|
149
198
|
}
|
|
@@ -246,6 +295,99 @@ export default function register(api: PluginApi) {
|
|
|
246
295
|
},
|
|
247
296
|
});
|
|
248
297
|
|
|
298
|
+
// ============================================================================
|
|
299
|
+
// Command: /jasper-recall setup
|
|
300
|
+
// ============================================================================
|
|
301
|
+
|
|
302
|
+
api.registerCommand({
|
|
303
|
+
name: 'jasper-recall',
|
|
304
|
+
description: 'Jasper Recall setup and status',
|
|
305
|
+
acceptsArgs: true,
|
|
306
|
+
requireAuth: true,
|
|
307
|
+
handler: async (ctx: { args?: string }) => {
|
|
308
|
+
const subcommand = ctx.args?.trim().toLowerCase();
|
|
309
|
+
|
|
310
|
+
if (subcommand === 'setup') {
|
|
311
|
+
return {
|
|
312
|
+
text: `🧠 **Jasper Recall Setup**
|
|
313
|
+
|
|
314
|
+
To complete setup, ask me to create these cron jobs:
|
|
315
|
+
|
|
316
|
+
**1. Index memories every 6 hours:**
|
|
317
|
+
\`\`\`
|
|
318
|
+
Create a cron job that runs every 6 hours to index memory files.
|
|
319
|
+
Schedule: "0 */6 * * *"
|
|
320
|
+
Payload: Run index-digests to update the ChromaDB index
|
|
321
|
+
\`\`\`
|
|
322
|
+
|
|
323
|
+
**2. Digest sessions daily at 4am:**
|
|
324
|
+
\`\`\`
|
|
325
|
+
Create a cron job that runs daily at 4am to digest session logs.
|
|
326
|
+
Schedule: "0 4 * * *"
|
|
327
|
+
Payload: Run digest-sessions to extract summaries from recent sessions
|
|
328
|
+
\`\`\`
|
|
329
|
+
|
|
330
|
+
Or just say: **"Set up jasper-recall cron jobs for me"**
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
**Current status:**
|
|
335
|
+
- Auto-recall: ${autoRecall ? '✅ Enabled' : '❌ Disabled'}
|
|
336
|
+
- Public-only mode: ${publicOnly ? '✅ Yes' : '❌ No (full access)'}
|
|
337
|
+
- Default limit: ${defaultLimit} results
|
|
338
|
+
- Min score: ${minScore}`,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (subcommand === 'status') {
|
|
343
|
+
try {
|
|
344
|
+
// Check if ChromaDB is accessible
|
|
345
|
+
const testResult = runRecall('test query', { limit: 1, json: true, publicOnly });
|
|
346
|
+
const parsed = JSON.parse(testResult);
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
text: `🧠 **Jasper Recall Status**
|
|
350
|
+
|
|
351
|
+
**Plugin:** ✅ Active
|
|
352
|
+
**Auto-recall:** ${autoRecall ? '✅ Enabled' : '❌ Disabled'}
|
|
353
|
+
**ChromaDB:** ✅ Connected
|
|
354
|
+
**Index size:** ${parsed.length > 0 ? 'Has data' : 'Empty or minimal'}
|
|
355
|
+
|
|
356
|
+
**Config:**
|
|
357
|
+
- Public-only: ${publicOnly}
|
|
358
|
+
- Default limit: ${defaultLimit}
|
|
359
|
+
- Min score: ${minScore}`,
|
|
360
|
+
};
|
|
361
|
+
} catch (err: any) {
|
|
362
|
+
return {
|
|
363
|
+
text: `🧠 **Jasper Recall Status**
|
|
364
|
+
|
|
365
|
+
**Plugin:** ✅ Active
|
|
366
|
+
**Auto-recall:** ${autoRecall ? '✅ Enabled' : '❌ Disabled'}
|
|
367
|
+
**ChromaDB:** ❌ Error - ${err.message}
|
|
368
|
+
|
|
369
|
+
Run \`npx jasper-recall setup\` to install dependencies.`,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Default: show help
|
|
375
|
+
return {
|
|
376
|
+
text: `🧠 **Jasper Recall**
|
|
377
|
+
|
|
378
|
+
**Commands:**
|
|
379
|
+
- \`/jasper-recall setup\` — Setup instructions & cron jobs
|
|
380
|
+
- \`/jasper-recall status\` — Check plugin status
|
|
381
|
+
- \`/recall <query>\` — Search memory
|
|
382
|
+
- \`/index\` — Re-index memory files
|
|
383
|
+
|
|
384
|
+
**CLI:**
|
|
385
|
+
- \`npx jasper-recall setup\` — Install Python dependencies
|
|
386
|
+
- \`npx jasper-recall doctor\` — Health check`,
|
|
387
|
+
};
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
|
|
249
391
|
// ============================================================================
|
|
250
392
|
// RPC Methods
|
|
251
393
|
// ============================================================================
|