@framers/agentos-ext-topicality 0.1.0 → 0.2.1
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 +18 -0
- package/dist/TopicalityGuardrail.d.ts +69 -154
- package/dist/TopicalityGuardrail.d.ts.map +1 -1
- package/dist/TopicalityGuardrail.js +229 -336
- package/dist/TopicalityGuardrail.js.map +1 -1
- package/dist/embeddings.d.ts +58 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +79 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/index.d.ts +42 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -160
- package/dist/index.js.map +1 -1
- package/dist/tools/CheckTopicTool.d.ts +39 -125
- package/dist/tools/CheckTopicTool.d.ts.map +1 -1
- package/dist/tools/CheckTopicTool.js +61 -168
- package/dist/tools/CheckTopicTool.js.map +1 -1
- package/dist/types.d.ts +85 -315
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +13 -202
- package/dist/types.js.map +1 -1
- package/package.json +12 -15
- package/src/TopicalityGuardrail.ts +265 -402
- package/src/embeddings.ts +84 -0
- package/src/index.ts +66 -188
- package/src/tools/CheckTopicTool.ts +73 -237
- package/src/types.ts +90 -505
- package/test/CheckTopicTool.spec.ts +271 -0
- package/test/TopicDriftTracker.spec.ts +422 -0
- package/test/TopicEmbeddingIndex.spec.ts +310 -0
- package/test/TopicalityGuardrail.spec.ts +610 -0
- package/test/index.spec.ts +312 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +24 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @framers/agentos-ext-topicality
|
|
2
|
+
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`15065c9`](https://github.com/framersai/agentos-extensions/commit/15065c949ea5d25f4408ffab2079ad3e600ddded) Thanks [@jddunn](https://github.com/jddunn)! - Fix npm publish: add missing repository.url field for sigstore provenance verification
|
|
8
|
+
|
|
9
|
+
## 0.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`c35afe8`](https://github.com/framersai/agentos-extensions/commit/c35afe8c16fdf51df6ce2d0bb83de6cd702e3a8b) Thanks [@jddunn](https://github.com/jddunn)! - Implement all 5 guardrail extension packs with full detection logic:
|
|
14
|
+
- PII Redaction: 4-tier detection (regex + keyword + NER + LLM)
|
|
15
|
+
- Code Safety: OWASP regex patterns for SQL injection, XSS, command injection
|
|
16
|
+
- ML Classifiers: toxicity/injection/NSFW via ONNX or LLM fallback
|
|
17
|
+
- Topicality: embedding-based topic enforcement with LLM fallback
|
|
18
|
+
- Grounding Guard: NLI-based hallucination detection against RAG sources
|
|
@@ -1,196 +1,111 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
2
|
+
* @file TopicalityGuardrail.ts
|
|
3
|
+
* @description Guardrail service that enforces on/off-topic boundaries for
|
|
4
|
+
* agent conversations using a three-tier evaluation strategy:
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* 1. **Embedding similarity** (primary) — cosine similarity between input
|
|
7
|
+
* and topic embeddings via `@huggingface/transformers`.
|
|
8
|
+
* 2. **LLM-as-judge** (fallback) — structured JSON classification prompt
|
|
9
|
+
* sent to the configured LLM invoker.
|
|
10
|
+
* 3. **Keyword matching** (last resort) — simple substring search against
|
|
11
|
+
* topic strings when neither embeddings nor LLM are available.
|
|
7
12
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* against *all* allowed topics are flagged (or blocked/redirected).
|
|
12
|
-
* 3. **Session drift** — An EMA-based tracker flags sustained drift away
|
|
13
|
-
* from allowed topics across consecutive messages.
|
|
13
|
+
* The guardrail only evaluates input (user messages). Output evaluation
|
|
14
|
+
* returns `null` (pass-through) because topic drift in agent responses is
|
|
15
|
+
* best handled at the input gate.
|
|
14
16
|
*
|
|
15
|
-
* ###
|
|
16
|
-
* Embedding indices are built on the **first evaluation call**, not at
|
|
17
|
-
* construction time. This keeps instantiation cheap and defers the
|
|
18
|
-
* potentially expensive batch embedding call until the agent actually
|
|
19
|
-
* receives its first message.
|
|
17
|
+
* ### Guardrail pipeline phase
|
|
20
18
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* logs a warning and returns `null` (pass) to avoid blocking legitimate
|
|
25
|
-
* traffic due to infrastructure failures.
|
|
19
|
+
* This guardrail sets `canSanitize: false` and `evaluateStreamingChunks: false`,
|
|
20
|
+
* placing it in Phase 2 (parallel) of the guardrail dispatcher. It never
|
|
21
|
+
* modifies content — it only FLAGs or BLOCKs.
|
|
26
22
|
*
|
|
27
|
-
* @module topicality/TopicalityGuardrail
|
|
23
|
+
* @module agentos/extensions/packs/topicality/TopicalityGuardrail
|
|
28
24
|
*/
|
|
29
|
-
import type {
|
|
30
|
-
import type {
|
|
31
|
-
import type { TopicalityPackOptions } from './types';
|
|
25
|
+
import type { IGuardrailService, GuardrailConfig, GuardrailInputPayload, GuardrailOutputPayload, GuardrailEvaluationResult } from '@framers/agentos';
|
|
26
|
+
import type { TopicalityOptions } from './types';
|
|
32
27
|
/**
|
|
33
|
-
* Guardrail that enforces
|
|
28
|
+
* Guardrail that enforces topic boundaries on user input.
|
|
34
29
|
*
|
|
35
|
-
* Implements {@link IGuardrailService} with
|
|
36
|
-
*
|
|
37
|
-
* never modifies content — it only blocks or flags.
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```ts
|
|
41
|
-
* const guardrail = new TopicalityGuardrail(registry, {
|
|
42
|
-
* allowedTopics: TOPIC_PRESETS.customerSupport,
|
|
43
|
-
* forbiddenTopics: TOPIC_PRESETS.commonUnsafe,
|
|
44
|
-
* forbiddenAction: 'block',
|
|
45
|
-
* offTopicAction: 'flag',
|
|
46
|
-
* }, embeddingFn);
|
|
47
|
-
*
|
|
48
|
-
* const result = await guardrail.evaluateInput(payload);
|
|
49
|
-
* if (result?.action === GuardrailAction.BLOCK) {
|
|
50
|
-
* // Reject the message
|
|
51
|
-
* }
|
|
52
|
-
* ```
|
|
30
|
+
* Implements {@link IGuardrailService} with input-only evaluation.
|
|
31
|
+
* Runs in Phase 2 (parallel, non-sanitizing) of the guardrail dispatcher.
|
|
53
32
|
*/
|
|
54
33
|
export declare class TopicalityGuardrail implements IGuardrailService {
|
|
55
34
|
/**
|
|
56
|
-
* Guardrail
|
|
57
|
-
*
|
|
58
|
-
* - `evaluateStreamingChunks: false` — topicality evaluation requires
|
|
59
|
-
* complete text, not partial deltas.
|
|
60
|
-
* - `canSanitize: false` — this guardrail only blocks or flags; it never
|
|
61
|
-
* modifies content, so it runs in Phase 2 (parallel) of the pipeline.
|
|
35
|
+
* Guardrail configuration — Phase 2 parallel (no sanitization, no streaming).
|
|
62
36
|
*/
|
|
63
37
|
readonly config: GuardrailConfig;
|
|
64
|
-
/**
|
|
65
|
-
private readonly
|
|
66
|
-
/** Resolved pack options with caller overrides. */
|
|
67
|
-
private readonly options;
|
|
68
|
-
/** Caller-supplied or registry-backed embedding function. */
|
|
69
|
-
private readonly embeddingFn;
|
|
70
|
-
/**
|
|
71
|
-
* Embedding index for allowed topics. Lazily built on the first
|
|
72
|
-
* evaluation call. `null` until built or if no allowed topics are
|
|
73
|
-
* configured.
|
|
74
|
-
*/
|
|
75
|
-
private allowedIndex;
|
|
76
|
-
/**
|
|
77
|
-
* Embedding index for forbidden topics. Lazily built on the first
|
|
78
|
-
* evaluation call. `null` until built or if no forbidden topics are
|
|
79
|
-
* configured.
|
|
80
|
-
*/
|
|
81
|
-
private forbiddenIndex;
|
|
82
|
-
/**
|
|
83
|
-
* Session-level EMA drift tracker. Only instantiated when
|
|
84
|
-
* `enableDriftDetection` is `true` (default). `null` otherwise.
|
|
85
|
-
*/
|
|
86
|
-
private driftTracker;
|
|
87
|
-
/**
|
|
88
|
-
* Which side of the conversation to evaluate.
|
|
89
|
-
* - `'input'` — only user messages
|
|
90
|
-
* - `'output'` — only agent responses
|
|
91
|
-
* - `'both'` — both directions
|
|
92
|
-
*/
|
|
93
|
-
private readonly scope;
|
|
38
|
+
/** Resolved options with defaults applied. */
|
|
39
|
+
private readonly opts;
|
|
94
40
|
/**
|
|
95
|
-
*
|
|
96
|
-
* considered on-topic.
|
|
41
|
+
* @param options - Topicality configuration provided by the pack factory.
|
|
97
42
|
*/
|
|
98
|
-
|
|
43
|
+
constructor(options: TopicalityOptions);
|
|
99
44
|
/**
|
|
100
|
-
*
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*/
|
|
107
|
-
private indicesBuilt;
|
|
108
|
-
/**
|
|
109
|
-
* Creates a new `TopicalityGuardrail`.
|
|
45
|
+
* Evaluate user input for topic relevance.
|
|
46
|
+
*
|
|
47
|
+
* Runs the three-tier evaluation strategy:
|
|
48
|
+
* 1. Embedding similarity (if `@huggingface/transformers` available)
|
|
49
|
+
* 2. LLM-as-judge (if `llmInvoker` configured)
|
|
50
|
+
* 3. Keyword matching (always available)
|
|
110
51
|
*
|
|
111
|
-
* @param
|
|
112
|
-
* @
|
|
113
|
-
* @param embeddingFn - Optional explicit embedding function. When omitted,
|
|
114
|
-
* the guardrail falls back to requesting an EmbeddingManager from the
|
|
115
|
-
* shared service registry at evaluation time.
|
|
52
|
+
* @param payload - The input payload containing user text and context.
|
|
53
|
+
* @returns A guardrail result (FLAG/BLOCK) or `null` to allow.
|
|
116
54
|
*/
|
|
117
|
-
|
|
55
|
+
evaluateInput(payload: GuardrailInputPayload): Promise<GuardrailEvaluationResult | null>;
|
|
118
56
|
/**
|
|
119
|
-
*
|
|
57
|
+
* Output evaluation — returns `null` (pass-through).
|
|
120
58
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* agent shuts down.
|
|
59
|
+
* Topic enforcement is applied at the input gate only. Agent responses
|
|
60
|
+
* are not evaluated for topicality.
|
|
124
61
|
*/
|
|
125
|
-
|
|
62
|
+
evaluateOutput(_payload: GuardrailOutputPayload): Promise<GuardrailEvaluationResult | null>;
|
|
126
63
|
/**
|
|
127
|
-
*
|
|
64
|
+
* Evaluate input via cosine similarity between embeddings.
|
|
128
65
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
66
|
+
* Embeds the input text and each topic string, then compares similarities
|
|
67
|
+
* against the configured thresholds.
|
|
131
68
|
*
|
|
132
|
-
* @param
|
|
133
|
-
*
|
|
134
|
-
* @returns A guardrail evaluation result (BLOCK or FLAG), or `null` if
|
|
135
|
-
* the message passes all topic checks. Returns `null` on any error
|
|
136
|
-
* (fail-open).
|
|
69
|
+
* @param text - The user input text.
|
|
70
|
+
* @returns A {@link TopicMatchResult} or `null` if embeddings are unavailable.
|
|
137
71
|
*/
|
|
138
|
-
|
|
72
|
+
private evaluateViaEmbeddings;
|
|
139
73
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* When `scope` is `'input'`, this method immediately returns `null`
|
|
143
|
-
* because output evaluation is disabled.
|
|
74
|
+
* Evaluate input via LLM classification prompt.
|
|
144
75
|
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* `false`, only FINAL_RESPONSE chunks are seen).
|
|
76
|
+
* Sends a structured prompt to the configured LLM invoker asking it to
|
|
77
|
+
* classify the input as on-topic or off-topic and return JSON.
|
|
148
78
|
*
|
|
149
|
-
* @param
|
|
150
|
-
*
|
|
151
|
-
* @returns A guardrail evaluation result (BLOCK or FLAG), or `null` if
|
|
152
|
-
* the output passes all topic checks. Returns `null` on any error
|
|
153
|
-
* (fail-open).
|
|
79
|
+
* @param text - The user input text.
|
|
80
|
+
* @returns A {@link TopicMatchResult} or `null` if no LLM invoker is configured.
|
|
154
81
|
*/
|
|
155
|
-
|
|
82
|
+
private evaluateViaLlm;
|
|
156
83
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* Evaluation order:
|
|
161
|
-
* 1. Forbidden topic check (highest priority — immediate block/flag)
|
|
162
|
-
* 2. Off-topic check against allowed topics
|
|
163
|
-
* 3. Session drift check (only if drift detection is enabled and allowed
|
|
164
|
-
* topics are configured)
|
|
84
|
+
* Evaluate input via simple case-insensitive substring matching against
|
|
85
|
+
* topic strings.
|
|
165
86
|
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* `null` if all checks pass.
|
|
87
|
+
* This is the fallback of last resort when neither embeddings nor LLM
|
|
88
|
+
* are available. It checks whether any topic string appears as a
|
|
89
|
+
* substring of the input (or vice versa).
|
|
170
90
|
*
|
|
171
|
-
* @
|
|
91
|
+
* @param text - The user input text.
|
|
92
|
+
* @returns A {@link TopicMatchResult}.
|
|
172
93
|
*/
|
|
173
|
-
private
|
|
94
|
+
private evaluateViaKeywords;
|
|
174
95
|
/**
|
|
175
|
-
*
|
|
96
|
+
* Convert a {@link TopicMatchResult} into a {@link GuardrailEvaluationResult}.
|
|
176
97
|
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
98
|
+
* - On-topic results return `null` (allow).
|
|
99
|
+
* - Blocked-topic matches return `BLOCK`.
|
|
100
|
+
* - Off-topic (below allowed threshold) returns `FLAG`.
|
|
179
101
|
*
|
|
180
|
-
* @
|
|
102
|
+
* @param result - The topic match result to convert.
|
|
103
|
+
* @returns A guardrail evaluation result, or `null` to allow.
|
|
181
104
|
*/
|
|
182
|
-
private
|
|
105
|
+
private toGuardrailResult;
|
|
183
106
|
/**
|
|
184
|
-
*
|
|
185
|
-
* the shared service registry at call time.
|
|
186
|
-
*
|
|
187
|
-
* This fallback is used when no explicit `embeddingFn` is provided to
|
|
188
|
-
* the constructor. It throws if the EmbeddingManager service is not
|
|
189
|
-
* available in the registry.
|
|
190
|
-
*
|
|
191
|
-
* @returns An async embedding function.
|
|
192
|
-
* @internal
|
|
107
|
+
* Clear cached embeddings. Called during pack deactivation.
|
|
193
108
|
*/
|
|
194
|
-
|
|
109
|
+
clearCache(): void;
|
|
195
110
|
}
|
|
196
111
|
//# sourceMappingURL=TopicalityGuardrail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TopicalityGuardrail.d.ts","sourceRoot":"","sources":["../src/TopicalityGuardrail.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"TopicalityGuardrail.d.ts","sourceRoot":"","sources":["../src/TopicalityGuardrail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,SAAS,CAAC;AA+DnE;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAG9B;IAEF,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAMmB;IAExC;;OAEG;gBACS,OAAO,EAAE,iBAAiB;IActC;;;;;;;;;;OAUG;IACG,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC;IAwB9F;;;;;OAKG;IACG,cAAc,CAClB,QAAQ,EAAE,sBAAsB,GAC/B,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC;IAQ5C;;;;;;;;OAQG;YACW,qBAAqB;IA+CnC;;;;;;;;OAQG;YACW,cAAc;IA0C5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,mBAAmB;IA+B3B;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IA6BzB;;OAEG;IACH,UAAU,IAAI,IAAI;CAGnB"}
|