jasper-recall 0.2.0 → 0.2.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 CHANGED
@@ -17,6 +17,12 @@ Local RAG (Retrieval-Augmented Generation) system for AI agent memory. Gives you
17
17
  - **Shared memory sync** — Bidirectional learning between main and sandboxed agents
18
18
  - **Privacy checker** — Scan content for sensitive data before sharing
19
19
 
20
+ ### New in v0.2.1: Recall Server
21
+
22
+ - **HTTP API server** — `npx jasper-recall serve` for Docker-isolated agents
23
+ - **Public-only by default** — Secure API access for untrusted callers
24
+ - **CORS enabled** — Works from browsers and agent containers
25
+
20
26
  ## Quick Start
21
27
 
22
28
  ```bash
@@ -154,6 +160,49 @@ index-digests
154
160
  recall "product info" --public-only
155
161
  ```
156
162
 
163
+ ## Recall Server (v0.2.1+)
164
+
165
+ For **Docker-isolated agents** that can't run the CLI directly, start an HTTP API server:
166
+
167
+ ```bash
168
+ npx jasper-recall serve # Default: localhost:3458
169
+ npx jasper-recall serve --port 8080 # Custom port
170
+ npx jasper-recall serve --host 0.0.0.0 # Allow external access
171
+ ```
172
+
173
+ ### API Endpoints
174
+
175
+ ```
176
+ GET /recall?q=search+query&limit=5
177
+ GET /health
178
+ ```
179
+
180
+ ### Example
181
+
182
+ ```bash
183
+ # Query from Docker container
184
+ curl "http://host.docker.internal:3458/recall?q=product+info"
185
+ ```
186
+
187
+ Response:
188
+ ```json
189
+ {
190
+ "ok": true,
191
+ "query": "product info",
192
+ "public_only": true,
193
+ "count": 3,
194
+ "results": [
195
+ { "content": "...", "file": "memory/shared/product-updates.md", "score": 0.85 }
196
+ ]
197
+ }
198
+ ```
199
+
200
+ ### Security
201
+
202
+ - **`public_only=true` is enforced by default** — API callers only see public content
203
+ - To allow private queries (dangerous!), set `RECALL_ALLOW_PRIVATE=true`
204
+ - Bind to `127.0.0.1` (default) to prevent external access
205
+
157
206
  ## Configuration
158
207
 
159
208
  Set environment variables to customize paths:
package/SKILL.md CHANGED
@@ -1,12 +1,17 @@
1
1
  ---
2
2
  name: jasper-recall
3
- description: Local RAG system for agent memory using ChromaDB and sentence-transformers. Provides semantic search over session logs, daily notes, and memory files. Use when you need persistent memory across sessions, want to search past conversations, or build agents that remember context. Commands: recall "query", index-digests, digest-sessions.
3
+ version: 0.2.1
4
+ description: Local RAG system for agent memory using ChromaDB and sentence-transformers. Provides semantic search over session logs, daily notes, and memory files. v0.2.1 adds HTTP server for Docker-isolated agents. Commands: recall, index-digests, digest-sessions, privacy-check, sync-shared, serve.
4
5
  ---
5
6
 
6
- # Jasper Recall
7
+ # Jasper Recall v0.2.1
7
8
 
8
9
  Local RAG (Retrieval-Augmented Generation) system for AI agent memory. Gives your agent the ability to remember and search past conversations.
9
10
 
11
+ **New in v0.2.1:** Recall Server — HTTP API for Docker-isolated agents that can't run CLI directly.
12
+
13
+ **New in v0.2.0:** Shared Agent Memory — bidirectional learning between main and sandboxed agents with privacy controls.
14
+
10
15
  ## When to Use
11
16
 
12
17
  - **Memory recall**: Search past sessions for context before answering
@@ -106,6 +111,44 @@ Schedule regular indexing:
106
111
  }
107
112
  ```
108
113
 
114
+ ## Shared Agent Memory (v0.2.0)
115
+
116
+ For multi-agent setups where sandboxed agents need access to some memories:
117
+
118
+ ### Memory Tagging
119
+
120
+ Tag entries in daily notes:
121
+
122
+ ```markdown
123
+ ## 2026-02-05 [public] - Feature shipped
124
+ This is visible to all agents.
125
+
126
+ ## 2026-02-05 [private] - Personal note
127
+ This is main agent only (default if untagged).
128
+ ```
129
+
130
+ ### Sandboxed Agent Access
131
+
132
+ ```bash
133
+ # Sandboxed agents use --public-only
134
+ recall "product info" --public-only
135
+
136
+ # Main agent can see everything
137
+ recall "product info"
138
+ ```
139
+
140
+ ### Privacy Workflow
141
+
142
+ ```bash
143
+ # Check for sensitive data before sharing
144
+ privacy-check "text to scan"
145
+ privacy-check --file notes.md
146
+
147
+ # Extract [public] entries to shared directory
148
+ sync-shared
149
+ sync-shared --dry-run # Preview first
150
+ ```
151
+
109
152
  ## CLI Reference
110
153
 
111
154
  ### recall
@@ -117,6 +160,53 @@ Options:
117
160
  -n, --limit N Number of results (default: 5)
118
161
  --json Output as JSON
119
162
  -v, --verbose Show similarity scores
163
+ --public-only Only search shared/public content (v0.2.0+)
164
+ ```
165
+
166
+ ### serve (v0.2.1+)
167
+
168
+ ```
169
+ npx jasper-recall serve [OPTIONS]
170
+
171
+ Options:
172
+ --port, -p N Port to listen on (default: 3458)
173
+ --host, -h H Host to bind (default: 127.0.0.1)
174
+
175
+ Starts HTTP API server for Docker-isolated agents.
176
+
177
+ Endpoints:
178
+ GET /recall?q=query&limit=5 Search memories
179
+ GET /health Health check
180
+
181
+ Security: public_only=true enforced by default.
182
+ Set RECALL_ALLOW_PRIVATE=true to allow private queries.
183
+ ```
184
+
185
+ **Example (from Docker container):**
186
+ ```bash
187
+ curl "http://host.docker.internal:3458/recall?q=product+info"
188
+ ```
189
+
190
+ ### privacy-check (v0.2.0+)
191
+
192
+ ```
193
+ privacy-check "text" # Scan inline text
194
+ privacy-check --file X # Scan a file
195
+
196
+ Detects: emails, API keys, internal IPs, home paths, credentials.
197
+ Returns: CLEAN or list of violations.
198
+ ```
199
+
200
+ ### sync-shared (v0.2.0+)
201
+
202
+ ```
203
+ sync-shared [OPTIONS]
204
+
205
+ Options:
206
+ --dry-run Preview without writing
207
+ --all Process all daily notes
208
+
209
+ Extracts [public] tagged entries to memory/shared/.
120
210
  ```
121
211
 
122
212
  ### index-digests
@@ -15,7 +15,7 @@ const fs = require('fs');
15
15
  const path = require('path');
16
16
  const os = require('os');
17
17
 
18
- const VERSION = '0.1.0';
18
+ const VERSION = '0.2.2';
19
19
  const VENV_PATH = path.join(os.homedir(), '.openclaw', 'rag-env');
20
20
  const CHROMA_PATH = path.join(os.homedir(), '.openclaw', 'chroma-db');
21
21
  const BIN_PATH = path.join(os.homedir(), '.local', 'bin');
@@ -134,6 +134,7 @@ COMMANDS:
134
134
  recall Search your memory (alias for the recall command)
135
135
  index Index memory files (alias for index-digests)
136
136
  digest Process session logs (alias for digest-sessions)
137
+ serve Start HTTP API server (for sandboxed agents)
137
138
  help Show this help message
138
139
 
139
140
  EXAMPLES:
@@ -141,6 +142,7 @@ EXAMPLES:
141
142
  recall "what did we discuss yesterday"
142
143
  index-digests
143
144
  digest-sessions --dry-run
145
+ npx jasper-recall serve --port 3458
144
146
  `);
145
147
  }
146
148
 
@@ -178,6 +180,12 @@ switch (command) {
178
180
  error('Run "npx jasper-recall setup" first');
179
181
  }
180
182
  break;
183
+ case 'serve':
184
+ case 'server':
185
+ // Start the HTTP server for sandboxed agents
186
+ const { runCLI } = require('./server');
187
+ runCLI(process.argv.slice(3));
188
+ break;
181
189
  case '--version':
182
190
  case '-v':
183
191
  console.log(VERSION);
package/cli/server.js ADDED
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Jasper Recall Server
3
+ * HTTP API for memory search - designed for sandboxed agents
4
+ *
5
+ * Security: public_only is enforced by default
6
+ */
7
+
8
+ const http = require('http');
9
+ const { execSync } = require('child_process');
10
+ const path = require('path');
11
+ const os = require('os');
12
+ const url = require('url');
13
+
14
+ const BIN_PATH = path.join(os.homedir(), '.local', 'bin');
15
+ const RECALL_SCRIPT = path.join(BIN_PATH, 'recall');
16
+
17
+ /**
18
+ * Execute recall query
19
+ */
20
+ function executeRecall(query, options = {}) {
21
+ const { publicOnly = true, limit = 5 } = options;
22
+
23
+ let cmd = `${RECALL_SCRIPT} "${query.replace(/"/g, '\\"')}"`;
24
+
25
+ // Security: always add --public-only unless explicitly disabled
26
+ if (publicOnly) {
27
+ cmd += ' --public-only';
28
+ }
29
+
30
+ cmd += ` --limit ${parseInt(limit) || 5}`;
31
+
32
+ try {
33
+ const output = execSync(cmd, {
34
+ encoding: 'utf8',
35
+ timeout: 30000,
36
+ env: { ...process.env, HOME: os.homedir() }
37
+ });
38
+ return { ok: true, output };
39
+ } catch (err) {
40
+ // Check if it's just "no results"
41
+ if (err.stdout?.includes('No results') || err.status === 0) {
42
+ return { ok: true, output: err.stdout || 'No results found' };
43
+ }
44
+ return { ok: false, error: err.message, stderr: err.stderr };
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Parse recall output into structured results
50
+ */
51
+ function parseResults(output) {
52
+ const results = [];
53
+
54
+ // Try to parse structured output
55
+ const blocks = output.split(/={3,}\s*(?:Result\s+\d+|---)/i);
56
+
57
+ for (const block of blocks) {
58
+ if (!block.trim()) continue;
59
+
60
+ const result = {};
61
+
62
+ const scoreMatch = block.match(/score:\s*([\d.]+)/i);
63
+ if (scoreMatch) result.score = parseFloat(scoreMatch[1]);
64
+
65
+ const fileMatch = block.match(/File:\s*(.+)/i);
66
+ if (fileMatch) result.file = fileMatch[1].trim();
67
+
68
+ const linesMatch = block.match(/Lines?:\s*(\d+(?:-\d+)?)/i);
69
+ if (linesMatch) result.lines = linesMatch[1];
70
+
71
+ // Content is everything else
72
+ let content = block
73
+ .replace(/score:\s*[\d.]+/gi, '')
74
+ .replace(/File:\s*.+/gi, '')
75
+ .replace(/Lines?:\s*\d+(?:-\d+)?/gi, '')
76
+ .trim();
77
+
78
+ if (content) {
79
+ result.content = content.substring(0, 1000);
80
+ results.push(result);
81
+ }
82
+ }
83
+
84
+ // Fallback for unparseable output
85
+ if (results.length === 0 && output.trim()) {
86
+ results.push({ content: output.trim().substring(0, 2000), raw: true });
87
+ }
88
+
89
+ return results;
90
+ }
91
+
92
+ /**
93
+ * Handle HTTP request
94
+ */
95
+ function handleRequest(req, res) {
96
+ // CORS headers for browser/agent access
97
+ res.setHeader('Access-Control-Allow-Origin', '*');
98
+ res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
99
+ res.setHeader('Content-Type', 'application/json');
100
+
101
+ if (req.method === 'OPTIONS') {
102
+ res.writeHead(200);
103
+ res.end();
104
+ return;
105
+ }
106
+
107
+ const parsedUrl = url.parse(req.url, true);
108
+ const pathname = parsedUrl.pathname;
109
+ const query = parsedUrl.query;
110
+
111
+ // Health check
112
+ if (pathname === '/health' || pathname === '/') {
113
+ res.writeHead(200);
114
+ res.end(JSON.stringify({ ok: true, service: 'jasper-recall', version: '0.2.1' }));
115
+ return;
116
+ }
117
+
118
+ // Recall endpoint
119
+ if (pathname === '/recall' || pathname === '/api/recall') {
120
+ const searchQuery = query.q || query.query;
121
+
122
+ if (!searchQuery) {
123
+ res.writeHead(400);
124
+ res.end(JSON.stringify({ ok: false, error: 'q or query parameter required' }));
125
+ return;
126
+ }
127
+
128
+ // Security: public_only defaults to true
129
+ // Only allow disabling if explicitly set AND RECALL_ALLOW_PRIVATE=true
130
+ let publicOnly = true;
131
+ if (query.public_only === 'false' && process.env.RECALL_ALLOW_PRIVATE === 'true') {
132
+ publicOnly = false;
133
+ }
134
+
135
+ const result = executeRecall(searchQuery, {
136
+ publicOnly,
137
+ limit: query.limit || 5
138
+ });
139
+
140
+ if (result.ok) {
141
+ const parsed = parseResults(result.output);
142
+ res.writeHead(200);
143
+ res.end(JSON.stringify({
144
+ ok: true,
145
+ query: searchQuery,
146
+ public_only: publicOnly,
147
+ count: parsed.length,
148
+ results: parsed,
149
+ raw: result.output
150
+ }));
151
+ } else {
152
+ res.writeHead(500);
153
+ res.end(JSON.stringify({
154
+ ok: false,
155
+ error: result.error,
156
+ stderr: result.stderr?.substring(0, 500)
157
+ }));
158
+ }
159
+ return;
160
+ }
161
+
162
+ // 404
163
+ res.writeHead(404);
164
+ res.end(JSON.stringify({ ok: false, error: 'Not found' }));
165
+ }
166
+
167
+ /**
168
+ * Start the server
169
+ */
170
+ function startServer(port = 3458, host = '127.0.0.1') {
171
+ const server = http.createServer(handleRequest);
172
+
173
+ server.listen(port, host, () => {
174
+ console.log(`🦊 Jasper Recall Server running on http://${host}:${port}`);
175
+ console.log('');
176
+ console.log('Endpoints:');
177
+ console.log(` GET /recall?q=query Search memories (public-only by default)`);
178
+ console.log(` GET /health Health check`);
179
+ console.log('');
180
+ console.log('Security: public_only=true is enforced by default');
181
+ console.log('Press Ctrl+C to stop');
182
+ });
183
+
184
+ return server;
185
+ }
186
+
187
+ /**
188
+ * Parse CLI args and start server
189
+ */
190
+ function runCLI(args) {
191
+ let port = 3458;
192
+ let host = '127.0.0.1';
193
+
194
+ for (let i = 0; i < args.length; i++) {
195
+ if (args[i] === '--port' || args[i] === '-p') {
196
+ port = parseInt(args[++i]) || 3458;
197
+ }
198
+ if (args[i] === '--host' || args[i] === '-h') {
199
+ host = args[++i] || '127.0.0.1';
200
+ }
201
+ if (args[i] === '--help') {
202
+ console.log(`
203
+ Jasper Recall Server
204
+ HTTP API for memory search
205
+
206
+ Usage: npx jasper-recall serve [options]
207
+
208
+ Options:
209
+ --port, -p Port to listen on (default: 3458)
210
+ --host, -h Host to bind to (default: 127.0.0.1)
211
+ --help Show this help
212
+
213
+ Environment:
214
+ RECALL_ALLOW_PRIVATE=true Allow public_only=false queries (dangerous!)
215
+
216
+ Examples:
217
+ npx jasper-recall serve
218
+ npx jasper-recall serve --port 8080
219
+ npx jasper-recall serve --host 0.0.0.0
220
+ `);
221
+ process.exit(0);
222
+ }
223
+ }
224
+
225
+ startServer(port, host);
226
+ }
227
+
228
+ // Export for programmatic use
229
+ module.exports = { startServer, executeRecall, parseResults, runCLI };
230
+
231
+ // CLI entry point
232
+ if (require.main === module) {
233
+ runCLI(process.argv.slice(2));
234
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jasper-recall",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Local RAG system for AI agent memory using ChromaDB and sentence-transformers",
5
5
  "main": "src/index.js",
6
6
  "bin": {