plugin-sensitive-filter-xr 0.0.6 → 0.0.7

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/README.md CHANGED
@@ -60,18 +60,19 @@
60
60
  | `model` | `ICopilotModel` | 是 | - | 用于判定的过滤模型。 |
61
61
  | `scope` | `'input' \| 'output' \| 'both'` | 是 | - | 生效范围。 |
62
62
  | `rulePrompt` | `string` | 是 | - | 审核规则说明(自然语言,不需要 JSON)。 |
63
- | `outputMethod` | `'functionCalling' \| 'jsonMode' \| 'jsonSchema'` | 否 | `jsonMode` | 结构化输出首选方式(不支持时自动降级)。 |
64
63
  | `rewriteFallbackText` | `string` | 否 | `[已过滤]` | 命中但未返回改写文本时兜底文案。 |
65
64
  | `timeoutMs` | `number` | 否 | 不限 | 判定超时(毫秒,上限 `120000`)。 |
66
65
 
67
66
  ### llm 模式行为说明
68
67
 
69
68
  - 用户只需填写自然语言规则,不需要书写 JSON 协议。
69
+ - `outputMethod` 由中间件内部自动自适应(兼容历史配置读取),默认不在配置面板展示。
70
70
  - 命中后统一执行 `rewrite`。
71
71
  - LLM 调用异常时也统一执行 `rewrite`。
72
72
  - 若配置了 `timeoutMs` 且判定超时,会直接使用 `rewriteFallbackText` 作为改写结果。
73
73
  - 若模型不支持当前 `outputMethod` 的 `response_format`,会自动尝试其它结构化方式并最终降级到纯文本 JSON 解析。
74
74
  - 若历史配置仍携带 `onLlmError/systemPrompt/errorRewriteText`,会按兼容逻辑处理并给出弃用告警。
75
+ - 内部判定与审计追踪默认静默执行,不会把 `{"matched":false}` 这类内部 JSON 透传到聊天回复。
75
76
 
76
77
  ## 界面怎么填(最简)
77
78
 
@@ -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;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"}
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;AAqgBnB,qBAEa,yBAA0B,YAAW,wBAAwB,CAAC,qBAAqB,CAAC;IAE/F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAwQlC;IAEK,gBAAgB,CACpB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,eAAe,CAAC;IAa3B,OAAO,CAAC,wBAAwB;IA8OhC,OAAO,CAAC,uBAAuB;CA4ahC;AAED,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
@@ -12,6 +12,10 @@ const DEFAULT_REWRITE_TEXT = '[已过滤]';
12
12
  const CONFIG_PARSE_ERROR = '敏感词过滤配置格式不正确,请检查填写内容。';
13
13
  const BUSINESS_RULES_VALIDATION_ERROR = '请至少配置 1 条有效业务规则(pattern/type/action/scope/severity),或启用通用规则包。';
14
14
  const LLM_MODE_VALIDATION_ERROR = '请完善 LLM 过滤配置:需填写过滤模型、生效范围、审核规则说明。';
15
+ const INTERNAL_LLM_INVOKE_TAG = 'sensitive-filter/internal-eval';
16
+ const INTERNAL_LLM_INVOKE_OPTIONS = {
17
+ tags: [INTERNAL_LLM_INVOKE_TAG],
18
+ };
15
19
  function isRecord(value) {
16
20
  return typeof value === 'object' && value !== null;
17
21
  }
@@ -22,6 +26,16 @@ function toNonEmptyString(value) {
22
26
  const trimmed = value.trim();
23
27
  return trimmed ? trimmed : null;
24
28
  }
29
+ function buildInternalModelConfig(model) {
30
+ const options = isRecord(model.options) ? model.options : {};
31
+ return {
32
+ ...model,
33
+ options: {
34
+ ...options,
35
+ streaming: false,
36
+ },
37
+ };
38
+ }
25
39
  function normalizeForMatching(text, normalize, caseSensitive) {
26
40
  const source = normalize ? text.trim().replace(/\s+/g, ' ') : text;
27
41
  return caseSensitive ? source : source.toLowerCase();
@@ -595,19 +609,6 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
595
609
  },
596
610
  },
597
611
  },
598
- outputMethod: {
599
- type: 'string',
600
- title: { en_US: 'Output Method', zh_Hans: '结构化输出方式' },
601
- enum: ['functionCalling', 'jsonMode', 'jsonSchema'],
602
- default: 'jsonMode',
603
- 'x-ui': {
604
- enumLabels: {
605
- functionCalling: { en_US: 'Function Calling', zh_Hans: '函数调用' },
606
- jsonMode: { en_US: 'JSON Mode', zh_Hans: 'JSON模式' },
607
- jsonSchema: { en_US: 'JSON Schema', zh_Hans: 'JSON架构' },
608
- },
609
- },
610
- },
611
612
  rewriteFallbackText: {
612
613
  type: 'string',
613
614
  title: { en_US: 'Rewrite Fallback Text', zh_Hans: '改写兜底文本' },
@@ -732,7 +733,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
732
733
  if (!configurable?.thread_id || !configurable.executionId || !this.commandBus) {
733
734
  return;
734
735
  }
735
- const { thread_id, checkpoint_ns, checkpoint_id, subscriber, executionId } = configurable;
736
+ const { thread_id, checkpoint_ns, checkpoint_id, executionId } = configurable;
736
737
  const snapshot = buildAuditSnapshot();
737
738
  const writeSnapshot = async () => {
738
739
  return {
@@ -756,7 +757,6 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
756
757
  checkpointId: checkpoint_id,
757
758
  agentKey: context.node.key,
758
759
  },
759
- subscriber,
760
760
  }));
761
761
  return undefined;
762
762
  }, async () => {
@@ -865,7 +865,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
865
865
  const ensureModel = async () => {
866
866
  const llmConfig = getLlmConfig();
867
867
  if (!modelPromise) {
868
- modelPromise = this.commandBus.execute(new CreateModelClientCommand(llmConfig.model, {
868
+ modelPromise = this.commandBus.execute(new CreateModelClientCommand(buildInternalModelConfig(llmConfig.model), {
869
869
  usageCallback: () => { },
870
870
  }));
871
871
  }
@@ -950,7 +950,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
950
950
  if (!configurable?.thread_id || !configurable.executionId || !this.commandBus) {
951
951
  return;
952
952
  }
953
- const { thread_id, checkpoint_ns, checkpoint_id, subscriber, executionId } = configurable;
953
+ const { thread_id, checkpoint_ns, checkpoint_id, executionId } = configurable;
954
954
  const snapshot = buildAuditSnapshot();
955
955
  const writeSnapshot = async () => {
956
956
  return {
@@ -974,7 +974,6 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
974
974
  checkpointId: checkpoint_id,
975
975
  agentKey: context.node.key,
976
976
  },
977
- subscriber,
978
977
  }));
979
978
  return undefined;
980
979
  }, async () => {
@@ -1006,7 +1005,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1006
1005
  if (!structuredModel) {
1007
1006
  throw new Error(`Structured output is not available for method: ${method}`);
1008
1007
  }
1009
- const raw = await withTimeout(structuredModel.invoke(messages), llmConfig.timeoutMs);
1008
+ const raw = await withTimeout(structuredModel.invoke(messages, INTERNAL_LLM_INVOKE_OPTIONS), llmConfig.timeoutMs);
1010
1009
  return {
1011
1010
  raw,
1012
1011
  trace: {
@@ -1025,7 +1024,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1025
1024
  }
1026
1025
  }
1027
1026
  attempts.push('plainText');
1028
- const raw = await withTimeout(model.invoke(messages), llmConfig.timeoutMs);
1027
+ const raw = await withTimeout(model.invoke(messages, INTERNAL_LLM_INVOKE_OPTIONS), llmConfig.timeoutMs);
1029
1028
  return {
1030
1029
  raw,
1031
1030
  trace: {
@@ -1042,7 +1041,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1042
1041
  return parseLlmDecision(raw, llmConfig.rewriteFallbackText);
1043
1042
  };
1044
1043
  const configurable = (runtime?.configurable ?? {});
1045
- const { thread_id, checkpoint_ns, checkpoint_id, subscriber, executionId } = configurable;
1044
+ const { thread_id, checkpoint_ns, checkpoint_id, executionId } = configurable;
1046
1045
  if (!thread_id || !executionId) {
1047
1046
  return parseCore();
1048
1047
  }
@@ -1053,7 +1052,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1053
1052
  trackedDecision = decision;
1054
1053
  return {
1055
1054
  state: decision,
1056
- output: decision,
1055
+ output: undefined,
1057
1056
  };
1058
1057
  }, {
1059
1058
  execution: {
@@ -1070,7 +1069,6 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1070
1069
  agentKey: context.node.key,
1071
1070
  title: context.node.title,
1072
1071
  },
1073
- subscriber,
1074
1072
  }));
1075
1073
  return undefined;
1076
1074
  }, async () => {
@@ -95,6 +95,7 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
95
95
  normalize: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
96
96
  llm: z.ZodOptional<z.ZodUnknown>;
97
97
  }, "strip", z.ZodTypeAny, {
98
+ llm?: unknown;
98
99
  mode?: "rule";
99
100
  rules?: {
100
101
  id?: string;
@@ -111,8 +112,8 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
111
112
  };
112
113
  caseSensitive?: boolean;
113
114
  normalize?: boolean;
114
- llm?: unknown;
115
115
  }, {
116
+ llm?: unknown;
116
117
  mode?: "rule";
117
118
  rules?: {
118
119
  id?: string;
@@ -129,7 +130,6 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
129
130
  };
130
131
  caseSensitive?: boolean;
131
132
  normalize?: boolean;
132
- llm?: unknown;
133
133
  }>, z.ZodObject<{
134
134
  mode: z.ZodLiteral<"llm">;
135
135
  llm: z.ZodDefault<z.ZodNullable<z.ZodOptional<z.ZodObject<{
@@ -171,11 +171,6 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
171
171
  caseSensitive: z.ZodOptional<z.ZodUnknown>;
172
172
  normalize: z.ZodOptional<z.ZodUnknown>;
173
173
  }, "strip", z.ZodTypeAny, {
174
- mode?: "llm";
175
- rules?: unknown;
176
- generalPack?: unknown;
177
- caseSensitive?: unknown;
178
- normalize?: unknown;
179
174
  llm?: {
180
175
  scope?: "input" | "output" | "both";
181
176
  model?: ICopilotModel;
@@ -188,12 +183,12 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
188
183
  rewriteFallbackText?: string;
189
184
  timeoutMs?: number;
190
185
  };
191
- }, {
192
186
  mode?: "llm";
193
187
  rules?: unknown;
194
188
  generalPack?: unknown;
195
189
  caseSensitive?: unknown;
196
190
  normalize?: unknown;
191
+ }, {
197
192
  llm?: {
198
193
  scope?: "input" | "output" | "both";
199
194
  model?: ICopilotModel;
@@ -206,6 +201,11 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
206
201
  rewriteFallbackText?: string;
207
202
  timeoutMs?: number;
208
203
  };
204
+ mode?: "llm";
205
+ rules?: unknown;
206
+ generalPack?: unknown;
207
+ caseSensitive?: unknown;
208
+ normalize?: unknown;
209
209
  }>]>;
210
210
  export declare const llmDecisionSchema: z.ZodObject<{
211
211
  matched: z.ZodBoolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plugin-sensitive-filter-xr",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "author": {
5
5
  "name": "XpertAI",
6
6
  "url": "https://xpertai.cn"