@zhin.js/plugin-group-suite 1.1.8 → 1.1.9

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
@@ -88,7 +88,7 @@ pnpm --filter @zhin.js/plugin-group-suite build
88
88
  pnpm --filter @zhin.js/plugin-group-suite test
89
89
  ```
90
90
 
91
- 集成验收使用公开 `@zhin.js/plugin-test-kit`、真实 Native Runtime/CommandIndex/PermissionHost、
91
+ 集成验收使用公开 `@zhin.js/testing`、真实 Native Runtime/CommandIndex/PermissionHost、
92
92
  合成端点、真实 PluginScheduleHost 和 SQLite 状态 CAS,覆盖两个实例、端点隔离、权限拒绝、
93
93
  无数据库错误、热更新、配置失败回滚及新进程重启后的持久词库。HTML 渲染使用 stub,另测文本
94
94
  降级;统计/签到/教学模型在此 fixture 为内存端口。它不代表真实平台登录、欢迎投递、截图质量或
@@ -0,0 +1,21 @@
1
+ import { type Token } from 'zhin.js';
2
+ import type { GroupSuiteConfig } from './config.js';
3
+ import type { ConversationInput } from './conversation-scope.js';
4
+ export declare const KEYWORD_STORAGE_REQUIREMENT = "\u5173\u952E\u8BCD\u7BA1\u7406\u9700\u8981 Database Host \u7684\u6301\u4E45\u72B6\u6001\u670D\u52A1\uFF1B\u8BF7\u914D\u7F6E\u6570\u636E\u5E93\uFF0C\u6216\u663E\u5F0F\u8BBE\u7F6E ephemeralKeywords: true \u4F7F\u7528\u4E34\u65F6\u8BCD\u5E93";
5
+ type KeywordRows = readonly (readonly [string, string])[];
6
+ interface KeywordContext {
7
+ readonly config: Readonly<Partial<GroupSuiteConfig>>;
8
+ use<T>(token: Token<T>): T;
9
+ }
10
+ /** Persistent owner + exact conversation state; volatile storage requires an explicit opt-in. */
11
+ export declare function keywords(input: ConversationInput | undefined, context: KeywordContext): {
12
+ read: () => Promise<KeywordRows>;
13
+ update: (updater: (current: Map<string, string>) => void) => Promise<void>;
14
+ };
15
+ /** Management commands surface a storage requirement instead of inventing an empty dictionary. */
16
+ export declare function keywordsForCommand(input: ConversationInput | undefined, context: KeywordContext): string | {
17
+ read: () => Promise<KeywordRows>;
18
+ update: (updater: (current: Map<string, string>) => void) => Promise<void>;
19
+ };
20
+ export {};
21
+ //# sourceMappingURL=keywords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keywords.d.ts","sourceRoot":"","sources":["../src/keywords.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAKjE,eAAO,MAAM,2BAA2B,mPAA8E,CAAC;AAIvH,KAAK,WAAW,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;AAC1D,UAAU,cAAc;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACrD,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;CAC5B;AAED,iGAAiG;AACjG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,EAAE,OAAO,EAAE,cAAc;;sBAOxD,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI;EAyBnE;AAED,kGAAkG;AAClG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,EAAE,OAAO,EAAE,cAAc;;sBA5BlE,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI;EAkCnE"}
@@ -0,0 +1,72 @@
1
+ import { createDeliveryTarget, databaseHostToken } from 'zhin.js';
2
+ import { requireConversation } from './conversation-scope.js';
3
+ import { keywordStore } from './keyword-store.js';
4
+ import { resolveGroupSuiteRuntime } from './runtime-state.js';
5
+ export const KEYWORD_STORAGE_REQUIREMENT = '关键词管理需要 Database Host 的持久状态服务;请配置数据库,或显式设置 ephemeralKeywords: true 使用临时词库';
6
+ class KeywordStorageRequirementError extends Error {
7
+ }
8
+ const MAX_KEYWORD_BYTES = 64 * 1024;
9
+ /** Persistent owner + exact conversation state; volatile storage requires an explicit opt-in. */
10
+ export function keywords(input, context) {
11
+ const target = requireConversation(input ?? {});
12
+ if (target.kind !== 'group')
13
+ throw new Error('Keywords require a group conversation');
14
+ if (context.config.ephemeralKeywords === true) {
15
+ const store = keywordStore({ conversation: target }, resolveGroupSuiteRuntime(context));
16
+ return {
17
+ read: async () => [...store.entries()],
18
+ update: async (updater) => {
19
+ const next = new Map(store);
20
+ updater(next);
21
+ assertLimit(next);
22
+ store.clear();
23
+ for (const [key, value] of next)
24
+ store.set(key, value);
25
+ },
26
+ };
27
+ }
28
+ const hostState = (() => {
29
+ try {
30
+ return context.use(databaseHostToken).state;
31
+ }
32
+ catch (cause) {
33
+ throw new KeywordStorageRequirementError(KEYWORD_STORAGE_REQUIREMENT, { cause });
34
+ }
35
+ })();
36
+ const state = hostState.forConversation(createDeliveryTarget({ conversation: target }));
37
+ return {
38
+ read: async () => (await state.get('keywords')) ?? [],
39
+ update: async (updater) => {
40
+ await state.update('keywords', current => {
41
+ const next = new Map(current ?? []);
42
+ updater(next);
43
+ assertLimit(next);
44
+ return [...next.entries()];
45
+ });
46
+ },
47
+ };
48
+ }
49
+ /** Management commands surface a storage requirement instead of inventing an empty dictionary. */
50
+ export function keywordsForCommand(input, context) {
51
+ try {
52
+ return keywords(input, context);
53
+ }
54
+ catch (error) {
55
+ if (error instanceof KeywordStorageRequirementError)
56
+ return error.message;
57
+ throw error;
58
+ }
59
+ }
60
+ function assertLimit(store) {
61
+ if (store.size > 200)
62
+ throw new Error('Group keywords are limited to 200 entries');
63
+ if (new TextEncoder().encode(JSON.stringify([...store.entries()])).byteLength >= MAX_KEYWORD_BYTES) {
64
+ throw new Error('Keyword dictionary JSON must be below 64 KiB (UTF-8); shorten replies or remove entries');
65
+ }
66
+ for (const [keyword, reply] of store) {
67
+ if (!keyword || keyword.length > 200 || !reply || reply.length > 2000) {
68
+ throw new Error('Keyword must contain 1–200 characters and reply 1–2000 characters');
69
+ }
70
+ }
71
+ }
72
+ //# sourceMappingURL=keywords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keywords.js","sourceRoot":"","sources":["../src/keywords.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-group-suite",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "Zhin.js 群运营套件:签到、教学、统计、持久词库与群欢迎",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -8,7 +8,6 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./lib/index.d.ts",
11
- "development": "./src/index.ts",
12
11
  "import": "./lib/index.js"
13
12
  },
14
13
  "./package.json": "./package.json"
@@ -42,25 +41,25 @@
42
41
  },
43
42
  "license": "MIT",
44
43
  "dependencies": {
45
- "@zhin.js/components": "1.1.2",
46
- "@zhin.js/core": "1.1.43",
47
- "@zhin.js/jsx": "1.1.2",
48
- "@zhin.js/skill": "1.1.5",
49
- "@zhin.js/tool": "1.1.5"
44
+ "@zhin.js/components": "1.1.3",
45
+ "@zhin.js/core": "1.1.44",
46
+ "@zhin.js/jsx": "1.1.3",
47
+ "@zhin.js/skill": "1.1.6",
48
+ "@zhin.js/tool": "1.1.6"
50
49
  },
51
50
  "devDependencies": {
52
51
  "typescript": "^6.0.3",
53
52
  "vitest": "^4.1.10",
54
53
  "zod": "^4.4.3",
55
- "zhin.js": "1.1.8"
54
+ "zhin.js": "1.1.9"
56
55
  },
57
56
  "peerDependencies": {
58
57
  "zod": "^4.0.0",
59
- "@zhin.js/command": "^1.1.6",
60
- "@zhin.js/middleware": "^1.1.5",
61
- "zhin.js": "^1.1.8",
62
- "@zhin.js/handler": "^1.1.4",
63
- "@zhin.js/schedule-feature": "^1.1.4"
58
+ "@zhin.js/command": "^1.1.7",
59
+ "@zhin.js/middleware": "^1.1.6",
60
+ "zhin.js": "^1.1.9",
61
+ "@zhin.js/handler": "^1.1.5",
62
+ "@zhin.js/schedule-feature": "^1.1.5"
64
63
  },
65
64
  "peerDependenciesMeta": {
66
65
  "@zhin.js/command": {
@@ -89,7 +88,7 @@
89
88
  "registry": "https://registry.npmjs.org"
90
89
  },
91
90
  "engines": {
92
- "node": "^20.19.0 || >=22.12.0"
91
+ "node": ">=22.19.0"
93
92
  },
94
93
  "zhin": {
95
94
  "protocol": 1,