plugin-sensitive-filter-xr 0.1.19 → 0.1.21

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
@@ -9,7 +9,7 @@
9
9
 
10
10
  - `beforeAgent`: evaluates and optionally rewrites/blocks input
11
11
  - `wrapModelCall`: evaluates and optionally rewrites/blocks output
12
- - `afterAgent`: writes audit snapshot
12
+ - `afterAgent`: writes audit snapshot and sends matched alerts to configured WeCom group webhooks
13
13
 
14
14
  ## Configuration
15
15
 
@@ -22,6 +22,15 @@
22
22
  | `caseSensitive` | `boolean` | No | `false` | Case-sensitive matching in `rule` mode. |
23
23
  | `normalize` | `boolean` | No | `true` | Whitespace normalization in `rule` mode. |
24
24
  | `llm` | `object` | Runtime-required in `llm` mode | - | LLM mode configuration. |
25
+ | `wecom` | `object` | No | disabled when no groups | WeCom webhook notification config. |
26
+
27
+ ### WeCom Notify (`wecom`)
28
+
29
+ | Field | Type | Required | Default | Description |
30
+ | --- | --- | --- | --- | --- |
31
+ | `enabled` | `boolean` | No | `true` | Turn notification on/off. |
32
+ | `groups` | `Array<{name?, webhookUrl}>` | Runtime-required for sending | `[]` | One or more WeCom group webhook targets. |
33
+ | `timeoutMs` | `number` | No | `10000` | Per webhook request timeout (max `120000`). |
25
34
 
26
35
  ### Rule Mode (`mode=rule`)
27
36
 
@@ -55,6 +64,7 @@ Notes:
55
64
  - The middleware internally enforces rewrite-only behavior for LLM hits.
56
65
  - Structured output method is internally adaptive; the UI does not expose method selection.
57
66
  - Internal decision traces are muted from chat output.
67
+ - Notifications are sent only when there is at least one matched record.
58
68
 
59
69
  ## Backward Compatibility
60
70
 
@@ -90,8 +100,6 @@ Current behavior:
90
100
  - Ensure `model/scope/rulePrompt` are all present.
91
101
 
92
102
  3. Unexpected rewrites in LLM mode:
93
- - Check audit records for `source=error-policy` and `reason` starting with `llm-error:`.
103
+ - Check audit records or runtime logs for entries with `source=error-policy` and `reason` starting with `llm-error:`.
94
104
 
95
105
  ## Validation Commands
96
-
97
-
@@ -1 +1 @@
1
- {"version":3,"file":"sensitiveFilter.d.ts","sourceRoot":"","sources":["../../src/lib/sensitiveFilter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAa,oBAAoB,EAA8B,MAAM,kBAAkB,CAAA;AAGnG,OAAO,EACL,eAAe,EAGf,uBAAuB,EACvB,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAML,qBAAqB,EAKtB,MAAM,YAAY,CAAA;AAoxBnB,qBAEa,yBAA0B,YAAW,wBAAwB,CAAC,qBAAqB,CAAC;IAE/F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CA6NlC;IAEK,gBAAgB,CACpB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,eAAe,CAAC;IAa3B,OAAO,CAAC,wBAAwB;IAgThC,OAAO,CAAC,uBAAuB;CA6fhC;AAED,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
1
+ {"version":3,"file":"sensitiveFilter.d.ts","sourceRoot":"","sources":["../../src/lib/sensitiveFilter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAa,oBAAoB,EAA8B,MAAM,kBAAkB,CAAA;AAGnG,OAAO,EACL,eAAe,EAGf,uBAAuB,EACvB,wBAAwB,EAEzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAML,qBAAqB,EAMtB,MAAM,YAAY,CAAA;AA67BnB,qBAEa,yBAA0B,YAAW,wBAAwB,CAAC,qBAAqB,CAAC;IAE/F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAuQlC;IAEK,gBAAgB,CACpB,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,eAAe,CAAC;IAa3B,OAAO,CAAC,wBAAwB;IA6ThC,OAAO,CAAC,uBAAuB;CA0gBhC;AAED,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
@@ -11,6 +11,7 @@ const SENSITIVE_FILTER_MIDDLEWARE_NAME = 'SensitiveFilterMiddleware';
11
11
  const DEFAULT_INPUT_BLOCK_MESSAGE = '输入内容触发敏感策略,已拦截。';
12
12
  const DEFAULT_OUTPUT_BLOCK_MESSAGE = '输出内容触发敏感策略,已拦截。';
13
13
  const DEFAULT_REWRITE_TEXT = '[已过滤]';
14
+ const DEFAULT_WECOM_TIMEOUT_MS = 10000;
14
15
  const CONFIG_PARSE_ERROR = '敏感词过滤配置格式不正确,请检查填写内容。';
15
16
  const BUSINESS_RULES_VALIDATION_ERROR = '请至少配置 1 条有效业务规则(pattern/type/action/scope/severity)。';
16
17
  const LLM_MODE_VALIDATION_ERROR = '请完善 LLM 过滤配置:需填写过滤模型、生效范围、审核规则说明。';
@@ -32,6 +33,36 @@ function toNonEmptyString(value) {
32
33
  const trimmed = value.trim();
33
34
  return trimmed ? trimmed : null;
34
35
  }
36
+ function resolveRuntimeWecomConfig(config) {
37
+ if (!isRecord(config) || config.enabled === false) {
38
+ return null;
39
+ }
40
+ const groups = [];
41
+ const drafts = Array.isArray(config.groups) ? config.groups : [];
42
+ for (const item of drafts) {
43
+ if (!isRecord(item)) {
44
+ continue;
45
+ }
46
+ const webhookUrl = toNonEmptyString(item.webhookUrl);
47
+ if (!webhookUrl) {
48
+ continue;
49
+ }
50
+ groups.push({
51
+ name: toNonEmptyString(item.name) ?? undefined,
52
+ webhookUrl,
53
+ });
54
+ }
55
+ if (groups.length === 0) {
56
+ return null;
57
+ }
58
+ const timeoutMs = typeof config.timeoutMs === 'number' && Number.isFinite(config.timeoutMs) && config.timeoutMs > 0
59
+ ? Math.min(Math.floor(config.timeoutMs), 120000)
60
+ : DEFAULT_WECOM_TIMEOUT_MS;
61
+ return {
62
+ groups,
63
+ timeoutMs,
64
+ };
65
+ }
35
66
  function buildInternalModelConfig(model) {
36
67
  const options = isRecord(model.options) ? model.options : {};
37
68
  return {
@@ -87,6 +118,63 @@ function extractInputText(state, runtime) {
87
118
  }
88
119
  return '';
89
120
  }
121
+ function buildMatchedNotificationMessage(input) {
122
+ const modeLabel = input.mode === 'rule' ? '规则模式' : 'LLM 模式';
123
+ const finalActionLabel = input.finalAction === 'block' ? '已拦截' : input.finalAction === 'rewrite' ? '已改写' : '放行';
124
+ const phaseLabel = (phase) => (phase === 'input' ? '输入' : '输出');
125
+ const actionLabel = (action) => {
126
+ if (action === 'block') {
127
+ return '拦截';
128
+ }
129
+ if (action === 'rewrite') {
130
+ return '改写';
131
+ }
132
+ return '未指定';
133
+ };
134
+ const sourceLabel = (source) => {
135
+ if (source === 'rule') {
136
+ return '规则';
137
+ }
138
+ if (source === 'llm') {
139
+ return 'LLM';
140
+ }
141
+ return '异常兜底策略';
142
+ };
143
+ const reasonLabel = (reason) => {
144
+ if (!reason) {
145
+ return '无';
146
+ }
147
+ if (reason.startsWith('rule:')) {
148
+ return `命中规则 ${reason.replace('rule:', '')}`;
149
+ }
150
+ if (reason.startsWith('llm-error:')) {
151
+ return `LLM判定异常: ${reason.replace('llm-error:', '')}`;
152
+ }
153
+ if (reason.startsWith('llm-fail-open:')) {
154
+ return `LLM故障放行: ${reason.replace('llm-fail-open:', '')}`;
155
+ }
156
+ return reason;
157
+ };
158
+ const matched = input.records.filter((entry) => entry.matched);
159
+ const lines = [
160
+ '【敏感内容告警】',
161
+ `节点:${input.nodeTitle || SENSITIVE_FILTER_MIDDLEWARE_NAME}`,
162
+ `模式:${modeLabel}`,
163
+ `处理结果:${finalActionLabel}`,
164
+ `命中数量:${matched.length}`,
165
+ ];
166
+ if (input.runtimeConfigurable?.thread_id) {
167
+ lines.push(`会话ID:${input.runtimeConfigurable.thread_id}`);
168
+ }
169
+ if (input.runtimeConfigurable?.executionId) {
170
+ lines.push(`执行ID:${input.runtimeConfigurable.executionId}`);
171
+ }
172
+ lines.push('命中详情:');
173
+ matched.forEach((entry, index) => {
174
+ lines.push(`${index + 1}. 阶段=${phaseLabel(entry.phase)},来源=${sourceLabel(entry.source)},动作=${actionLabel(entry.action)},依据=${reasonLabel(entry.reason)}`);
175
+ });
176
+ return lines.join('\n');
177
+ }
90
178
  function getSeverityWeight(severity) {
91
179
  return severity === 'high' ? 2 : 1;
92
180
  }
@@ -538,6 +626,43 @@ function withTimeout(promise, timeoutMs) {
538
626
  });
539
627
  });
540
628
  }
629
+ async function dispatchWecomNotification(wecomConfig, message) {
630
+ if (!wecomConfig || !message.trim()) {
631
+ return;
632
+ }
633
+ const payload = {
634
+ msgtype: 'text',
635
+ text: {
636
+ content: message,
637
+ },
638
+ };
639
+ for (const group of wecomConfig.groups) {
640
+ try {
641
+ const response = await withTimeout(fetch(group.webhookUrl, {
642
+ method: 'POST',
643
+ headers: {
644
+ 'Content-Type': 'application/json',
645
+ },
646
+ body: JSON.stringify(payload),
647
+ }), wecomConfig.timeoutMs);
648
+ if (!response.ok) {
649
+ throw new Error(`HTTP ${response.status}`);
650
+ }
651
+ const body = await response.json().catch(() => null);
652
+ const rawErrCode = isRecord(body) ? body['errcode'] : undefined;
653
+ const errCode = typeof rawErrCode === 'number' ? rawErrCode : Number(rawErrCode);
654
+ if (!Number.isFinite(errCode) || errCode !== 0) {
655
+ const errMsg = isRecord(body) ? String(body['errmsg'] ?? '') : 'unknown';
656
+ throw new Error(`errcode=${String(rawErrCode ?? 'unknown')}, errmsg=${errMsg}`);
657
+ }
658
+ }
659
+ catch (error) {
660
+ const target = group.name ? `${group.name}(${group.webhookUrl})` : group.webhookUrl;
661
+ // Notify failure should not break model execution.
662
+ console.warn(`[${SENSITIVE_FILTER_MIDDLEWARE_NAME}] Failed to send WeCom notification to ${target}: ${getErrorText(error)}`);
663
+ }
664
+ }
665
+ }
541
666
  function normalizeConfigurable(input) {
542
667
  if (!isRecord(input)) {
543
668
  return null;
@@ -797,6 +922,48 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
797
922
  },
798
923
  required: ['model', 'scope', 'rulePrompt'],
799
924
  },
925
+ wecom: {
926
+ type: 'object',
927
+ 'x-ui': {
928
+ span: 2,
929
+ },
930
+ title: {
931
+ en_US: 'WeCom Notify',
932
+ zh_Hans: '企业微信群通知',
933
+ },
934
+ description: {
935
+ en_US: 'When sensitive content is matched, send alerts to configured WeCom group webhooks.',
936
+ zh_Hans: '敏感内容命中后,发送告警到已配置的企业微信群 webhook。',
937
+ },
938
+ properties: {
939
+ enabled: {
940
+ type: 'boolean',
941
+ default: true,
942
+ title: { en_US: 'Enabled', zh_Hans: '启用通知' },
943
+ },
944
+ timeoutMs: {
945
+ type: 'number',
946
+ title: { en_US: 'Timeout (ms)', zh_Hans: '请求超时(毫秒)' },
947
+ },
948
+ groups: {
949
+ type: 'array',
950
+ title: { en_US: 'Group Webhooks', zh_Hans: '群聊 Webhook 配置' },
951
+ items: {
952
+ type: 'object',
953
+ properties: {
954
+ name: {
955
+ type: 'string',
956
+ title: { en_US: 'Group Name', zh_Hans: '群名称(可选)' },
957
+ },
958
+ webhookUrl: {
959
+ type: 'string',
960
+ title: { en_US: 'Webhook URL', zh_Hans: 'Webhook 地址' },
961
+ },
962
+ },
963
+ },
964
+ },
965
+ },
966
+ },
800
967
  },
801
968
  required: ['mode'],
802
969
  allOf: [
@@ -829,6 +996,7 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
829
996
  createRuleModeMiddleware(config, context) {
830
997
  const caseSensitive = config.caseSensitive ?? false;
831
998
  const normalize = config.normalize ?? true;
999
+ const wecomConfig = resolveRuntimeWecomConfig(config.wecom);
832
1000
  const customRules = normalizeRuleDrafts(config.rules ?? []);
833
1001
  const allRules = [...customRules];
834
1002
  const hasEffectiveRules = allRules.length > 0;
@@ -1081,12 +1249,24 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1081
1249
  },
1082
1250
  afterAgent: async () => {
1083
1251
  await persistAuditSnapshot();
1252
+ const matchedRecords = auditEntries.filter((entry) => entry.matched);
1253
+ if (matchedRecords.length > 0) {
1254
+ const notification = buildMatchedNotificationMessage({
1255
+ mode: 'rule',
1256
+ nodeTitle: context.node.title ?? SENSITIVE_FILTER_MIDDLEWARE_NAME,
1257
+ finalAction,
1258
+ records: matchedRecords,
1259
+ runtimeConfigurable,
1260
+ });
1261
+ await dispatchWecomNotification(wecomConfig, notification);
1262
+ }
1084
1263
  return undefined;
1085
1264
  },
1086
1265
  };
1087
1266
  }
1088
1267
  createLlmModeMiddleware(config, context) {
1089
1268
  const llmDraftConfig = config.llm;
1269
+ const wecomConfig = resolveRuntimeWecomConfig(config.wecom);
1090
1270
  let resolvedLlmConfig = null;
1091
1271
  let modelPromise = null;
1092
1272
  const structuredModelPromises = new Map();
@@ -1499,6 +1679,17 @@ let SensitiveFilterMiddleware = class SensitiveFilterMiddleware {
1499
1679
  },
1500
1680
  afterAgent: async () => {
1501
1681
  await persistAuditSnapshot();
1682
+ const matchedRecords = auditEntries.filter((entry) => entry.matched);
1683
+ if (matchedRecords.length > 0) {
1684
+ const notification = buildMatchedNotificationMessage({
1685
+ mode: 'llm',
1686
+ nodeTitle: context.node.title ?? SENSITIVE_FILTER_MIDDLEWARE_NAME,
1687
+ finalAction,
1688
+ records: matchedRecords,
1689
+ runtimeConfigurable,
1690
+ });
1691
+ await dispatchWecomNotification(wecomConfig, notification);
1692
+ }
1502
1693
  return undefined;
1503
1694
  },
1504
1695
  };
@@ -14,6 +14,7 @@ export type RuleModeConfig = {
14
14
  rules?: Array<Partial<SensitiveRule> | null>;
15
15
  caseSensitive?: boolean;
16
16
  normalize?: boolean;
17
+ wecom?: WecomNotifyConfig | null;
17
18
  generalPack?: unknown;
18
19
  };
19
20
  export type LlmScope = 'input' | 'output' | 'both';
@@ -34,9 +35,19 @@ export type LlmFilterConfig = {
34
35
  export type LlmModeConfig = {
35
36
  mode: 'llm';
36
37
  llm?: LlmFilterConfig | null;
38
+ wecom?: WecomNotifyConfig | null;
37
39
  generalPack?: unknown;
38
40
  };
39
41
  export type SensitiveFilterConfig = RuleModeConfig | LlmModeConfig;
42
+ export type WecomNotifyGroup = {
43
+ name?: string | null;
44
+ webhookUrl?: string | null;
45
+ };
46
+ export type WecomNotifyConfig = {
47
+ enabled?: boolean;
48
+ groups?: Array<WecomNotifyGroup | null>;
49
+ timeoutMs?: number | null;
50
+ };
40
51
  export type LlmDecision = {
41
52
  matched: boolean;
42
53
  action?: 'block' | 'rewrite';
@@ -80,6 +91,34 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
80
91
  }>>, "many">>>;
81
92
  caseSensitive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
82
93
  normalize: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
94
+ wecom: z.ZodDefault<z.ZodNullable<z.ZodOptional<z.ZodObject<{
95
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
96
+ groups: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodObject<{
97
+ name: z.ZodNullable<z.ZodOptional<z.ZodString>>;
98
+ webhookUrl: z.ZodNullable<z.ZodOptional<z.ZodString>>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ name?: string;
101
+ webhookUrl?: string;
102
+ }, {
103
+ name?: string;
104
+ webhookUrl?: string;
105
+ }>>, "many">>>;
106
+ timeoutMs: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
107
+ }, "strip", z.ZodTypeAny, {
108
+ enabled?: boolean;
109
+ groups?: {
110
+ name?: string;
111
+ webhookUrl?: string;
112
+ }[];
113
+ timeoutMs?: number;
114
+ }, {
115
+ enabled?: boolean;
116
+ groups?: {
117
+ name?: string;
118
+ webhookUrl?: string;
119
+ }[];
120
+ timeoutMs?: number;
121
+ }>>>>;
83
122
  llm: z.ZodOptional<z.ZodUnknown>;
84
123
  generalPack: z.ZodOptional<z.ZodUnknown>;
85
124
  }, "strip", z.ZodTypeAny, {
@@ -95,6 +134,14 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
95
134
  }[];
96
135
  caseSensitive?: boolean;
97
136
  normalize?: boolean;
137
+ wecom?: {
138
+ enabled?: boolean;
139
+ groups?: {
140
+ name?: string;
141
+ webhookUrl?: string;
142
+ }[];
143
+ timeoutMs?: number;
144
+ };
98
145
  llm?: unknown;
99
146
  generalPack?: unknown;
100
147
  }, {
@@ -110,6 +157,14 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
110
157
  }[];
111
158
  caseSensitive?: boolean;
112
159
  normalize?: boolean;
160
+ wecom?: {
161
+ enabled?: boolean;
162
+ groups?: {
163
+ name?: string;
164
+ webhookUrl?: string;
165
+ }[];
166
+ timeoutMs?: number;
167
+ };
113
168
  llm?: unknown;
114
169
  generalPack?: unknown;
115
170
  }>, z.ZodObject<{
@@ -127,6 +182,7 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
127
182
  timeoutMs: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
128
183
  }, "strip", z.ZodTypeAny, {
129
184
  scope?: "input" | "output" | "both";
185
+ timeoutMs?: number;
130
186
  model?: ICopilotModel;
131
187
  rulePrompt?: string;
132
188
  systemPrompt?: string;
@@ -135,9 +191,9 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
135
191
  errorRewriteText?: string;
136
192
  blockMessage?: string;
137
193
  rewriteFallbackText?: string;
138
- timeoutMs?: number;
139
194
  }, {
140
195
  scope?: "input" | "output" | "both";
196
+ timeoutMs?: number;
141
197
  model?: ICopilotModel;
142
198
  rulePrompt?: string;
143
199
  systemPrompt?: string;
@@ -146,6 +202,33 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
146
202
  errorRewriteText?: string;
147
203
  blockMessage?: string;
148
204
  rewriteFallbackText?: string;
205
+ }>>>>;
206
+ wecom: z.ZodDefault<z.ZodNullable<z.ZodOptional<z.ZodObject<{
207
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
208
+ groups: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodObject<{
209
+ name: z.ZodNullable<z.ZodOptional<z.ZodString>>;
210
+ webhookUrl: z.ZodNullable<z.ZodOptional<z.ZodString>>;
211
+ }, "strip", z.ZodTypeAny, {
212
+ name?: string;
213
+ webhookUrl?: string;
214
+ }, {
215
+ name?: string;
216
+ webhookUrl?: string;
217
+ }>>, "many">>>;
218
+ timeoutMs: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
219
+ }, "strip", z.ZodTypeAny, {
220
+ enabled?: boolean;
221
+ groups?: {
222
+ name?: string;
223
+ webhookUrl?: string;
224
+ }[];
225
+ timeoutMs?: number;
226
+ }, {
227
+ enabled?: boolean;
228
+ groups?: {
229
+ name?: string;
230
+ webhookUrl?: string;
231
+ }[];
149
232
  timeoutMs?: number;
150
233
  }>>>>;
151
234
  rules: z.ZodOptional<z.ZodUnknown>;
@@ -157,8 +240,17 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
157
240
  rules?: unknown;
158
241
  caseSensitive?: unknown;
159
242
  normalize?: unknown;
243
+ wecom?: {
244
+ enabled?: boolean;
245
+ groups?: {
246
+ name?: string;
247
+ webhookUrl?: string;
248
+ }[];
249
+ timeoutMs?: number;
250
+ };
160
251
  llm?: {
161
252
  scope?: "input" | "output" | "both";
253
+ timeoutMs?: number;
162
254
  model?: ICopilotModel;
163
255
  rulePrompt?: string;
164
256
  systemPrompt?: string;
@@ -167,7 +259,6 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
167
259
  errorRewriteText?: string;
168
260
  blockMessage?: string;
169
261
  rewriteFallbackText?: string;
170
- timeoutMs?: number;
171
262
  };
172
263
  generalPack?: unknown;
173
264
  }, {
@@ -175,8 +266,17 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
175
266
  rules?: unknown;
176
267
  caseSensitive?: unknown;
177
268
  normalize?: unknown;
269
+ wecom?: {
270
+ enabled?: boolean;
271
+ groups?: {
272
+ name?: string;
273
+ webhookUrl?: string;
274
+ }[];
275
+ timeoutMs?: number;
276
+ };
178
277
  llm?: {
179
278
  scope?: "input" | "output" | "both";
279
+ timeoutMs?: number;
180
280
  model?: ICopilotModel;
181
281
  rulePrompt?: string;
182
282
  systemPrompt?: string;
@@ -185,7 +285,6 @@ export declare const sensitiveFilterConfigSchema: z.ZodUnion<[z.ZodObject<{
185
285
  errorRewriteText?: string;
186
286
  blockMessage?: string;
187
287
  rewriteFallbackText?: string;
188
- timeoutMs?: number;
189
288
  };
190
289
  generalPack?: unknown;
191
290
  }>]>;
@@ -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,cAAc,GAAG;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5C,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,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,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,eAAe,CAAA;IAE9B,UAAU,CAAC,EAAE,cAAc,CAAA;IAE3B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,KAAK,CAAA;IACX,GAAG,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IAE5B,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,aAAa,CAAA;AAElE,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB,EAAE,MAAM,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,mBAAmB,wSAA8R,CAAA;AAgD9T,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAuD,CAAA;AAE/F,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;EAM5B,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
@@ -24,11 +24,23 @@ const llmConfigSchema = z
24
24
  rewriteFallbackText: z.string().optional().nullable(),
25
25
  timeoutMs: z.number().int().positive().max(120000).optional().nullable(),
26
26
  });
27
+ const wecomNotifyGroupSchema = z
28
+ .object({
29
+ name: z.string().optional().nullable(),
30
+ webhookUrl: z.string().optional().nullable(),
31
+ })
32
+ .nullable();
33
+ const wecomNotifyConfigSchema = z.object({
34
+ enabled: z.boolean().optional().default(true),
35
+ groups: z.array(wecomNotifyGroupSchema).optional().default([]),
36
+ timeoutMs: z.number().int().positive().max(120000).optional().nullable(),
37
+ });
27
38
  const ruleModeConfigSchema = z.object({
28
39
  mode: z.literal('rule').optional(),
29
40
  rules: z.array(sensitiveRuleDraftSchema).optional().default([]),
30
41
  caseSensitive: z.boolean().optional().default(false),
31
42
  normalize: z.boolean().optional().default(true),
43
+ wecom: wecomNotifyConfigSchema.optional().nullable().default({}),
32
44
  llm: z.unknown().optional(),
33
45
  // Backward compatibility only.
34
46
  generalPack: z.unknown().optional(),
@@ -36,6 +48,7 @@ const ruleModeConfigSchema = z.object({
36
48
  const llmModeConfigSchema = z.object({
37
49
  mode: z.literal('llm'),
38
50
  llm: llmConfigSchema.optional().nullable().default({}),
51
+ wecom: wecomNotifyConfigSchema.optional().nullable().default({}),
39
52
  rules: z.unknown().optional(),
40
53
  caseSensitive: z.unknown().optional(),
41
54
  normalize: z.unknown().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plugin-sensitive-filter-xr",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "author": {
5
5
  "name": "XpertAI",
6
6
  "url": "https://xpertai.cn"