@chatpanel/gateway 0.6.62 → 0.6.63
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 +2 -2
- package/src/redact.js +17 -4
- package/src/server.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/gateway",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.63",
|
|
4
4
|
"description": "Local privacy gateway — 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": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"node": ">=18"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@chatpanel/pii": "^0.7.
|
|
30
|
+
"@chatpanel/pii": "^0.7.1",
|
|
31
31
|
"@huggingface/transformers": "^4.2.0",
|
|
32
32
|
"onnxruntime-web": "1.26.0-dev.20260416-b7804b056c",
|
|
33
33
|
"phonemizer": "^1.2.1"
|
package/src/redact.js
CHANGED
|
@@ -20,7 +20,14 @@ import * as engine from './ner-engine.js';
|
|
|
20
20
|
// quality — free requests get the full tier (names/orgs via NER) within their
|
|
21
21
|
// allowance. The custom dictionary is capped for free: gatedDictionary limits it
|
|
22
22
|
// to FREE_DICT_LIMIT via the shared chatpanel-pii gate.
|
|
23
|
-
export async function redactSegments(segments, redactionCfg, {
|
|
23
|
+
export async function redactSegments(segments, redactionCfg, {
|
|
24
|
+
signal, isPro = true, onEgress = null, fetchImpl: fetchOverride = null,
|
|
25
|
+
// The bundled detector, INJECTED rather than reached for. An ES module namespace cannot
|
|
26
|
+
// be monkey-patched, so with a hard import there is no way to ask "does an entity the
|
|
27
|
+
// engine found actually come out the other side as a token" without downloading a model.
|
|
28
|
+
// That question went unasked for exactly that reason, and the answer was no.
|
|
29
|
+
nerEngine = engine,
|
|
30
|
+
} = {}) {
|
|
24
31
|
const vault = createVault();
|
|
25
32
|
|
|
26
33
|
// De-steganography FIRST (before detection). Invisible/format Unicode is a triple
|
|
@@ -51,7 +58,7 @@ export async function redactSegments(segments, redactionCfg, { signal, isPro = t
|
|
|
51
58
|
// @chatpanel/pii's caching / timeout / type-gating — one source of truth.
|
|
52
59
|
const det = redactionCfg.detection;
|
|
53
60
|
const useExternal = !!(det && det.backend && det.backend !== 'off');
|
|
54
|
-
const useEngine = !useExternal &&
|
|
61
|
+
const useEngine = !useExternal && nerEngine.isReady();
|
|
55
62
|
|
|
56
63
|
let entities = [];
|
|
57
64
|
if (tier === 'full' && (useExternal || useEngine)) {
|
|
@@ -61,12 +68,18 @@ export async function redactSegments(segments, redactionCfg, { signal, isPro = t
|
|
|
61
68
|
// under a second, but a cold one must be allowed to finish; on timeout the turn
|
|
62
69
|
// falls back to dictionary/deterministic-only redaction.
|
|
63
70
|
const detection = useEngine
|
|
64
|
-
|
|
71
|
+
// `transport: 'in-process'` is load-bearing, not decoration. Without it the sentinel
|
|
72
|
+
// URL below fails @chatpanel/pii's SSRF scheme check, the throw is swallowed by the
|
|
73
|
+
// fail-open path, and the bundled engine contributes NOTHING to any redaction while
|
|
74
|
+
// reporting itself ready — names and organisations reach the model in full under a
|
|
75
|
+
// config that says "full". The flag is only honoured alongside an injected fetch,
|
|
76
|
+
// which is `engine.fetchAdapter` on the next line.
|
|
77
|
+
? { backend: 'endpoint', url: 'inproc:ner', transport: 'in-process', timeoutMs: 30000, maxChars: 8000, types: det?.types }
|
|
65
78
|
: { ...det, timeoutMs: Math.max(Number(det.timeoutMs) || 0, 30000) };
|
|
66
79
|
// The in-process engine is already injected this way; `fetchOverride` is the same seam
|
|
67
80
|
// for a test, so the detector hop can be exercised without a network. Never used in
|
|
68
81
|
// production — nothing passes it but tests.
|
|
69
|
-
const fetchImpl = useEngine ?
|
|
82
|
+
const fetchImpl = useEngine ? nerEngine.fetchAdapter : (fetchOverride || undefined);
|
|
70
83
|
try {
|
|
71
84
|
entities = await detectEntities(texts.join('\n\n'), { detection }, {
|
|
72
85
|
signal,
|
package/src/server.js
CHANGED
|
@@ -55,7 +55,7 @@ import * as openai from './openai.js';
|
|
|
55
55
|
import * as responses from './responses.js';
|
|
56
56
|
import * as anthropic from './anthropic.js';
|
|
57
57
|
|
|
58
|
-
export const VERSION = '0.6.
|
|
58
|
+
export const VERSION = '0.6.63';
|
|
59
59
|
|
|
60
60
|
// WARM search tier — SQLite + FTS5 record store (falls back to an encrypted-JSON
|
|
61
61
|
// store if SQLite can't load), fed by the extension's ingest sync + backup-ingest.
|