@chatpanel/pii 0.2.1 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/pii-redact.js +12 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/pii",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "The canonical ChatPanel privacy engine — reversible PII redaction + pseudonymization with local entity detection. Pure, dependency-free ESM shared by the ChatPanel extension, gateway, and bridge.",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/pii-redact.js CHANGED
@@ -20,6 +20,14 @@
20
20
 
21
21
  const TOKEN_RE = /\[\[([A-Z][A-Z0-9]*)_(\d+)\]\]/g;
22
22
 
23
+ // Bracket-TOLERANT match of the same token. Smaller models routinely drop or mangle
24
+ // the [[ ]] when echoing a placeholder into tool-call JSON — e.g. they emit "ORG_1"
25
+ // or "[ORG_1]" instead of "[[ORG_1]]" — which the strict TOKEN_RE misses, leaving
26
+ // the tool to search the literal "ORG_1" (and get nothing). We match 0–2 brackets
27
+ // on each side and reconstruct the canonical token to look up; only ACTUAL vault
28
+ // tokens are swapped, so a coincidental "ABC_1" that isn't ours is left untouched.
29
+ const TOLERANT_TOKEN_RE = /\[{0,2}([A-Z][A-Z0-9]*_\d+)\]{0,2}/g;
30
+
23
31
  // A vault is the per-conversation mapping between placeholders and originals. Keep
24
32
  // one per conversation so PERSON_1 means the same entity across turns.
25
33
  export function createVault() {
@@ -168,7 +176,10 @@ export function redactText(text, vault, {
168
176
  // Swap placeholders back to their originals. Unknown tokens are left untouched.
169
177
  export function restoreText(text, vault) {
170
178
  if (text == null || !vault) return text;
171
- return String(text).replace(TOKEN_RE, (m) => (vault.byToken.has(m) ? vault.byToken.get(m) : m));
179
+ return String(text).replace(TOLERANT_TOKEN_RE, (m, inner) => {
180
+ const canonical = `[[${inner}]]`;
181
+ return vault.byToken.has(canonical) ? vault.byToken.get(canonical) : m;
182
+ });
172
183
  }
173
184
 
174
185
  // Restore for LOCAL use only — e.g. tool-call args that hit on-device history /