@datafog/fogclaw 0.1.5 → 0.2.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/CHANGELOG.md +31 -0
- package/README.md +83 -4
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +100 -1
- package/dist/config.js.map +1 -1
- package/dist/extract.d.ts +28 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +91 -0
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +135 -30
- package/dist/index.js.map +1 -1
- package/dist/message-sending-handler.d.ts +40 -0
- package/dist/message-sending-handler.d.ts.map +1 -0
- package/dist/message-sending-handler.js +50 -0
- package/dist/message-sending-handler.js.map +1 -0
- package/dist/scanner.d.ts +13 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +76 -2
- package/dist/scanner.js.map +1 -1
- package/dist/tool-result-handler.d.ts +36 -0
- package/dist/tool-result-handler.d.ts.map +1 -0
- package/dist/tool-result-handler.js +91 -0
- package/dist/tool-result-handler.js.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/docs/OBSERVABILITY.md +22 -15
- package/docs/SECURITY.md +6 -4
- package/docs/plans/active/2026-02-17-feat-tool-result-pii-scanning-plan.md +293 -0
- package/docs/specs/2026-02-17-feat-outbound-message-pii-scanning-spec.md +93 -0
- package/docs/specs/2026-02-17-feat-tool-result-pii-scanning-spec.md +122 -0
- package/fogclaw.config.example.json +19 -1
- package/openclaw.plugin.json +63 -2
- package/package.json +9 -9
- package/scripts/ci/he-docs-drift.sh +0 -0
- package/scripts/ci/he-docs-lint.sh +0 -0
- package/scripts/ci/he-plans-lint.sh +0 -0
- package/scripts/ci/he-runbooks-lint.sh +0 -0
- package/scripts/ci/he-specs-lint.sh +0 -0
- package/scripts/ci/he-spikes-lint.sh +0 -0
- package/scripts/runbooks/select-runbooks.sh +0 -0
- package/src/config.ts +139 -2
- package/src/extract.ts +98 -0
- package/src/index.ts +194 -36
- package/src/message-sending-handler.ts +87 -0
- package/src/scanner.ts +114 -8
- package/src/tool-result-handler.ts +133 -0
- package/src/types.ts +23 -0
- package/tests/config.test.ts +55 -81
- package/tests/extract.test.ts +185 -0
- package/tests/message-sending-handler.test.ts +244 -0
- package/tests/plugin-smoke.test.ts +139 -3
- package/tests/scanner.test.ts +61 -1
- package/tests/tool-result-handler.test.ts +329 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Tool result PII scanning** — new `tool_result_persist` hook scans file reads, API responses, and web fetches for PII before they enter the session transcript. Uses regex engine (sync) for <1ms latency on the hot path.
|
|
8
|
+
- **Outbound message PII scanning** — new `message_sending` hook provides a last-chance gate that catches PII in agent replies before delivery to Telegram, Slack, Discord, and other external channels. Uses full Scanner (regex + GLiNER).
|
|
9
|
+
- **Policy allowlist** — whitelist exact strings, regex patterns, or per-entity-type values to skip enforcement on known-safe content (e.g., `noreply@example.com`).
|
|
10
|
+
- **Per-entity confidence thresholds** — tune GLiNER detection sensitivity per label (e.g., require 0.7 for PERSON, 0.85 for ORGANIZATION).
|
|
11
|
+
- **Audit trail logging** — structured audit log entries with `source` field (`guardrail`, `tool_result`, `outbound`) when `auditEnabled: true`. Logs entity counts and labels without raw PII.
|
|
12
|
+
- **Policy preview tool** — `fogclaw_preview` shows which entities would be blocked, warned, or redacted without changing runtime behavior.
|
|
13
|
+
- **Scanning architecture documentation** — README now includes a comparison matrix showing engine trade-offs across all three hooks.
|
|
14
|
+
- **Control UI hints** — `openclaw.plugin.json` includes `uiHints` for policy configuration in OpenClaw's Control UI.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- `resolveAction` extracted to shared `types.ts` module (was duplicated across files).
|
|
19
|
+
- README updated with three-layer scanning overview and defense-in-depth flow diagram.
|
|
20
|
+
|
|
21
|
+
## 0.1.6
|
|
22
|
+
|
|
23
|
+
Initial scoped release as `@datafog/fogclaw`.
|
|
24
|
+
|
|
25
|
+
- Dual-engine PII detection (regex + GLiNER via ONNX)
|
|
26
|
+
- `before_agent_start` hook for automatic prompt guardrail
|
|
27
|
+
- `fogclaw_scan` and `fogclaw_redact` tools
|
|
28
|
+
- Configurable per-entity actions (`redact`, `block`, `warn`)
|
|
29
|
+
- Multiple redaction strategies (`token`, `mask`, `hash`)
|
|
30
|
+
- Custom entity types via GLiNER zero-shot NER
|
|
31
|
+
- Graceful degradation to regex-only when GLiNER unavailable
|
package/README.md
CHANGED
|
@@ -6,12 +6,19 @@ FogClaw uses a dual-engine approach: battle-tested regex patterns for structured
|
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
+
- **Three-layer scanning** — inbound prompts, tool results, and outbound messages are all scanned for PII before they cross trust boundaries
|
|
9
10
|
- **Automatic guardrail** — intercepts messages before they reach the LLM via OpenClaw's `before_agent_start` hook
|
|
10
|
-
- **
|
|
11
|
+
- **Tool result scanning** — redacts PII in file reads, API responses, and web fetches before they enter the session transcript (`tool_result_persist`)
|
|
12
|
+
- **Outbound message scanning** — last-chance gate that catches PII in agent replies before delivery to external channels (`message_sending`)
|
|
13
|
+
- **On-demand tools** — `fogclaw_scan`, `fogclaw_preview`, and `fogclaw_redact`
|
|
11
14
|
- **Dual detection engine** — regex for structured PII (<1ms), GLiNER for zero-shot NER (~50-200ms)
|
|
12
15
|
- **Custom entity types** — define any entity label (e.g., "project codename", "competitor name") and GLiNER detects them with zero training
|
|
13
16
|
- **Configurable actions** — per-entity-type behavior: `redact`, `block`, or `warn`
|
|
17
|
+
- **Per-entity confidence tuning** — tighten or relax detection confidence by label
|
|
18
|
+
- **Policy allowlist** — whitelist exact strings or regex patterns to skip enforcement on known-safe values
|
|
19
|
+
- **Policy preview** — run a dry-run simulation before changing runtime policy
|
|
14
20
|
- **Multiple redaction strategies** — `token`, `mask`, or `hash`
|
|
21
|
+
- **Audit trail summary logging** — optional structured action summaries without logging raw entity content
|
|
15
22
|
- **Graceful degradation** — falls back to regex-only mode if GLiNER fails to load
|
|
16
23
|
|
|
17
24
|
## Installation
|
|
@@ -60,6 +67,10 @@ cp fogclaw.config.example.json fogclaw.config.json
|
|
|
60
67
|
"redactStrategy": "token",
|
|
61
68
|
"model": "onnx-community/gliner_large-v2.1",
|
|
62
69
|
"confidence_threshold": 0.5,
|
|
70
|
+
"entityConfidenceThresholds": {
|
|
71
|
+
"PERSON": 0.6,
|
|
72
|
+
"ORGANIZATION": 0.7
|
|
73
|
+
},
|
|
63
74
|
"custom_entities": ["project codename", "competitor name"],
|
|
64
75
|
"entityActions": {
|
|
65
76
|
"SSN": "block",
|
|
@@ -67,7 +78,15 @@ cp fogclaw.config.example.json fogclaw.config.json
|
|
|
67
78
|
"EMAIL": "redact",
|
|
68
79
|
"PHONE": "redact",
|
|
69
80
|
"PERSON": "warn"
|
|
70
|
-
}
|
|
81
|
+
},
|
|
82
|
+
"allowlist": {
|
|
83
|
+
"values": ["noreply@example.com"],
|
|
84
|
+
"patterns": ["^internal-"],
|
|
85
|
+
"entities": {
|
|
86
|
+
"PERSON": ["john doe"]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"auditEnabled": true
|
|
71
90
|
}
|
|
72
91
|
```
|
|
73
92
|
|
|
@@ -113,18 +132,54 @@ Incoming message
|
|
|
113
132
|
+-----------+
|
|
114
133
|
| GLiNER | persons, orgs, locations + your custom entities
|
|
115
134
|
| (ONNX) | confidence: 0.0-1.0
|
|
116
|
-
|
|
135
|
+
+-----------+
|
|
117
136
|
|
|
|
118
137
|
v
|
|
119
138
|
+-----------+
|
|
120
139
|
| Merge & | deduplicate overlapping spans, prefer higher confidence
|
|
121
140
|
| Normalize |
|
|
122
|
-
|
|
141
|
+
+-----------+
|
|
123
142
|
|
|
|
124
143
|
v
|
|
125
144
|
Apply action per entity type (redact / block / warn)
|
|
126
145
|
```
|
|
127
146
|
|
|
147
|
+
## Scanning Architecture
|
|
148
|
+
|
|
149
|
+
FogClaw hooks into three points in the OpenClaw message lifecycle. Each hook uses the detection engine best suited to its runtime constraints:
|
|
150
|
+
|
|
151
|
+
| Hook | Direction | Engine | Latency | Async | Entity Coverage |
|
|
152
|
+
|------|-----------|--------|---------|-------|-----------------|
|
|
153
|
+
| `before_agent_start` | Inbound (user prompt) | Regex + GLiNER | ~50-200ms | Yes | Full — structured PII + names, orgs, custom entities |
|
|
154
|
+
| `tool_result_persist` | Internal (tool results) | Regex only | <1ms | No (sync) | Structured PII — emails, SSNs, phones, credit cards, IPs |
|
|
155
|
+
| `message_sending` | Outbound (agent reply) | Regex + GLiNER | ~50-200ms | Yes | Full — structured PII + names, orgs, custom entities |
|
|
156
|
+
|
|
157
|
+
**Why regex-only for tool results?** OpenClaw's `tool_result_persist` hook requires synchronous handlers — async returns are rejected. GLiNER inference runs a synchronous ONNX native call that blocks the event loop for 100-500ms per invocation, which would degrade gateway responsiveness (delayed heartbeats, WebSocket pings, HTTP responses). Regex covers the high-confidence structured patterns most common in tool output (credentials in file reads, contact info in API responses). Person names and organization names are caught on the async inbound and outbound paths, providing defense-in-depth without hot-path latency.
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
User prompt ──► before_agent_start (regex + GLiNER)
|
|
161
|
+
│
|
|
162
|
+
▼
|
|
163
|
+
Agent + LLM
|
|
164
|
+
│
|
|
165
|
+
┌─────────┼─────────┐
|
|
166
|
+
▼ ▼ ▼
|
|
167
|
+
Tool call Tool call Tool call
|
|
168
|
+
│ │ │
|
|
169
|
+
▼ ▼ ▼
|
|
170
|
+
tool_result_persist (regex only, sync)
|
|
171
|
+
│
|
|
172
|
+
▼
|
|
173
|
+
Agent reply
|
|
174
|
+
│
|
|
175
|
+
▼
|
|
176
|
+
message_sending (regex + GLiNER)
|
|
177
|
+
│
|
|
178
|
+
▼
|
|
179
|
+
External channel
|
|
180
|
+
(Telegram, Slack, etc.)
|
|
181
|
+
```
|
|
182
|
+
|
|
128
183
|
## Detected Entity Types
|
|
129
184
|
|
|
130
185
|
### Regex Engine (structured PII)
|
|
@@ -162,8 +217,11 @@ Plus any labels you add via `custom_entities` in the config.
|
|
|
162
217
|
| `redactStrategy` | `string` | `"token"` | How to redact: `"token"`, `"mask"`, or `"hash"` |
|
|
163
218
|
| `model` | `string` | `"onnx-community/gliner_large-v2.1"` | HuggingFace model path for GLiNER (or a local `.onnx` path for advanced setups). |
|
|
164
219
|
| `confidence_threshold` | `number` | `0.5` | Minimum confidence for GLiNER detections (0-1) |
|
|
220
|
+
| `entityConfidenceThresholds` | `object` | `{}` | Per-label confidence overrides, e.g. `{ "PERSON": 0.7, "ORGANIZATION": 0.85 }` |
|
|
165
221
|
| `custom_entities` | `string[]` | `[]` | Custom entity labels for zero-shot detection |
|
|
166
222
|
| `entityActions` | `object` | `{}` | Per-entity-type action overrides |
|
|
223
|
+
| `allowlist` | `object` | `{}` | Exception rules to skip enforcement via exact values or regex patterns |
|
|
224
|
+
| `auditEnabled` | `boolean` | `true` | Emit structured audit logs for guardrail decisions |
|
|
167
225
|
|
|
168
226
|
## OpenClaw Tools
|
|
169
227
|
|
|
@@ -175,6 +233,21 @@ Scan text for PII and custom entities. Returns detected entities with types, pos
|
|
|
175
233
|
- `text` (required) — text to scan
|
|
176
234
|
- `custom_labels` (optional) — additional entity labels for zero-shot detection
|
|
177
235
|
|
|
236
|
+
### `fogclaw_preview`
|
|
237
|
+
|
|
238
|
+
Preview what the guardrail would do for a message.
|
|
239
|
+
|
|
240
|
+
**Parameters:**
|
|
241
|
+
- `text` (required) — text to simulate
|
|
242
|
+
- `strategy` (optional) — `"token"`, `"mask"`, or `"hash"` (defaults to config)
|
|
243
|
+
- `custom_labels` (optional) — additional entity labels for zero-shot detection
|
|
244
|
+
|
|
245
|
+
**Response:**
|
|
246
|
+
- `entities`: detected entities and metadata
|
|
247
|
+
- `totalEntities`: total entities found
|
|
248
|
+
- `actionPlan`: counts and labels grouped by `blocked`, `warned`, `redacted`
|
|
249
|
+
- `redactedText`: message with only redacted entities applied
|
|
250
|
+
|
|
178
251
|
### `fogclaw_redact`
|
|
179
252
|
|
|
180
253
|
Scan and redact PII/custom entities from text. Returns sanitized text with entities replaced.
|
|
@@ -219,6 +292,12 @@ npm run build # compile TypeScript
|
|
|
219
292
|
npm run lint # type-check without emitting
|
|
220
293
|
```
|
|
221
294
|
|
|
295
|
+
## Security Notes
|
|
296
|
+
|
|
297
|
+
- Keep `api.logger` output free of raw sensitive values.
|
|
298
|
+
- Use allowlists and `auditEnabled` according to your governance requirements.
|
|
299
|
+
- Consider `block` actions for high-risk entity types in regulated environments.
|
|
300
|
+
|
|
222
301
|
## License
|
|
223
302
|
|
|
224
303
|
MIT
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type FogClawConfig } from "./types.js";
|
|
2
2
|
export declare const DEFAULT_CONFIG: FogClawConfig;
|
|
3
3
|
export declare function loadConfig(overrides: Partial<FogClawConfig>): FogClawConfig;
|
|
4
4
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAGnB,MAAM,YAAY,CAAC;AAoGpB,eAAO,MAAM,cAAc,EAAE,aAe5B,CAAC;AAEF,wBAAgB,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CA2D3E"}
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
|
+
import { canonicalType, } from "./types.js";
|
|
1
2
|
const VALID_GUARDRAIL_MODES = ["redact", "block", "warn"];
|
|
2
3
|
const VALID_REDACT_STRATEGIES = ["token", "mask", "hash"];
|
|
4
|
+
function ensureStringList(value, path) {
|
|
5
|
+
if (!Array.isArray(value)) {
|
|
6
|
+
throw new Error(`${path} must be an array of strings`);
|
|
7
|
+
}
|
|
8
|
+
const entries = value.filter((entry) => {
|
|
9
|
+
if (typeof entry !== "string") {
|
|
10
|
+
throw new Error(`${path} must contain only strings`);
|
|
11
|
+
}
|
|
12
|
+
return true;
|
|
13
|
+
});
|
|
14
|
+
return entries.map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
15
|
+
}
|
|
16
|
+
function ensureEntityAllowlist(value) {
|
|
17
|
+
if (value == null) {
|
|
18
|
+
return { values: [], patterns: [], entities: {} };
|
|
19
|
+
}
|
|
20
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
21
|
+
throw new Error("allowlist must be an object");
|
|
22
|
+
}
|
|
23
|
+
const raw = value;
|
|
24
|
+
const values = ensureStringList(raw.values ?? [], "allowlist.values");
|
|
25
|
+
const patterns = ensureStringList(raw.patterns ?? [], "allowlist.patterns");
|
|
26
|
+
for (const pattern of patterns) {
|
|
27
|
+
try {
|
|
28
|
+
new RegExp(pattern);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error(`allowlist.patterns contains invalid regex pattern: "${pattern}"`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const entitiesValue = raw.entities ?? {};
|
|
35
|
+
if (typeof entitiesValue !== "object" ||
|
|
36
|
+
Array.isArray(entitiesValue) ||
|
|
37
|
+
entitiesValue === null) {
|
|
38
|
+
throw new Error("allowlist.entities must be an object mapping entity labels to string arrays");
|
|
39
|
+
}
|
|
40
|
+
const entities = {};
|
|
41
|
+
for (const [entityType, entryValue] of Object.entries(entitiesValue)) {
|
|
42
|
+
const normalizedType = canonicalType(entityType);
|
|
43
|
+
entities[normalizedType] = ensureStringList(entryValue, `allowlist.entities.${entityType}`);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
values: [...new Set(values)],
|
|
47
|
+
patterns: [...new Set(patterns)],
|
|
48
|
+
entities,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function ensureEntityConfidenceThresholds(value) {
|
|
52
|
+
if (!value) {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
if (typeof value !== "object" || Array.isArray(value) || value === null) {
|
|
56
|
+
throw new Error("entityConfidenceThresholds must be an object");
|
|
57
|
+
}
|
|
58
|
+
const raw = value;
|
|
59
|
+
const normalized = {};
|
|
60
|
+
for (const [entityType, rawThreshold] of Object.entries(raw)) {
|
|
61
|
+
if (typeof rawThreshold !== "number" || Number.isNaN(rawThreshold)) {
|
|
62
|
+
throw new Error(`entityConfidenceThresholds["${entityType}"] must be a number between 0 and 1, got ${String(rawThreshold)}`);
|
|
63
|
+
}
|
|
64
|
+
if (rawThreshold < 0 || rawThreshold > 1) {
|
|
65
|
+
throw new Error(`entityConfidenceThresholds["${entityType}"] must be between 0 and 1, got ${rawThreshold}`);
|
|
66
|
+
}
|
|
67
|
+
const canonicalTypeKey = canonicalType(entityType);
|
|
68
|
+
normalized[canonicalTypeKey] = rawThreshold;
|
|
69
|
+
}
|
|
70
|
+
return normalized;
|
|
71
|
+
}
|
|
3
72
|
export const DEFAULT_CONFIG = {
|
|
4
73
|
enabled: true,
|
|
5
74
|
guardrail_mode: "redact",
|
|
@@ -8,9 +77,32 @@ export const DEFAULT_CONFIG = {
|
|
|
8
77
|
confidence_threshold: 0.5,
|
|
9
78
|
custom_entities: [],
|
|
10
79
|
entityActions: {},
|
|
80
|
+
entityConfidenceThresholds: {},
|
|
81
|
+
allowlist: {
|
|
82
|
+
values: [],
|
|
83
|
+
patterns: [],
|
|
84
|
+
entities: {},
|
|
85
|
+
},
|
|
86
|
+
auditEnabled: true,
|
|
11
87
|
};
|
|
12
88
|
export function loadConfig(overrides) {
|
|
13
|
-
const config = {
|
|
89
|
+
const config = {
|
|
90
|
+
...DEFAULT_CONFIG,
|
|
91
|
+
...overrides,
|
|
92
|
+
entityActions: {
|
|
93
|
+
...DEFAULT_CONFIG.entityActions,
|
|
94
|
+
...(overrides.entityActions ?? {}),
|
|
95
|
+
},
|
|
96
|
+
entityConfidenceThresholds: {
|
|
97
|
+
...DEFAULT_CONFIG.entityConfidenceThresholds,
|
|
98
|
+
...(overrides.entityConfidenceThresholds ?? {}),
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
config.allowlist = ensureEntityAllowlist(overrides.allowlist ?? DEFAULT_CONFIG.allowlist);
|
|
102
|
+
config.entityConfidenceThresholds = ensureEntityConfidenceThresholds(config.entityConfidenceThresholds);
|
|
103
|
+
if (typeof config.enabled !== "boolean") {
|
|
104
|
+
throw new Error(`enabled must be true or false`);
|
|
105
|
+
}
|
|
14
106
|
if (!VALID_GUARDRAIL_MODES.includes(config.guardrail_mode)) {
|
|
15
107
|
throw new Error(`Invalid guardrail_mode "${config.guardrail_mode}". Must be one of: ${VALID_GUARDRAIL_MODES.join(", ")}`);
|
|
16
108
|
}
|
|
@@ -20,11 +112,18 @@ export function loadConfig(overrides) {
|
|
|
20
112
|
if (config.confidence_threshold < 0 || config.confidence_threshold > 1) {
|
|
21
113
|
throw new Error(`confidence_threshold must be between 0 and 1, got ${config.confidence_threshold}`);
|
|
22
114
|
}
|
|
115
|
+
if (typeof config.auditEnabled !== "boolean") {
|
|
116
|
+
throw new Error(`auditEnabled must be true or false`);
|
|
117
|
+
}
|
|
118
|
+
const normalizedActions = {};
|
|
23
119
|
for (const [entityType, action] of Object.entries(config.entityActions)) {
|
|
24
120
|
if (!VALID_GUARDRAIL_MODES.includes(action)) {
|
|
25
121
|
throw new Error(`Invalid action "${action}" for entity type "${entityType}". Must be one of: ${VALID_GUARDRAIL_MODES.join(", ")}`);
|
|
26
122
|
}
|
|
123
|
+
const normalizedType = canonicalType(entityType);
|
|
124
|
+
normalizedActions[normalizedType] = action;
|
|
27
125
|
}
|
|
126
|
+
config.entityActions = normalizedActions;
|
|
28
127
|
return config;
|
|
29
128
|
}
|
|
30
129
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for extracting text from AgentMessage tool result payloads
|
|
3
|
+
* and replacing text content after redaction.
|
|
4
|
+
*
|
|
5
|
+
* AgentMessage shapes handled:
|
|
6
|
+
* - Plain string
|
|
7
|
+
* - Object with `content: string`
|
|
8
|
+
* - Object with `content: [{ type: "text", text: "..." }, ...]`
|
|
9
|
+
*
|
|
10
|
+
* When multiple text blocks exist in a content array, they are joined
|
|
11
|
+
* with a null byte separator (\0) so entity offsets stay valid across
|
|
12
|
+
* the concatenated string. replaceText splits on the same separator
|
|
13
|
+
* to map redacted text back to individual blocks.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Extract all text content from an AgentMessage tool result payload.
|
|
17
|
+
* Returns an empty string if no text content is found.
|
|
18
|
+
*/
|
|
19
|
+
export declare function extractText(message: unknown): string;
|
|
20
|
+
/**
|
|
21
|
+
* Replace text content in an AgentMessage tool result payload with
|
|
22
|
+
* the redacted version. Returns a shallow copy; does not mutate.
|
|
23
|
+
*
|
|
24
|
+
* If the message shape is not recognized or has no text, returns
|
|
25
|
+
* the original message unchanged.
|
|
26
|
+
*/
|
|
27
|
+
export declare function replaceText(message: unknown, redactedText: string): unknown;
|
|
28
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CA4BpD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAqC3E"}
|
package/dist/extract.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for extracting text from AgentMessage tool result payloads
|
|
3
|
+
* and replacing text content after redaction.
|
|
4
|
+
*
|
|
5
|
+
* AgentMessage shapes handled:
|
|
6
|
+
* - Plain string
|
|
7
|
+
* - Object with `content: string`
|
|
8
|
+
* - Object with `content: [{ type: "text", text: "..." }, ...]`
|
|
9
|
+
*
|
|
10
|
+
* When multiple text blocks exist in a content array, they are joined
|
|
11
|
+
* with a null byte separator (\0) so entity offsets stay valid across
|
|
12
|
+
* the concatenated string. replaceText splits on the same separator
|
|
13
|
+
* to map redacted text back to individual blocks.
|
|
14
|
+
*/
|
|
15
|
+
// Separator between text segments from content block arrays.
|
|
16
|
+
// Null byte won't appear in regex PII patterns or normal text content.
|
|
17
|
+
const SEGMENT_SEP = "\0";
|
|
18
|
+
/**
|
|
19
|
+
* Extract all text content from an AgentMessage tool result payload.
|
|
20
|
+
* Returns an empty string if no text content is found.
|
|
21
|
+
*/
|
|
22
|
+
export function extractText(message) {
|
|
23
|
+
if (message == null)
|
|
24
|
+
return "";
|
|
25
|
+
if (typeof message === "string")
|
|
26
|
+
return message;
|
|
27
|
+
if (typeof message !== "object")
|
|
28
|
+
return "";
|
|
29
|
+
const msg = message;
|
|
30
|
+
const content = msg.content;
|
|
31
|
+
if (content == null)
|
|
32
|
+
return "";
|
|
33
|
+
if (typeof content === "string")
|
|
34
|
+
return content;
|
|
35
|
+
if (Array.isArray(content)) {
|
|
36
|
+
const textParts = [];
|
|
37
|
+
for (const block of content) {
|
|
38
|
+
if (block != null &&
|
|
39
|
+
typeof block === "object" &&
|
|
40
|
+
block.type === "text" &&
|
|
41
|
+
typeof block.text === "string") {
|
|
42
|
+
textParts.push(block.text);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (textParts.length === 0)
|
|
46
|
+
return "";
|
|
47
|
+
return textParts.join(SEGMENT_SEP);
|
|
48
|
+
}
|
|
49
|
+
return "";
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Replace text content in an AgentMessage tool result payload with
|
|
53
|
+
* the redacted version. Returns a shallow copy; does not mutate.
|
|
54
|
+
*
|
|
55
|
+
* If the message shape is not recognized or has no text, returns
|
|
56
|
+
* the original message unchanged.
|
|
57
|
+
*/
|
|
58
|
+
export function replaceText(message, redactedText) {
|
|
59
|
+
if (message == null)
|
|
60
|
+
return message;
|
|
61
|
+
if (typeof message === "string")
|
|
62
|
+
return redactedText;
|
|
63
|
+
if (typeof message !== "object")
|
|
64
|
+
return message;
|
|
65
|
+
const msg = message;
|
|
66
|
+
const content = msg.content;
|
|
67
|
+
if (content == null)
|
|
68
|
+
return message;
|
|
69
|
+
if (typeof content === "string") {
|
|
70
|
+
return { ...msg, content: redactedText };
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(content)) {
|
|
73
|
+
const segments = redactedText.split(SEGMENT_SEP);
|
|
74
|
+
let segmentIndex = 0;
|
|
75
|
+
const newContent = content.map((block) => {
|
|
76
|
+
if (block != null &&
|
|
77
|
+
typeof block === "object" &&
|
|
78
|
+
block.type === "text" &&
|
|
79
|
+
typeof block.text === "string" &&
|
|
80
|
+
segmentIndex < segments.length) {
|
|
81
|
+
const replaced = { ...block, text: segments[segmentIndex] };
|
|
82
|
+
segmentIndex++;
|
|
83
|
+
return replaced;
|
|
84
|
+
}
|
|
85
|
+
return block;
|
|
86
|
+
});
|
|
87
|
+
return { ...msg, content: newContent };
|
|
88
|
+
}
|
|
89
|
+
return message;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,6DAA6D;AAC7D,uEAAuE;AACvE,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,IAAI,OAAO,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAE3C,MAAM,GAAG,GAAG,OAAkC,CAAC;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAE5B,IAAI,OAAO,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAEhD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IACE,KAAK,IAAI,IAAI;gBACb,OAAO,KAAK,KAAK,QAAQ;gBACxB,KAAiC,CAAC,IAAI,KAAK,MAAM;gBAClD,OAAQ,KAAiC,CAAC,IAAI,KAAK,QAAQ,EAC3D,CAAC;gBACD,SAAS,CAAC,IAAI,CAAE,KAAiC,CAAC,IAAc,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,OAAO,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,YAAoB;IAChE,IAAI,OAAO,IAAI,IAAI;QAAE,OAAO,OAAO,CAAC;IACpC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC;IACrD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAEhD,MAAM,GAAG,GAAG,OAAkC,CAAC;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAE5B,IAAI,OAAO,IAAI,IAAI;QAAE,OAAO,OAAO,CAAC;IAEpC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACvC,IACE,KAAK,IAAI,IAAI;gBACb,OAAO,KAAK,KAAK,QAAQ;gBACxB,KAAiC,CAAC,IAAI,KAAK,MAAM;gBAClD,OAAQ,KAAiC,CAAC,IAAI,KAAK,QAAQ;gBAC3D,YAAY,GAAG,QAAQ,CAAC,MAAM,EAC9B,CAAC;gBACD,MAAM,QAAQ,GAAG,EAAE,GAAI,KAAiC,EAAE,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACzF,YAAY,EAAE,CAAC;gBACf,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACzC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type { Entity, FogClawConfig, ScanResult, RedactResult, RedactStrategy, G
|
|
|
8
8
|
* Registers:
|
|
9
9
|
* - `before_agent_start` hook for automatic PII guardrail
|
|
10
10
|
* - `fogclaw_scan` tool for on-demand entity detection
|
|
11
|
+
* - `fogclaw_preview` tool for dry-run policy simulation
|
|
11
12
|
* - `fogclaw_redact` tool for on-demand redaction
|
|
12
13
|
*/
|
|
13
14
|
declare const fogclaw: {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,YAAY,EACZ,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAC;AAqEpB;;;;;;;;GAQG;AACH,QAAA,MAAM,OAAO;;;kBAIG,GAAG;CA8QlB,CAAC;AAEF,eAAe,OAAO,CAAC"}
|