plugin-sensitive-filter-xr 0.0.4 → 0.0.6
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/dist/lib/sensitiveFilter.d.ts.map +1 -1
- package/dist/lib/sensitiveFilter.js +316 -135
- package/dist/lib/types.d.ts +24 -30
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +3 -11
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensitiveFilter.d.ts","sourceRoot":"","sources":["../../src/lib/sensitiveFilter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,oBAAoB,EAA8B,MAAM,kBAAkB,CAAA;AAGnG,OAAO,EACL,eAAe,EAGf,uBAAuB,EACvB,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAOL,qBAAqB,EAMtB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"sensitiveFilter.d.ts","sourceRoot":"","sources":["../../src/lib/sensitiveFilter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,oBAAoB,EAA8B,MAAM,kBAAkB,CAAA;AAGnG,OAAO,EACL,eAAe,EAGf,uBAAuB,EACvB,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAOL,qBAAqB,EAMtB,MAAM,YAAY,CAAA;AAofnB,qBAEa,yBAA0B,YAAW,wBAAwB,CAAC,qBAAqB,CAAC;IAE/F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAqRlC;IAEK,gBAAgB,CACpB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,eAAe,CAAC;IAa3B,OAAO,CAAC,wBAAwB;IA+OhC,OAAO,CAAC,uBAAuB;CAwahC;AAED,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
|
|
@@ -11,7 +11,7 @@ const DEFAULT_OUTPUT_BLOCK_MESSAGE = '输出内容触发敏感策略,已拦截
|
|
|
11
11
|
const DEFAULT_REWRITE_TEXT = '[已过滤]';
|
|
12
12
|
const CONFIG_PARSE_ERROR = '敏感词过滤配置格式不正确,请检查填写内容。';
|
|
13
13
|
const BUSINESS_RULES_VALIDATION_ERROR = '请至少配置 1 条有效业务规则(pattern/type/action/scope/severity),或启用通用规则包。';
|
|
14
|
-
const LLM_MODE_VALIDATION_ERROR = '请完善 LLM
|
|
14
|
+
const LLM_MODE_VALIDATION_ERROR = '请完善 LLM 过滤配置:需填写过滤模型、生效范围、审核规则说明。';
|
|
15
15
|
function isRecord(value) {
|
|
16
16
|
return typeof value === 'object' && value !== null;
|
|
17
17
|
}
|
|
@@ -212,6 +212,14 @@ function normalizeRuleDrafts(input) {
|
|
|
212
212
|
function modeIncludesScope(scope, phase) {
|
|
213
213
|
return scope === 'both' || scope === phase;
|
|
214
214
|
}
|
|
215
|
+
function buildInternalLlmPrompt(rulePrompt) {
|
|
216
|
+
return ('你是敏感内容审核器。请根据用户给出的审核规则判断文本是否命中敏感内容。' +
|
|
217
|
+
'\n你只能返回 JSON,不要输出额外说明。' +
|
|
218
|
+
'\nJSON字段: matched(boolean), action("block"|"rewrite"), replacementText(string), reason(string), categories(string[]).' +
|
|
219
|
+
'\n命中时请尽量给出 replacementText;未命中时返回 {"matched": false}。' +
|
|
220
|
+
'\n说明:系统会统一执行改写策略,即便你返回 action=block 也会按 rewrite 处理。' +
|
|
221
|
+
`\n\n用户审核规则:\n${rulePrompt}`);
|
|
222
|
+
}
|
|
215
223
|
function parseLlmDecision(raw, rewriteFallbackText) {
|
|
216
224
|
let payload = raw;
|
|
217
225
|
if (typeof payload === 'string') {
|
|
@@ -248,14 +256,6 @@ function parseLlmDecision(raw, rewriteFallbackText) {
|
|
|
248
256
|
categories,
|
|
249
257
|
};
|
|
250
258
|
}
|
|
251
|
-
if (decision.action === 'block') {
|
|
252
|
-
return {
|
|
253
|
-
matched: true,
|
|
254
|
-
action: 'block',
|
|
255
|
-
reason,
|
|
256
|
-
categories,
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
259
|
return {
|
|
260
260
|
matched: true,
|
|
261
261
|
action: 'rewrite',
|
|
@@ -270,30 +270,27 @@ function resolveRuntimeLlmConfig(config) {
|
|
|
270
270
|
}
|
|
271
271
|
const model = isRecord(config.model) ? config.model : null;
|
|
272
272
|
const scope = toNonEmptyString(config.scope);
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
if (!model || !scope || !systemPrompt || !onLlmError) {
|
|
273
|
+
const rulePrompt = toNonEmptyString(config.rulePrompt) ?? toNonEmptyString(config.systemPrompt);
|
|
274
|
+
if (!model || !scope || !rulePrompt) {
|
|
276
275
|
throw new Error(LLM_MODE_VALIDATION_ERROR);
|
|
277
276
|
}
|
|
278
277
|
const outputMethodRaw = toNonEmptyString(config.outputMethod);
|
|
279
278
|
const outputMethod = ['functionCalling', 'jsonMode', 'jsonSchema'].includes(outputMethodRaw ?? '')
|
|
280
279
|
? outputMethodRaw
|
|
281
|
-
: '
|
|
282
|
-
const errorRewriteText = toNonEmptyString(config.errorRewriteText) ?? undefined;
|
|
283
|
-
if (onLlmError === 'rewrite' && !errorRewriteText) {
|
|
284
|
-
throw new Error('请完善 LLM 过滤配置:当失败处理为改写时,必须填写失败改写文本。');
|
|
285
|
-
}
|
|
280
|
+
: 'jsonMode';
|
|
286
281
|
const timeoutMs = typeof config.timeoutMs === 'number' && Number.isFinite(config.timeoutMs) && config.timeoutMs > 0
|
|
287
282
|
? Math.min(Math.floor(config.timeoutMs), 120000)
|
|
288
283
|
: undefined;
|
|
284
|
+
const legacyOnLlmError = toNonEmptyString(config.onLlmError);
|
|
285
|
+
const legacyErrorRewriteText = toNonEmptyString(config.errorRewriteText) ?? undefined;
|
|
289
286
|
return {
|
|
290
287
|
model,
|
|
291
288
|
scope,
|
|
292
|
-
|
|
289
|
+
rulePrompt,
|
|
290
|
+
systemPrompt: buildInternalLlmPrompt(rulePrompt),
|
|
293
291
|
outputMethod,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
blockMessage: toNonEmptyString(config.blockMessage) ?? undefined,
|
|
292
|
+
legacyOnLlmError: legacyOnLlmError ?? undefined,
|
|
293
|
+
legacyErrorRewriteText,
|
|
297
294
|
rewriteFallbackText: toNonEmptyString(config.rewriteFallbackText) ?? DEFAULT_REWRITE_TEXT,
|
|
298
295
|
timeoutMs,
|
|
299
296
|
};
|
|
@@ -317,6 +314,54 @@ function withTimeout(promise, timeoutMs) {
|
|
|
317
314
|
});
|
|
318
315
|
});
|
|
319
316
|
}
|
|
317
|
+
function normalizeConfigurable(input) {
|
|
318
|
+
if (!isRecord(input)) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
return input;
|
|
322
|
+
}
|
|
323
|
+
function buildOutputMethodCandidates(preferred) {
|
|
324
|
+
const queue = [preferred, 'functionCalling', 'jsonMode', 'jsonSchema'];
|
|
325
|
+
const unique = [];
|
|
326
|
+
for (const method of queue) {
|
|
327
|
+
if (!unique.includes(method)) {
|
|
328
|
+
unique.push(method);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return unique;
|
|
332
|
+
}
|
|
333
|
+
function getErrorText(error) {
|
|
334
|
+
if (error instanceof Error) {
|
|
335
|
+
return error.message;
|
|
336
|
+
}
|
|
337
|
+
return String(error ?? '');
|
|
338
|
+
}
|
|
339
|
+
function isUnsupportedStructuredOutputError(error) {
|
|
340
|
+
const message = getErrorText(error).toLowerCase();
|
|
341
|
+
const patterns = [
|
|
342
|
+
'response_format type is unavailable',
|
|
343
|
+
'invalid response_format',
|
|
344
|
+
'response_format',
|
|
345
|
+
'unsupported schema',
|
|
346
|
+
'not support',
|
|
347
|
+
];
|
|
348
|
+
return patterns.some((pattern) => message.includes(pattern));
|
|
349
|
+
}
|
|
350
|
+
function isMissingWrapWorkflowHandlerError(error) {
|
|
351
|
+
const message = getErrorText(error).toLowerCase();
|
|
352
|
+
return message.includes('no handler found') && message.includes('wrapworkflownodeexecutioncommand');
|
|
353
|
+
}
|
|
354
|
+
async function runWithWrapWorkflowFallback(runTracked, runFallback) {
|
|
355
|
+
try {
|
|
356
|
+
return await runTracked();
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
if (isMissingWrapWorkflowHandlerError(error)) {
|
|
360
|
+
return runFallback();
|
|
361
|
+
}
|
|
362
|
+
throw error;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
320
365
|
let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
321
366
|
constructor() {
|
|
322
367
|
this.meta = {
|
|
@@ -534,19 +579,27 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
534
579
|
},
|
|
535
580
|
},
|
|
536
581
|
},
|
|
537
|
-
|
|
582
|
+
rulePrompt: {
|
|
538
583
|
type: 'string',
|
|
539
|
-
title: { en_US: '
|
|
584
|
+
title: { en_US: 'Rule Prompt', zh_Hans: '审核规则说明' },
|
|
585
|
+
description: {
|
|
586
|
+
en_US: 'Describe your moderation rules in natural language. No JSON format is required.',
|
|
587
|
+
zh_Hans: '用自然语言描述审核规则,无需手写 JSON 格式。',
|
|
588
|
+
},
|
|
540
589
|
'x-ui': {
|
|
541
590
|
component: 'textarea',
|
|
542
591
|
span: 2,
|
|
592
|
+
placeholder: {
|
|
593
|
+
en_US: 'e.g. Rewrite violent/privacy-sensitive content into a safe neutral response.',
|
|
594
|
+
zh_Hans: '例如:涉及暴力或隐私泄露内容时,改写为安全中性表达。',
|
|
595
|
+
},
|
|
543
596
|
},
|
|
544
597
|
},
|
|
545
598
|
outputMethod: {
|
|
546
599
|
type: 'string',
|
|
547
600
|
title: { en_US: 'Output Method', zh_Hans: '结构化输出方式' },
|
|
548
601
|
enum: ['functionCalling', 'jsonMode', 'jsonSchema'],
|
|
549
|
-
default: '
|
|
602
|
+
default: 'jsonMode',
|
|
550
603
|
'x-ui': {
|
|
551
604
|
enumLabels: {
|
|
552
605
|
functionCalling: { en_US: 'Function Calling', zh_Hans: '函数调用' },
|
|
@@ -555,25 +608,6 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
555
608
|
},
|
|
556
609
|
},
|
|
557
610
|
},
|
|
558
|
-
onLlmError: {
|
|
559
|
-
type: 'string',
|
|
560
|
-
title: { en_US: 'On LLM Error', zh_Hans: 'LLM失败处理' },
|
|
561
|
-
enum: ['block', 'rewrite'],
|
|
562
|
-
'x-ui': {
|
|
563
|
-
enumLabels: {
|
|
564
|
-
block: { en_US: 'Block', zh_Hans: '拦截' },
|
|
565
|
-
rewrite: { en_US: 'Rewrite', zh_Hans: '改写' },
|
|
566
|
-
},
|
|
567
|
-
},
|
|
568
|
-
},
|
|
569
|
-
errorRewriteText: {
|
|
570
|
-
type: 'string',
|
|
571
|
-
title: { en_US: 'Error Rewrite Text', zh_Hans: '失败改写文本' },
|
|
572
|
-
},
|
|
573
|
-
blockMessage: {
|
|
574
|
-
type: 'string',
|
|
575
|
-
title: { en_US: 'Block Message', zh_Hans: '拦截提示文本' },
|
|
576
|
-
},
|
|
577
611
|
rewriteFallbackText: {
|
|
578
612
|
type: 'string',
|
|
579
613
|
title: { en_US: 'Rewrite Fallback Text', zh_Hans: '改写兜底文本' },
|
|
@@ -583,21 +617,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
583
617
|
title: { en_US: 'Timeout (ms)', zh_Hans: '超时毫秒' },
|
|
584
618
|
},
|
|
585
619
|
},
|
|
586
|
-
required: ['model', 'scope', '
|
|
587
|
-
allOf: [
|
|
588
|
-
{
|
|
589
|
-
if: {
|
|
590
|
-
properties: {
|
|
591
|
-
onLlmError: {
|
|
592
|
-
const: 'rewrite',
|
|
593
|
-
},
|
|
594
|
-
},
|
|
595
|
-
},
|
|
596
|
-
then: {
|
|
597
|
-
required: ['errorRewriteText'],
|
|
598
|
-
},
|
|
599
|
-
},
|
|
600
|
-
],
|
|
620
|
+
required: ['model', 'scope', 'rulePrompt'],
|
|
601
621
|
},
|
|
602
622
|
},
|
|
603
623
|
required: ['mode'],
|
|
@@ -626,9 +646,9 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
626
646
|
if (parsed.data.mode === 'llm') {
|
|
627
647
|
return this.createLlmModeMiddleware(parsed.data, context);
|
|
628
648
|
}
|
|
629
|
-
return this.createRuleModeMiddleware(parsed.data);
|
|
649
|
+
return this.createRuleModeMiddleware(parsed.data, context);
|
|
630
650
|
}
|
|
631
|
-
createRuleModeMiddleware(config) {
|
|
651
|
+
createRuleModeMiddleware(config, context) {
|
|
632
652
|
const caseSensitive = config.caseSensitive ?? false;
|
|
633
653
|
const normalize = config.normalize ?? true;
|
|
634
654
|
const customRules = normalizeRuleDrafts(config.rules ?? []);
|
|
@@ -669,6 +689,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
669
689
|
let pendingInputRewrite = null;
|
|
670
690
|
let finalAction = 'pass';
|
|
671
691
|
let auditEntries = [];
|
|
692
|
+
let runtimeConfigurable = null;
|
|
672
693
|
const resetRunState = () => {
|
|
673
694
|
inputBlockedMessage = null;
|
|
674
695
|
pendingInputRewrite = null;
|
|
@@ -682,10 +703,72 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
682
703
|
mode: 'rule',
|
|
683
704
|
});
|
|
684
705
|
};
|
|
706
|
+
const assignRuntimeConfigurable = (runtimeLike) => {
|
|
707
|
+
const configurable = normalizeConfigurable(runtimeLike?.configurable);
|
|
708
|
+
if (!configurable) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
if (configurable.thread_id && configurable.executionId) {
|
|
712
|
+
runtimeConfigurable = configurable;
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
const buildAuditSnapshot = () => {
|
|
716
|
+
const summary = {
|
|
717
|
+
total: auditEntries.length,
|
|
718
|
+
matched: auditEntries.filter((entry) => entry.matched).length,
|
|
719
|
+
blocked: auditEntries.filter((entry) => entry.action === 'block').length,
|
|
720
|
+
rewritten: auditEntries.filter((entry) => entry.action === 'rewrite').length,
|
|
721
|
+
errorPolicyTriggered: auditEntries.filter((entry) => entry.errorPolicyTriggered).length,
|
|
722
|
+
};
|
|
723
|
+
return {
|
|
724
|
+
mode: 'rule',
|
|
725
|
+
finalAction,
|
|
726
|
+
records: auditEntries,
|
|
727
|
+
summary,
|
|
728
|
+
};
|
|
729
|
+
};
|
|
730
|
+
const persistAuditSnapshot = async () => {
|
|
731
|
+
const configurable = runtimeConfigurable;
|
|
732
|
+
if (!configurable?.thread_id || !configurable.executionId || !this.commandBus) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const { thread_id, checkpoint_ns, checkpoint_id, subscriber, executionId } = configurable;
|
|
736
|
+
const snapshot = buildAuditSnapshot();
|
|
737
|
+
const writeSnapshot = async () => {
|
|
738
|
+
return {
|
|
739
|
+
state: snapshot,
|
|
740
|
+
output: snapshot,
|
|
741
|
+
};
|
|
742
|
+
};
|
|
743
|
+
await runWithWrapWorkflowFallback(async () => {
|
|
744
|
+
await this.commandBus.execute(new WrapWorkflowNodeExecutionCommand(writeSnapshot, {
|
|
745
|
+
execution: {
|
|
746
|
+
category: 'workflow',
|
|
747
|
+
type: 'middleware',
|
|
748
|
+
title: `${context.node.title} Audit`,
|
|
749
|
+
inputs: {
|
|
750
|
+
mode: snapshot.mode,
|
|
751
|
+
total: snapshot.summary.total,
|
|
752
|
+
},
|
|
753
|
+
parentId: executionId,
|
|
754
|
+
threadId: thread_id,
|
|
755
|
+
checkpointNs: checkpoint_ns,
|
|
756
|
+
checkpointId: checkpoint_id,
|
|
757
|
+
agentKey: context.node.key,
|
|
758
|
+
},
|
|
759
|
+
subscriber,
|
|
760
|
+
}));
|
|
761
|
+
return undefined;
|
|
762
|
+
}, async () => {
|
|
763
|
+
await writeSnapshot();
|
|
764
|
+
return undefined;
|
|
765
|
+
});
|
|
766
|
+
};
|
|
685
767
|
return {
|
|
686
768
|
name: SENSITIVE_FILTER_MIDDLEWARE_NAME,
|
|
687
769
|
beforeAgent: async (state, runtime) => {
|
|
688
770
|
resetRunState();
|
|
771
|
+
assignRuntimeConfigurable(runtime);
|
|
689
772
|
if (!hasEffectiveRules) {
|
|
690
773
|
throw new Error(BUSINESS_RULES_VALIDATION_ERROR);
|
|
691
774
|
}
|
|
@@ -722,6 +805,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
722
805
|
return undefined;
|
|
723
806
|
},
|
|
724
807
|
wrapModelCall: async (request, handler) => {
|
|
808
|
+
assignRuntimeConfigurable(request?.runtime);
|
|
725
809
|
if (!hasEffectiveRules) {
|
|
726
810
|
throw new Error(BUSINESS_RULES_VALIDATION_ERROR);
|
|
727
811
|
}
|
|
@@ -762,11 +846,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
762
846
|
return replaceModelResponseText(response, rewrittenOutput);
|
|
763
847
|
},
|
|
764
848
|
afterAgent: async () => {
|
|
765
|
-
|
|
766
|
-
mode: 'rule',
|
|
767
|
-
finalAction,
|
|
768
|
-
records: auditEntries,
|
|
769
|
-
}, null, 2));
|
|
849
|
+
await persistAuditSnapshot();
|
|
770
850
|
return undefined;
|
|
771
851
|
},
|
|
772
852
|
};
|
|
@@ -775,7 +855,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
775
855
|
const llmDraftConfig = config.llm;
|
|
776
856
|
let resolvedLlmConfig = null;
|
|
777
857
|
let modelPromise = null;
|
|
778
|
-
|
|
858
|
+
const structuredModelPromises = new Map();
|
|
779
859
|
const getLlmConfig = () => {
|
|
780
860
|
if (!resolvedLlmConfig) {
|
|
781
861
|
resolvedLlmConfig = resolveRuntimeLlmConfig(llmDraftConfig);
|
|
@@ -786,34 +866,36 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
786
866
|
const llmConfig = getLlmConfig();
|
|
787
867
|
if (!modelPromise) {
|
|
788
868
|
modelPromise = this.commandBus.execute(new CreateModelClientCommand(llmConfig.model, {
|
|
789
|
-
usageCallback: (
|
|
790
|
-
console.log('[SensitiveFilterMiddleware][LLM] Model Usage:', event);
|
|
791
|
-
},
|
|
869
|
+
usageCallback: () => { },
|
|
792
870
|
}));
|
|
793
871
|
}
|
|
794
872
|
return modelPromise;
|
|
795
873
|
};
|
|
796
|
-
const ensureStructuredModel = async () => {
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
structuredModelPromise = (async () => {
|
|
874
|
+
const ensureStructuredModel = async (method) => {
|
|
875
|
+
if (!structuredModelPromises.has(method)) {
|
|
876
|
+
structuredModelPromises.set(method, (async () => {
|
|
800
877
|
const model = await ensureModel();
|
|
801
878
|
return model.withStructuredOutput?.(llmDecisionSchema, {
|
|
802
|
-
method
|
|
879
|
+
method,
|
|
803
880
|
}) ?? null;
|
|
804
|
-
})();
|
|
881
|
+
})());
|
|
805
882
|
}
|
|
806
|
-
return
|
|
883
|
+
return structuredModelPromises.get(method);
|
|
807
884
|
};
|
|
808
|
-
let inputBlockedMessage = null;
|
|
809
885
|
let pendingInputRewrite = null;
|
|
810
886
|
let finalAction = 'pass';
|
|
811
887
|
let auditEntries = [];
|
|
888
|
+
let runtimeConfigurable = null;
|
|
889
|
+
let resolvedOutputMethod;
|
|
890
|
+
let fallbackTriggered = false;
|
|
891
|
+
let methodAttempts = [];
|
|
812
892
|
const resetRunState = () => {
|
|
813
|
-
inputBlockedMessage = null;
|
|
814
893
|
pendingInputRewrite = null;
|
|
815
894
|
finalAction = 'pass';
|
|
816
895
|
auditEntries = [];
|
|
896
|
+
resolvedOutputMethod = undefined;
|
|
897
|
+
fallbackTriggered = false;
|
|
898
|
+
methodAttempts = [];
|
|
817
899
|
};
|
|
818
900
|
const pushAudit = (entry) => {
|
|
819
901
|
auditEntries.push({
|
|
@@ -822,6 +904,84 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
822
904
|
mode: 'llm',
|
|
823
905
|
});
|
|
824
906
|
};
|
|
907
|
+
const assignRuntimeConfigurable = (runtimeLike) => {
|
|
908
|
+
const configurable = normalizeConfigurable(runtimeLike?.configurable);
|
|
909
|
+
if (!configurable) {
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
if (configurable.thread_id && configurable.executionId) {
|
|
913
|
+
runtimeConfigurable = configurable;
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
const captureLlmOutputTrace = (trace) => {
|
|
917
|
+
for (const method of trace.methodAttempts) {
|
|
918
|
+
if (!methodAttempts.includes(method)) {
|
|
919
|
+
methodAttempts.push(method);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
resolvedOutputMethod = trace.resolvedOutputMethod;
|
|
923
|
+
fallbackTriggered = fallbackTriggered || trace.fallbackTriggered;
|
|
924
|
+
};
|
|
925
|
+
const buildAuditSnapshot = () => {
|
|
926
|
+
const summary = {
|
|
927
|
+
total: auditEntries.length,
|
|
928
|
+
matched: auditEntries.filter((entry) => entry.matched).length,
|
|
929
|
+
blocked: auditEntries.filter((entry) => entry.action === 'block').length,
|
|
930
|
+
rewritten: auditEntries.filter((entry) => entry.action === 'rewrite').length,
|
|
931
|
+
errorPolicyTriggered: auditEntries.filter((entry) => entry.errorPolicyTriggered).length,
|
|
932
|
+
};
|
|
933
|
+
return {
|
|
934
|
+
mode: 'llm',
|
|
935
|
+
finalAction,
|
|
936
|
+
records: auditEntries,
|
|
937
|
+
summary,
|
|
938
|
+
llmOutput: resolvedLlmConfig
|
|
939
|
+
? {
|
|
940
|
+
requestedOutputMethod: resolvedLlmConfig.outputMethod,
|
|
941
|
+
resolvedOutputMethod,
|
|
942
|
+
methodAttempts,
|
|
943
|
+
fallbackTriggered,
|
|
944
|
+
}
|
|
945
|
+
: undefined,
|
|
946
|
+
};
|
|
947
|
+
};
|
|
948
|
+
const persistAuditSnapshot = async () => {
|
|
949
|
+
const configurable = runtimeConfigurable;
|
|
950
|
+
if (!configurable?.thread_id || !configurable.executionId || !this.commandBus) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const { thread_id, checkpoint_ns, checkpoint_id, subscriber, executionId } = configurable;
|
|
954
|
+
const snapshot = buildAuditSnapshot();
|
|
955
|
+
const writeSnapshot = async () => {
|
|
956
|
+
return {
|
|
957
|
+
state: snapshot,
|
|
958
|
+
output: snapshot,
|
|
959
|
+
};
|
|
960
|
+
};
|
|
961
|
+
await runWithWrapWorkflowFallback(async () => {
|
|
962
|
+
await this.commandBus.execute(new WrapWorkflowNodeExecutionCommand(writeSnapshot, {
|
|
963
|
+
execution: {
|
|
964
|
+
category: 'workflow',
|
|
965
|
+
type: 'middleware',
|
|
966
|
+
title: `${context.node.title} Audit`,
|
|
967
|
+
inputs: {
|
|
968
|
+
mode: snapshot.mode,
|
|
969
|
+
total: snapshot.summary.total,
|
|
970
|
+
},
|
|
971
|
+
parentId: executionId,
|
|
972
|
+
threadId: thread_id,
|
|
973
|
+
checkpointNs: checkpoint_ns,
|
|
974
|
+
checkpointId: checkpoint_id,
|
|
975
|
+
agentKey: context.node.key,
|
|
976
|
+
},
|
|
977
|
+
subscriber,
|
|
978
|
+
}));
|
|
979
|
+
return undefined;
|
|
980
|
+
}, async () => {
|
|
981
|
+
await writeSnapshot();
|
|
982
|
+
return undefined;
|
|
983
|
+
});
|
|
984
|
+
};
|
|
825
985
|
const buildEvaluationMessages = (phase, text, llmConfig) => {
|
|
826
986
|
return [
|
|
827
987
|
{ role: 'system', content: llmConfig.systemPrompt },
|
|
@@ -836,14 +996,49 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
836
996
|
const invokeAndTrack = async (phase, text, runtime, llmConfig) => {
|
|
837
997
|
const invokeCore = async () => {
|
|
838
998
|
const messages = buildEvaluationMessages(phase, text, llmConfig);
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
999
|
+
const model = await ensureModel();
|
|
1000
|
+
const candidates = buildOutputMethodCandidates(llmConfig.outputMethod);
|
|
1001
|
+
const attempts = [];
|
|
1002
|
+
for (const method of candidates) {
|
|
1003
|
+
attempts.push(method);
|
|
1004
|
+
try {
|
|
1005
|
+
const structuredModel = await ensureStructuredModel(method);
|
|
1006
|
+
if (!structuredModel) {
|
|
1007
|
+
throw new Error(`Structured output is not available for method: ${method}`);
|
|
1008
|
+
}
|
|
1009
|
+
const raw = await withTimeout(structuredModel.invoke(messages), llmConfig.timeoutMs);
|
|
1010
|
+
return {
|
|
1011
|
+
raw,
|
|
1012
|
+
trace: {
|
|
1013
|
+
requestedOutputMethod: llmConfig.outputMethod,
|
|
1014
|
+
resolvedOutputMethod: method,
|
|
1015
|
+
methodAttempts: attempts,
|
|
1016
|
+
fallbackTriggered: method !== llmConfig.outputMethod || attempts.length > 1,
|
|
1017
|
+
},
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
catch (error) {
|
|
1021
|
+
if (isUnsupportedStructuredOutputError(error)) {
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
throw error;
|
|
1025
|
+
}
|
|
842
1026
|
}
|
|
843
|
-
|
|
1027
|
+
attempts.push('plainText');
|
|
1028
|
+
const raw = await withTimeout(model.invoke(messages), llmConfig.timeoutMs);
|
|
1029
|
+
return {
|
|
1030
|
+
raw,
|
|
1031
|
+
trace: {
|
|
1032
|
+
requestedOutputMethod: llmConfig.outputMethod,
|
|
1033
|
+
resolvedOutputMethod: 'plainText',
|
|
1034
|
+
methodAttempts: attempts,
|
|
1035
|
+
fallbackTriggered: true,
|
|
1036
|
+
},
|
|
1037
|
+
};
|
|
844
1038
|
};
|
|
845
1039
|
const parseCore = async () => {
|
|
846
|
-
const raw = await invokeCore();
|
|
1040
|
+
const { raw, trace } = await invokeCore();
|
|
1041
|
+
captureLlmOutputTrace(trace);
|
|
847
1042
|
return parseLlmDecision(raw, llmConfig.rewriteFallbackText);
|
|
848
1043
|
};
|
|
849
1044
|
const configurable = (runtime?.configurable ?? {});
|
|
@@ -851,55 +1046,56 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
851
1046
|
if (!thread_id || !executionId) {
|
|
852
1047
|
return parseCore();
|
|
853
1048
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1049
|
+
let trackedDecision = null;
|
|
1050
|
+
await runWithWrapWorkflowFallback(async () => {
|
|
1051
|
+
await this.commandBus.execute(new WrapWorkflowNodeExecutionCommand(async () => {
|
|
1052
|
+
const decision = await parseCore();
|
|
1053
|
+
trackedDecision = decision;
|
|
1054
|
+
return {
|
|
1055
|
+
state: decision,
|
|
1056
|
+
output: decision,
|
|
1057
|
+
};
|
|
1058
|
+
}, {
|
|
1059
|
+
execution: {
|
|
1060
|
+
category: 'workflow',
|
|
1061
|
+
type: 'middleware',
|
|
1062
|
+
inputs: {
|
|
1063
|
+
phase,
|
|
1064
|
+
text,
|
|
1065
|
+
},
|
|
1066
|
+
parentId: executionId,
|
|
1067
|
+
threadId: thread_id,
|
|
1068
|
+
checkpointNs: checkpoint_ns,
|
|
1069
|
+
checkpointId: checkpoint_id,
|
|
1070
|
+
agentKey: context.node.key,
|
|
1071
|
+
title: context.node.title,
|
|
867
1072
|
},
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1073
|
+
subscriber,
|
|
1074
|
+
}));
|
|
1075
|
+
return undefined;
|
|
1076
|
+
}, async () => {
|
|
1077
|
+
trackedDecision = await parseCore();
|
|
1078
|
+
return undefined;
|
|
1079
|
+
});
|
|
1080
|
+
if (!trackedDecision) {
|
|
1081
|
+
throw new Error('LLM decision tracking failed: no decision resolved');
|
|
1082
|
+
}
|
|
1083
|
+
return trackedDecision;
|
|
878
1084
|
};
|
|
879
1085
|
const resolveOnErrorDecision = (llmConfig, error) => {
|
|
880
1086
|
const reason = `llm-error:${error instanceof Error ? error.message : String(error)}`;
|
|
881
|
-
if (llmConfig.onLlmError === 'block') {
|
|
882
|
-
return {
|
|
883
|
-
matched: true,
|
|
884
|
-
action: 'block',
|
|
885
|
-
reason,
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
1087
|
return {
|
|
889
1088
|
matched: true,
|
|
890
1089
|
action: 'rewrite',
|
|
891
|
-
replacementText: llmConfig.
|
|
1090
|
+
replacementText: llmConfig.legacyErrorRewriteText ?? llmConfig.rewriteFallbackText,
|
|
892
1091
|
reason,
|
|
893
1092
|
};
|
|
894
1093
|
};
|
|
895
|
-
const resolveBlockMessage = (llmConfig, phase) => {
|
|
896
|
-
return llmConfig.blockMessage ??
|
|
897
|
-
(phase === 'input' ? DEFAULT_INPUT_BLOCK_MESSAGE : DEFAULT_OUTPUT_BLOCK_MESSAGE);
|
|
898
|
-
};
|
|
899
1094
|
return {
|
|
900
1095
|
name: SENSITIVE_FILTER_MIDDLEWARE_NAME,
|
|
901
1096
|
beforeAgent: async (state, runtime) => {
|
|
902
1097
|
resetRunState();
|
|
1098
|
+
assignRuntimeConfigurable(runtime);
|
|
903
1099
|
const llmConfig = getLlmConfig();
|
|
904
1100
|
if (!modeIncludesScope(llmConfig.scope, 'input')) {
|
|
905
1101
|
pushAudit({
|
|
@@ -942,20 +1138,13 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
942
1138
|
if (!decision.matched || !decision.action) {
|
|
943
1139
|
return undefined;
|
|
944
1140
|
}
|
|
945
|
-
if (decision.action === 'block') {
|
|
946
|
-
finalAction = 'block';
|
|
947
|
-
inputBlockedMessage = resolveBlockMessage(llmConfig, 'input');
|
|
948
|
-
return undefined;
|
|
949
|
-
}
|
|
950
1141
|
finalAction = 'rewrite';
|
|
951
1142
|
pendingInputRewrite = toNonEmptyString(decision.replacementText) ?? llmConfig.rewriteFallbackText;
|
|
952
1143
|
return undefined;
|
|
953
1144
|
},
|
|
954
1145
|
wrapModelCall: async (request, handler) => {
|
|
1146
|
+
assignRuntimeConfigurable(request?.runtime);
|
|
955
1147
|
const llmConfig = getLlmConfig();
|
|
956
|
-
if (inputBlockedMessage) {
|
|
957
|
-
return new AIMessage(inputBlockedMessage);
|
|
958
|
-
}
|
|
959
1148
|
const modelRequest = pendingInputRewrite ? rewriteModelRequestInput(request, pendingInputRewrite) : request;
|
|
960
1149
|
pendingInputRewrite = null;
|
|
961
1150
|
const response = await handler(modelRequest);
|
|
@@ -1000,19 +1189,11 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
|
|
|
1000
1189
|
if (!decision.matched || !decision.action) {
|
|
1001
1190
|
return response;
|
|
1002
1191
|
}
|
|
1003
|
-
if (decision.action === 'block') {
|
|
1004
|
-
finalAction = 'block';
|
|
1005
|
-
return replaceModelResponseText(response, resolveBlockMessage(llmConfig, 'output'));
|
|
1006
|
-
}
|
|
1007
1192
|
finalAction = 'rewrite';
|
|
1008
1193
|
return replaceModelResponseText(response, toNonEmptyString(decision.replacementText) ?? llmConfig.rewriteFallbackText);
|
|
1009
1194
|
},
|
|
1010
1195
|
afterAgent: async () => {
|
|
1011
|
-
|
|
1012
|
-
mode: 'llm',
|
|
1013
|
-
finalAction,
|
|
1014
|
-
records: auditEntries,
|
|
1015
|
-
}, null, 2));
|
|
1196
|
+
await persistAuditSnapshot();
|
|
1016
1197
|
return undefined;
|
|
1017
1198
|
},
|
|
1018
1199
|
};
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export type LlmErrorAction = 'block' | 'rewrite';
|
|
|
26
26
|
export type LlmFilterConfig = {
|
|
27
27
|
model?: ICopilotModel;
|
|
28
28
|
scope?: LlmScope;
|
|
29
|
+
rulePrompt?: string;
|
|
29
30
|
systemPrompt?: string;
|
|
30
31
|
outputMethod?: LlmOutputMethod;
|
|
31
32
|
onLlmError?: LlmErrorAction;
|
|
@@ -64,17 +65,17 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
64
65
|
action: z.ZodNullable<z.ZodOptional<z.ZodEnum<["block", "rewrite"]>>>;
|
|
65
66
|
replacementText: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
66
67
|
}, "strip", z.ZodTypeAny, {
|
|
67
|
-
type?: "keyword" | "regex";
|
|
68
68
|
id?: string;
|
|
69
69
|
pattern?: string;
|
|
70
|
+
type?: "keyword" | "regex";
|
|
70
71
|
scope?: "input" | "output" | "both";
|
|
71
72
|
severity?: "high" | "medium";
|
|
72
73
|
action?: "block" | "rewrite";
|
|
73
74
|
replacementText?: string;
|
|
74
75
|
}, {
|
|
75
|
-
type?: "keyword" | "regex";
|
|
76
76
|
id?: string;
|
|
77
77
|
pattern?: string;
|
|
78
|
+
type?: "keyword" | "regex";
|
|
78
79
|
scope?: "input" | "output" | "both";
|
|
79
80
|
severity?: "high" | "medium";
|
|
80
81
|
action?: "block" | "rewrite";
|
|
@@ -94,13 +95,11 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
94
95
|
normalize: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
95
96
|
llm: z.ZodOptional<z.ZodUnknown>;
|
|
96
97
|
}, "strip", z.ZodTypeAny, {
|
|
97
|
-
normalize?: boolean;
|
|
98
|
-
llm?: unknown;
|
|
99
98
|
mode?: "rule";
|
|
100
99
|
rules?: {
|
|
101
|
-
type?: "keyword" | "regex";
|
|
102
100
|
id?: string;
|
|
103
101
|
pattern?: string;
|
|
102
|
+
type?: "keyword" | "regex";
|
|
104
103
|
scope?: "input" | "output" | "both";
|
|
105
104
|
severity?: "high" | "medium";
|
|
106
105
|
action?: "block" | "rewrite";
|
|
@@ -111,14 +110,14 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
111
110
|
profile?: "strict" | "balanced";
|
|
112
111
|
};
|
|
113
112
|
caseSensitive?: boolean;
|
|
114
|
-
}, {
|
|
115
113
|
normalize?: boolean;
|
|
116
114
|
llm?: unknown;
|
|
115
|
+
}, {
|
|
117
116
|
mode?: "rule";
|
|
118
117
|
rules?: {
|
|
119
|
-
type?: "keyword" | "regex";
|
|
120
118
|
id?: string;
|
|
121
119
|
pattern?: string;
|
|
120
|
+
type?: "keyword" | "regex";
|
|
122
121
|
scope?: "input" | "output" | "both";
|
|
123
122
|
severity?: "high" | "medium";
|
|
124
123
|
action?: "block" | "rewrite";
|
|
@@ -129,11 +128,14 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
129
128
|
profile?: "strict" | "balanced";
|
|
130
129
|
};
|
|
131
130
|
caseSensitive?: boolean;
|
|
131
|
+
normalize?: boolean;
|
|
132
|
+
llm?: unknown;
|
|
132
133
|
}>, z.ZodObject<{
|
|
133
134
|
mode: z.ZodLiteral<"llm">;
|
|
134
135
|
llm: z.ZodDefault<z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
135
136
|
model: z.ZodNullable<z.ZodOptional<z.ZodType<ICopilotModel, z.ZodTypeDef, ICopilotModel>>>;
|
|
136
137
|
scope: z.ZodNullable<z.ZodOptional<z.ZodEnum<["input", "output", "both"]>>>;
|
|
138
|
+
rulePrompt: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
137
139
|
systemPrompt: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
138
140
|
outputMethod: z.ZodDefault<z.ZodOptional<z.ZodEnum<["functionCalling", "jsonMode", "jsonSchema"]>>>;
|
|
139
141
|
onLlmError: z.ZodNullable<z.ZodOptional<z.ZodEnum<["block", "rewrite"]>>>;
|
|
@@ -142,8 +144,9 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
142
144
|
rewriteFallbackText: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
143
145
|
timeoutMs: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
144
146
|
}, "strip", z.ZodTypeAny, {
|
|
145
|
-
model?: ICopilotModel;
|
|
146
147
|
scope?: "input" | "output" | "both";
|
|
148
|
+
model?: ICopilotModel;
|
|
149
|
+
rulePrompt?: string;
|
|
147
150
|
systemPrompt?: string;
|
|
148
151
|
outputMethod?: "functionCalling" | "jsonMode" | "jsonSchema";
|
|
149
152
|
onLlmError?: "block" | "rewrite";
|
|
@@ -152,8 +155,9 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
152
155
|
rewriteFallbackText?: string;
|
|
153
156
|
timeoutMs?: number;
|
|
154
157
|
}, {
|
|
155
|
-
model?: ICopilotModel;
|
|
156
158
|
scope?: "input" | "output" | "both";
|
|
159
|
+
model?: ICopilotModel;
|
|
160
|
+
rulePrompt?: string;
|
|
157
161
|
systemPrompt?: string;
|
|
158
162
|
outputMethod?: "functionCalling" | "jsonMode" | "jsonSchema";
|
|
159
163
|
onLlmError?: "block" | "rewrite";
|
|
@@ -167,10 +171,15 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
167
171
|
caseSensitive: z.ZodOptional<z.ZodUnknown>;
|
|
168
172
|
normalize: z.ZodOptional<z.ZodUnknown>;
|
|
169
173
|
}, "strip", z.ZodTypeAny, {
|
|
174
|
+
mode?: "llm";
|
|
175
|
+
rules?: unknown;
|
|
176
|
+
generalPack?: unknown;
|
|
177
|
+
caseSensitive?: unknown;
|
|
170
178
|
normalize?: unknown;
|
|
171
179
|
llm?: {
|
|
172
|
-
model?: ICopilotModel;
|
|
173
180
|
scope?: "input" | "output" | "both";
|
|
181
|
+
model?: ICopilotModel;
|
|
182
|
+
rulePrompt?: string;
|
|
174
183
|
systemPrompt?: string;
|
|
175
184
|
outputMethod?: "functionCalling" | "jsonMode" | "jsonSchema";
|
|
176
185
|
onLlmError?: "block" | "rewrite";
|
|
@@ -179,15 +188,16 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
179
188
|
rewriteFallbackText?: string;
|
|
180
189
|
timeoutMs?: number;
|
|
181
190
|
};
|
|
191
|
+
}, {
|
|
182
192
|
mode?: "llm";
|
|
183
193
|
rules?: unknown;
|
|
184
194
|
generalPack?: unknown;
|
|
185
195
|
caseSensitive?: unknown;
|
|
186
|
-
}, {
|
|
187
196
|
normalize?: unknown;
|
|
188
197
|
llm?: {
|
|
189
|
-
model?: ICopilotModel;
|
|
190
198
|
scope?: "input" | "output" | "both";
|
|
199
|
+
model?: ICopilotModel;
|
|
200
|
+
rulePrompt?: string;
|
|
191
201
|
systemPrompt?: string;
|
|
192
202
|
outputMethod?: "functionCalling" | "jsonMode" | "jsonSchema";
|
|
193
203
|
onLlmError?: "block" | "rewrite";
|
|
@@ -196,14 +206,10 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
196
206
|
rewriteFallbackText?: string;
|
|
197
207
|
timeoutMs?: number;
|
|
198
208
|
};
|
|
199
|
-
mode?: "llm";
|
|
200
|
-
rules?: unknown;
|
|
201
|
-
generalPack?: unknown;
|
|
202
|
-
caseSensitive?: unknown;
|
|
203
209
|
}>]>;
|
|
204
|
-
export declare const llmDecisionSchema: z.
|
|
210
|
+
export declare const llmDecisionSchema: z.ZodObject<{
|
|
205
211
|
matched: z.ZodBoolean;
|
|
206
|
-
action: z.ZodOptional<z.ZodEnum<["block", "rewrite"]
|
|
212
|
+
action: z.ZodNullable<z.ZodOptional<z.ZodEnum<["block", "rewrite"]>>>;
|
|
207
213
|
replacementText: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
208
214
|
reason: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
209
215
|
categories: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
|
|
@@ -219,18 +225,6 @@ export declare const llmDecisionSchema: z.ZodEffects<z.ZodObject<{
|
|
|
219
225
|
matched?: boolean;
|
|
220
226
|
reason?: string;
|
|
221
227
|
categories?: string[];
|
|
222
|
-
}>, {
|
|
223
|
-
action?: "block" | "rewrite";
|
|
224
|
-
replacementText?: string;
|
|
225
|
-
matched?: boolean;
|
|
226
|
-
reason?: string;
|
|
227
|
-
categories?: string[];
|
|
228
|
-
}, {
|
|
229
|
-
action?: "block" | "rewrite";
|
|
230
|
-
replacementText?: string;
|
|
231
|
-
matched?: boolean;
|
|
232
|
-
reason?: string;
|
|
233
|
-
categories?: string[];
|
|
234
228
|
}>;
|
|
235
229
|
export declare function resolveGeneralPackRules(config?: GeneralPackConfig): SensitiveRule[];
|
|
236
230
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,SAAS,GAAG,OAAO,CAAA;IACzB,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IAClC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC3B,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5C,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAClD,MAAM,MAAM,eAAe,GAAG,iBAAiB,GAAG,UAAU,GAAG,YAAY,CAAA;AAC3E,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,CAAA;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/types.js
CHANGED
|
@@ -34,8 +34,9 @@ const llmConfigSchema = z
|
|
|
34
34
|
.object({
|
|
35
35
|
model: z.custom().optional().nullable(),
|
|
36
36
|
scope: z.enum(['input', 'output', 'both']).optional().nullable(),
|
|
37
|
+
rulePrompt: z.string().optional().nullable(),
|
|
37
38
|
systemPrompt: z.string().optional().nullable(),
|
|
38
|
-
outputMethod: z.enum(['functionCalling', 'jsonMode', 'jsonSchema']).optional().default('
|
|
39
|
+
outputMethod: z.enum(['functionCalling', 'jsonMode', 'jsonSchema']).optional().default('jsonMode'),
|
|
39
40
|
onLlmError: z.enum(['block', 'rewrite']).optional().nullable(),
|
|
40
41
|
errorRewriteText: z.string().optional().nullable(),
|
|
41
42
|
blockMessage: z.string().optional().nullable(),
|
|
@@ -62,19 +63,10 @@ export const sensitiveFilterConfigSchema = z.union([ruleModeConfigSchema, llmMod
|
|
|
62
63
|
export const llmDecisionSchema = z
|
|
63
64
|
.object({
|
|
64
65
|
matched: z.boolean(),
|
|
65
|
-
action: z.enum(['block', 'rewrite']).optional(),
|
|
66
|
+
action: z.enum(['block', 'rewrite']).optional().nullable(),
|
|
66
67
|
replacementText: z.string().optional().nullable(),
|
|
67
68
|
reason: z.string().optional().nullable(),
|
|
68
69
|
categories: z.array(z.string()).optional().nullable(),
|
|
69
|
-
})
|
|
70
|
-
.superRefine((data, ctx) => {
|
|
71
|
-
if (data.matched && !data.action) {
|
|
72
|
-
ctx.addIssue({
|
|
73
|
-
code: z.ZodIssueCode.custom,
|
|
74
|
-
path: ['action'],
|
|
75
|
-
message: 'action is required when matched is true',
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
70
|
});
|
|
79
71
|
function escapeRegExp(value) {
|
|
80
72
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|