@chatpanel/gateway 0.6.39 → 0.6.40
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/package.json +1 -1
- package/src/history-store.js +9 -0
- package/src/server.js +7 -3
- package/src/sqlite-store.js +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/gateway",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.40",
|
|
4
4
|
"description": "Local privacy gateway \u2014 redacts PII out of OpenAI/Anthropic API traffic before it reaches a model, then restores it in the reply. Point opencode, codex, aider, Claude Code, etc. at it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/history-store.js
CHANGED
|
@@ -178,6 +178,15 @@ export class HistoryStore {
|
|
|
178
178
|
return this.records.size;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
// Wipe every record — the user purging the on-disk warm copy. Returns how many were dropped.
|
|
182
|
+
clear() {
|
|
183
|
+
const n = this.records.size;
|
|
184
|
+
this.records.clear();
|
|
185
|
+
this.index = new SearchIndex();
|
|
186
|
+
this.schedulePersist();
|
|
187
|
+
return n;
|
|
188
|
+
}
|
|
189
|
+
|
|
181
190
|
search(query, opts) {
|
|
182
191
|
return this.index.search(query, opts);
|
|
183
192
|
}
|
package/src/server.js
CHANGED
|
@@ -46,7 +46,7 @@ import * as openai from './openai.js';
|
|
|
46
46
|
import * as responses from './responses.js';
|
|
47
47
|
import * as anthropic from './anthropic.js';
|
|
48
48
|
|
|
49
|
-
export const VERSION = '0.6.
|
|
49
|
+
export const VERSION = '0.6.40';
|
|
50
50
|
|
|
51
51
|
// WARM search tier — SQLite + FTS5 record store (falls back to an encrypted-JSON
|
|
52
52
|
// store if SQLite can't load), fed by the extension's ingest sync + backup-ingest.
|
|
@@ -534,8 +534,8 @@ export function createGateway(cfg = loadConfig()) {
|
|
|
534
534
|
// WRITES are not: a drive-by localhost page or a random local process must not be
|
|
535
535
|
// able to inject records the model then trusts as the user's real history. Ingest
|
|
536
536
|
// requires the extension Origin (which its POST always carries) or the gateway token.
|
|
537
|
-
if (pathname === '/v1/history/ingest' && req.method === 'POST' && !isAdminAuthorized(req)) {
|
|
538
|
-
return sendJson(res, 403, { error: { message: 'history
|
|
537
|
+
if ((pathname === '/v1/history/ingest' || pathname === '/v1/history/clear') && req.method === 'POST' && !isAdminAuthorized(req)) {
|
|
538
|
+
return sendJson(res, 403, { error: { message: 'history write — extension origin or gateway token required', type: 'forbidden' } });
|
|
539
539
|
}
|
|
540
540
|
// The access log is who-read-what — sensitive, and writable only by the local MCP
|
|
541
541
|
// process (which sends the gateway token). Extension Origin or token for both the
|
|
@@ -596,6 +596,10 @@ export function createGateway(cfg = loadConfig()) {
|
|
|
596
596
|
return sendJson(res, 400, { error: { message: `ingest failed: ${e.message}`, type: 'ingest_error' } });
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
|
+
if (pathname === '/v1/history/clear' && req.method === 'POST') {
|
|
600
|
+
const dropped = historyStore.clear();
|
|
601
|
+
return sendJson(res, 200, { ok: true, dropped, size: historyStore.size });
|
|
602
|
+
}
|
|
599
603
|
if (pathname === '/v1/history/search' && req.method === 'POST') {
|
|
600
604
|
try {
|
|
601
605
|
const body = JSON.parse((await readBody(req, cfg.maxBodyBytes)).toString('utf8')) || {};
|
package/src/sqlite-store.js
CHANGED
|
@@ -153,6 +153,14 @@ export class SqliteHistoryStore {
|
|
|
153
153
|
const body = this.db.get('SELECT text FROM fts WHERE id = ?', [id]);
|
|
154
154
|
return { ...meta, text: body?.text || '' };
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
// Wipe every record — the user purging the on-disk warm copy. Returns how many were dropped.
|
|
158
|
+
clear() {
|
|
159
|
+
const n = this.size;
|
|
160
|
+
this.db.exec('DELETE FROM records');
|
|
161
|
+
this.db.exec('DELETE FROM fts');
|
|
162
|
+
return n;
|
|
163
|
+
}
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
// Pick the best available warm engine. SQLite when it loads; otherwise the
|