@zhin.js/core 1.0.57 → 1.1.2

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.
Files changed (126) hide show
  1. package/lib/adapter.d.ts +1 -26
  2. package/lib/adapter.d.ts.map +1 -1
  3. package/lib/adapter.js +20 -117
  4. package/lib/adapter.js.map +1 -1
  5. package/lib/ai/index.d.ts +2 -0
  6. package/lib/ai/index.d.ts.map +1 -1
  7. package/lib/ai/index.js +1 -0
  8. package/lib/ai/index.js.map +1 -1
  9. package/lib/built/adapter-process.d.ts +0 -4
  10. package/lib/built/adapter-process.d.ts.map +1 -1
  11. package/lib/built/adapter-process.js +0 -95
  12. package/lib/built/adapter-process.js.map +1 -1
  13. package/lib/built/agent-preset.d.ts +2 -0
  14. package/lib/built/agent-preset.d.ts.map +1 -1
  15. package/lib/built/agent-preset.js +4 -0
  16. package/lib/built/agent-preset.js.map +1 -1
  17. package/lib/built/command.d.ts +4 -0
  18. package/lib/built/command.d.ts.map +1 -1
  19. package/lib/built/command.js +6 -0
  20. package/lib/built/command.js.map +1 -1
  21. package/lib/built/component.d.ts.map +1 -1
  22. package/lib/built/component.js +1 -0
  23. package/lib/built/component.js.map +1 -1
  24. package/lib/built/dispatcher.d.ts.map +1 -1
  25. package/lib/built/dispatcher.js +0 -13
  26. package/lib/built/dispatcher.js.map +1 -1
  27. package/lib/built/message-filter.d.ts +2 -0
  28. package/lib/built/message-filter.d.ts.map +1 -1
  29. package/lib/built/message-filter.js +5 -0
  30. package/lib/built/message-filter.js.map +1 -1
  31. package/lib/built/skill.d.ts +11 -0
  32. package/lib/built/skill.d.ts.map +1 -1
  33. package/lib/built/skill.js +14 -0
  34. package/lib/built/skill.js.map +1 -1
  35. package/lib/built/tool.d.ts +11 -44
  36. package/lib/built/tool.d.ts.map +1 -1
  37. package/lib/built/tool.js +14 -353
  38. package/lib/built/tool.js.map +1 -1
  39. package/lib/plugin.d.ts +1 -25
  40. package/lib/plugin.d.ts.map +1 -1
  41. package/lib/plugin.js +1 -77
  42. package/lib/plugin.js.map +1 -1
  43. package/lib/types.d.ts +0 -25
  44. package/lib/types.d.ts.map +1 -1
  45. package/package.json +10 -7
  46. package/CHANGELOG.md +0 -538
  47. package/REFACTORING_COMPLETE.md +0 -178
  48. package/REFACTORING_STATUS.md +0 -263
  49. package/src/adapter.ts +0 -275
  50. package/src/ai/index.ts +0 -52
  51. package/src/ai/providers/anthropic.ts +0 -379
  52. package/src/ai/providers/base.ts +0 -175
  53. package/src/ai/providers/index.ts +0 -13
  54. package/src/ai/providers/ollama.ts +0 -302
  55. package/src/ai/providers/openai.ts +0 -174
  56. package/src/ai/types.ts +0 -348
  57. package/src/bot.ts +0 -37
  58. package/src/built/adapter-process.ts +0 -177
  59. package/src/built/agent-preset.ts +0 -136
  60. package/src/built/ai-trigger.ts +0 -259
  61. package/src/built/command.ts +0 -108
  62. package/src/built/common-adapter-tools.ts +0 -242
  63. package/src/built/component.ts +0 -130
  64. package/src/built/config.ts +0 -335
  65. package/src/built/cron.ts +0 -156
  66. package/src/built/database.ts +0 -134
  67. package/src/built/dispatcher.ts +0 -496
  68. package/src/built/login-assist.ts +0 -131
  69. package/src/built/message-filter.ts +0 -390
  70. package/src/built/permission.ts +0 -151
  71. package/src/built/schema-feature.ts +0 -190
  72. package/src/built/skill.ts +0 -221
  73. package/src/built/tool.ts +0 -948
  74. package/src/command.ts +0 -87
  75. package/src/component.ts +0 -565
  76. package/src/cron.ts +0 -4
  77. package/src/errors.ts +0 -46
  78. package/src/feature.ts +0 -7
  79. package/src/index.ts +0 -53
  80. package/src/jsx-dev-runtime.ts +0 -2
  81. package/src/jsx-runtime.ts +0 -12
  82. package/src/jsx.ts +0 -135
  83. package/src/message.ts +0 -48
  84. package/src/models/system-log.ts +0 -20
  85. package/src/models/user.ts +0 -15
  86. package/src/notice.ts +0 -98
  87. package/src/plugin.ts +0 -896
  88. package/src/prompt.ts +0 -293
  89. package/src/request.ts +0 -95
  90. package/src/scheduler/index.ts +0 -19
  91. package/src/scheduler/scheduler.ts +0 -372
  92. package/src/scheduler/types.ts +0 -74
  93. package/src/tool-zod.ts +0 -115
  94. package/src/types-generator.ts +0 -78
  95. package/src/types.ts +0 -505
  96. package/src/utils.ts +0 -227
  97. package/tests/adapter.test.ts +0 -638
  98. package/tests/ai/ai-trigger.test.ts +0 -368
  99. package/tests/ai/providers.integration.test.ts +0 -227
  100. package/tests/ai/setup.ts +0 -308
  101. package/tests/ai/tool.test.ts +0 -800
  102. package/tests/bot.test.ts +0 -151
  103. package/tests/command.test.ts +0 -737
  104. package/tests/component-new.test.ts +0 -361
  105. package/tests/config.test.ts +0 -372
  106. package/tests/cron.test.ts +0 -82
  107. package/tests/dispatcher.test.ts +0 -293
  108. package/tests/errors.test.ts +0 -21
  109. package/tests/expression-evaluation.test.ts +0 -258
  110. package/tests/features-builtin.test.ts +0 -191
  111. package/tests/jsx-runtime.test.ts +0 -45
  112. package/tests/jsx.test.ts +0 -319
  113. package/tests/message-filter.test.ts +0 -566
  114. package/tests/message.test.ts +0 -402
  115. package/tests/notice.test.ts +0 -198
  116. package/tests/plugin.test.ts +0 -779
  117. package/tests/prompt.test.ts +0 -78
  118. package/tests/redos-protection.test.ts +0 -198
  119. package/tests/request.test.ts +0 -221
  120. package/tests/schema.test.ts +0 -248
  121. package/tests/skill-feature.test.ts +0 -179
  122. package/tests/test-utils.ts +0 -59
  123. package/tests/tool-feature.test.ts +0 -254
  124. package/tests/types.test.ts +0 -162
  125. package/tests/utils.test.ts +0 -135
  126. package/tsconfig.json +0 -24
@@ -1,78 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest'
2
- import { Prompt } from '../src/prompt'
3
- import { Plugin } from '../src/plugin'
4
- import { Schema } from '@zhin.js/schema'
5
-
6
- describe('Prompt', () => {
7
- let plugin: Plugin
8
- let mockEvent: any
9
- let prompt: Prompt<any>
10
-
11
- beforeEach(() => {
12
- plugin = new Plugin('/test/plugin.ts')
13
-
14
- // 创建模拟事件
15
- mockEvent = {
16
- $adapter: 'test-adapter',
17
- $bot: 'test-bot',
18
- $channel: { type: 'text', id: 'test-channel' },
19
- $sender: { id: 'test-user' },
20
- $raw: 'test message',
21
- $reply: vi.fn().mockResolvedValue('message-id')
22
- }
23
-
24
- prompt = new Prompt(plugin, mockEvent as any)
25
- })
26
-
27
- describe('Constructor', () => {
28
- it('should create Prompt instance', () => {
29
- expect(prompt).toBeInstanceOf(Prompt)
30
- })
31
- })
32
-
33
- describe('const', () => {
34
- it('should return constant value', async () => {
35
- const result = await prompt.const(42)
36
- expect(result).toBe(42)
37
- })
38
-
39
- it('should return constant string', async () => {
40
- const result = await prompt.const('test-value')
41
- expect(result).toBe('test-value')
42
- })
43
-
44
- it('should return constant object', async () => {
45
- const obj = { key: 'value' }
46
- const result = await prompt.const(obj)
47
- expect(result).toBe(obj)
48
- })
49
-
50
- it('should return constant array', async () => {
51
- const arr = [1, 2, 3]
52
- const result = await prompt.const(arr)
53
- expect(result).toBe(arr)
54
- })
55
- })
56
-
57
- describe('Schema error handling', () => {
58
- it('should throw error for unsupported list inner type', async () => {
59
- const schema = Schema.list(Schema.object({})).description('不支持的列表类型')
60
-
61
- await expect(prompt.getValueWithSchema(schema)).rejects.toThrow('unsupported inner type')
62
- })
63
-
64
- it('should throw error for unsupported schema type', async () => {
65
- const schema = Schema.dict(Schema.string()).description('不支持的类型')
66
-
67
- await expect(prompt.getValueWithSchema(schema)).rejects.toThrow('Unsupported schema input type')
68
- })
69
-
70
- it('should throw error for object schema without object definition', async () => {
71
- const schema = Schema.object({})
72
- // 删除 object 定义来触发错误
73
- delete (schema as any).options.object
74
-
75
- await expect(prompt.getValueWithSchema(schema)).rejects.toThrow('Object schema missing object definition')
76
- })
77
- })
78
- })
@@ -1,198 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { segment } from '../src/utils.js';
3
-
4
- describe('ReDoS Protection Tests', () => {
5
- describe('segment.from() ReDoS protection', () => {
6
- it('should handle small inputs (100 attributes) without timeout', () => {
7
- // 测试少量属性的标签
8
- const smallInput = '<tag ' + 'a="b" '.repeat(100) + '/>';
9
- const start = Date.now();
10
-
11
- try {
12
- segment.from(smallInput);
13
- const duration = Date.now() - start;
14
-
15
- // 应该在合理时间内完成(100ms)
16
- expect(duration).toBeLessThan(100);
17
- } catch (error) {
18
- // 如果抛出错误,也是可以接受的(比如输入太大)
19
- expect(error).toBeDefined();
20
- }
21
- });
22
-
23
- it('should handle medium inputs (500 attributes) without timeout', () => {
24
- // 测试中等数量属性的标签
25
- const mediumInput = '<tag ' + 'a="b" '.repeat(500) + '/>';
26
- const start = Date.now();
27
-
28
- try {
29
- segment.from(mediumInput);
30
- const duration = Date.now() - start;
31
-
32
- // 应该在合理时间内完成(500ms)
33
- expect(duration).toBeLessThan(500);
34
- } catch (error) {
35
- // 如果抛出错误,也是可以接受的(比如输入太大)
36
- expect(error).toBeDefined();
37
- }
38
- });
39
-
40
- it('should handle large inputs (1000 attributes) without timeout', () => {
41
- // 测试大量属性的标签
42
- const largeInput = '<tag ' + 'a="b" '.repeat(1000) + '/>';
43
- const start = Date.now();
44
-
45
- try {
46
- segment.from(largeInput);
47
- const duration = Date.now() - start;
48
-
49
- // 应该在合理时间内完成(1秒)
50
- expect(duration).toBeLessThan(1000);
51
- } catch (error) {
52
- // 如果抛出错误,也是可以接受的(比如输入太大)
53
- expect(error).toBeDefined();
54
- }
55
- });
56
-
57
- it('should handle very large inputs (2000 attributes) without timeout', () => {
58
- // 测试更大量属性的标签
59
- const veryLargeInput = '<tag ' + 'a="b" '.repeat(2000) + '/>';
60
- const start = Date.now();
61
-
62
- try {
63
- segment.from(veryLargeInput);
64
- const duration = Date.now() - start;
65
-
66
- // 应该在合理时间内完成(2秒)
67
- expect(duration).toBeLessThan(2000);
68
- } catch (error) {
69
- // 如果抛出错误,也是可以接受的(比如输入太大)
70
- expect(error).toBeDefined();
71
- }
72
- });
73
-
74
- it('should reject extremely large templates', () => {
75
- // segment.from 在 utils 中限制单段模板长度 > 400_000(见 MAX_TEMPLATE_LENGTH)
76
- const chunk = '<tag>content</tag>';
77
- const hugeTemplate = chunk.repeat(Math.ceil(400_001 / chunk.length));
78
-
79
- expect(() => {
80
- segment.from(hugeTemplate);
81
- }).toThrow(/Template too large/);
82
- });
83
-
84
- it('should handle nested tags without exponential backtracking', () => {
85
- // 测试嵌套标签
86
- const nestedInput = '<outer ' + 'attr="val" '.repeat(100) + '><inner>text</inner></outer>';
87
- const start = Date.now();
88
-
89
- segment.from(nestedInput);
90
- const duration = Date.now() - start;
91
-
92
- // 应该在合理时间内完成
93
- expect(duration).toBeLessThan(500);
94
- });
95
-
96
- it('should handle malformed attributes gracefully', () => {
97
- // 测试格式错误的属性
98
- const malformedInput = '<tag a=b c=d e="f"/>';
99
-
100
- // 不应该崩溃或超时
101
- const start = Date.now();
102
- const result = segment.from(malformedInput);
103
- const duration = Date.now() - start;
104
-
105
- expect(duration).toBeLessThan(100);
106
- expect(result).toBeDefined();
107
- });
108
-
109
- it('should prevent infinite loops', () => {
110
- // 测试可能导致无限循环的输入
111
- const problematicInput = '<tag><tag><tag><tag><tag>';
112
-
113
- const start = Date.now();
114
- try {
115
- segment.from(problematicInput);
116
- } catch (error) {
117
- // 可能会抛出错误,这是可以接受的
118
- }
119
- const duration = Date.now() - start;
120
-
121
- // 应该在合理时间内完成或失败
122
- expect(duration).toBeLessThan(1000);
123
- });
124
-
125
- it('should handle complex attribute patterns', () => {
126
- // 测试复杂的属性模式
127
- const complexInput = '<tag attr1="value1" attr2=\'value2\' attr3="value with spaces"/>';
128
-
129
- const start = Date.now();
130
- const result = segment.from(complexInput);
131
- const duration = Date.now() - start;
132
-
133
- expect(duration).toBeLessThan(100);
134
- expect(Array.isArray(result)).toBe(true);
135
- });
136
-
137
- it('should handle repeated patterns efficiently', () => {
138
- // 测试重复模式
139
- const repeatedPattern = ('<tag attr="value">content</tag>').repeat(100);
140
-
141
- const start = Date.now();
142
- try {
143
- segment.from(repeatedPattern);
144
- } catch (error) {
145
- // 如果输入太大,抛出错误是可以接受的
146
- }
147
- const duration = Date.now() - start;
148
-
149
- expect(duration).toBeLessThan(1000);
150
- });
151
-
152
- it('should handle edge cases with special characters', () => {
153
- // 测试特殊字符
154
- const specialChars = '<tag attr="value with \\"quotes\\" and \'apostrophes\'">content</tag>';
155
-
156
- const start = Date.now();
157
- const result = segment.from(specialChars);
158
- const duration = Date.now() - start;
159
-
160
- expect(duration).toBeLessThan(100);
161
- expect(Array.isArray(result)).toBe(true);
162
- });
163
- });
164
-
165
- describe('Normal functionality should still work', () => {
166
- it('should parse simple self-closing tags', () => {
167
- const input = '<image url="test.jpg"/>';
168
- const result = segment.from(input);
169
-
170
- expect(Array.isArray(result)).toBe(true);
171
- expect(result.length).toBeGreaterThan(0);
172
- });
173
-
174
- it('should parse tags with content', () => {
175
- const input = '<text>Hello World</text>';
176
- const result = segment.from(input);
177
-
178
- expect(Array.isArray(result)).toBe(true);
179
- expect(result.length).toBeGreaterThan(0);
180
- });
181
-
182
- it('should parse tags with attributes', () => {
183
- const input = '<at id="123" name="user"/>';
184
- const result = segment.from(input);
185
-
186
- expect(Array.isArray(result)).toBe(true);
187
- expect(result.length).toBeGreaterThan(0);
188
- });
189
-
190
- it('should parse nested tags', () => {
191
- const input = '<quote><text>quoted text</text></quote>';
192
- const result = segment.from(input);
193
-
194
- expect(Array.isArray(result)).toBe(true);
195
- expect(result.length).toBeGreaterThan(0);
196
- });
197
- });
198
- });
@@ -1,221 +0,0 @@
1
- /**
2
- * Request 抽象层测试
3
- */
4
- import { Request, RequestBase, RequestType } from '../src/request.js';
5
-
6
- describe('Request', () => {
7
- // ============================================================================
8
- // Request.from()
9
- // ============================================================================
10
- describe('Request.from()', () => {
11
- it('应合并原始数据与基础结构', () => {
12
- const raw = { flag: 'abc123', extra_data: 42 };
13
- const base: RequestBase = {
14
- $id: 'req_001',
15
- $adapter: 'onebot11' as any,
16
- $bot: 'bot1',
17
- $type: 'friend_add',
18
- $channel: { id: '100', type: 'private' },
19
- $sender: { id: '200', name: '请求者' },
20
- $comment: '请加我好友',
21
- $timestamp: 1000,
22
- $approve: async () => {},
23
- $reject: async () => {},
24
- };
25
- const request = Request.from(raw, base);
26
-
27
- expect(request.$id).toBe('req_001');
28
- expect(request.$adapter).toBe('onebot11');
29
- expect(request.$bot).toBe('bot1');
30
- expect(request.$type).toBe('friend_add');
31
- expect(request.$channel.type).toBe('private');
32
- expect(request.$sender).toEqual({ id: '200', name: '请求者' });
33
- expect(request.$comment).toBe('请加我好友');
34
- expect(request.$timestamp).toBe(1000);
35
- // 原始字段保留
36
- expect(request.flag).toBe('abc123');
37
- expect(request.extra_data).toBe(42);
38
- });
39
-
40
- it('$comment 和 $subType 应可以为 undefined', () => {
41
- const request = Request.from({}, {
42
- $id: 'req_002',
43
- $adapter: 'icqq' as any,
44
- $bot: 'bot1',
45
- $type: 'group_add',
46
- $channel: { id: '300', type: 'group' },
47
- $sender: { id: '400', name: '申请者' },
48
- $timestamp: 2000,
49
- $approve: async () => {},
50
- $reject: async () => {},
51
- });
52
-
53
- expect(request.$comment).toBeUndefined();
54
- expect(request.$subType).toBeUndefined();
55
- });
56
- });
57
-
58
- // ============================================================================
59
- // $approve / $reject
60
- // ============================================================================
61
- describe('$approve() 和 $reject()', () => {
62
- it('调用 $approve 应执行同意逻辑', async () => {
63
- let approved = false;
64
- let approveRemark: string | undefined;
65
- const request = Request.from({}, {
66
- $id: 'req_approve',
67
- $adapter: 'onebot11' as any,
68
- $bot: 'bot1',
69
- $type: 'friend_add',
70
- $channel: { id: '100', type: 'private' },
71
- $sender: { id: '200', name: '用户' },
72
- $timestamp: 0,
73
- $approve: async (remark?: string) => {
74
- approved = true;
75
- approveRemark = remark;
76
- },
77
- $reject: async () => {},
78
- });
79
-
80
- await request.$approve('备注名');
81
- expect(approved).toBe(true);
82
- expect(approveRemark).toBe('备注名');
83
- });
84
-
85
- it('调用 $reject 应执行拒绝逻辑', async () => {
86
- let rejected = false;
87
- let rejectReason: string | undefined;
88
- const request = Request.from({}, {
89
- $id: 'req_reject',
90
- $adapter: 'onebot11' as any,
91
- $bot: 'bot1',
92
- $type: 'group_invite',
93
- $channel: { id: '300', type: 'group' },
94
- $sender: { id: '400', name: '邀请者' },
95
- $timestamp: 0,
96
- $approve: async () => {},
97
- $reject: async (reason?: string) => {
98
- rejected = true;
99
- rejectReason = reason;
100
- },
101
- });
102
-
103
- await request.$reject('不接受邀请');
104
- expect(rejected).toBe(true);
105
- expect(rejectReason).toBe('不接受邀请');
106
- });
107
-
108
- it('$approve 无参数调用应不报错', async () => {
109
- let called = false;
110
- const request = Request.from({}, {
111
- $id: 'req_noarg',
112
- $adapter: 'onebot11' as any,
113
- $bot: 'bot1',
114
- $type: 'friend_add',
115
- $channel: { id: '1', type: 'private' },
116
- $sender: { id: '2', name: 'user' },
117
- $timestamp: 0,
118
- $approve: async () => { called = true; },
119
- $reject: async () => {},
120
- });
121
-
122
- await request.$approve();
123
- expect(called).toBe(true);
124
- });
125
- });
126
-
127
- // ============================================================================
128
- // RequestType
129
- // ============================================================================
130
- describe('RequestType', () => {
131
- it('应接受所有预定义类型', () => {
132
- const types: RequestType[] = ['friend_add', 'group_add', 'group_invite'];
133
- expect(types).toHaveLength(3);
134
- });
135
-
136
- it('应接受自定义扩展类型', () => {
137
- const customType: RequestType = 'custom_request_type';
138
- expect(customType).toBe('custom_request_type');
139
- });
140
- });
141
-
142
- // ============================================================================
143
- // 典型场景
144
- // ============================================================================
145
- describe('典型场景', () => {
146
- it('好友添加请求', async () => {
147
- let approvedFlag: string | undefined;
148
- const raw = { flag: 'friend_flag_001', user_id: 12345 };
149
- const request = Request.from(raw, {
150
- $id: 'friend_flag_001',
151
- $adapter: 'onebot11' as any,
152
- $bot: 'mybot',
153
- $type: 'friend_add',
154
- $subType: 'add',
155
- $channel: { id: '12345', type: 'private' },
156
- $sender: { id: '12345', name: '新朋友' },
157
- $comment: '你好,加个好友吧',
158
- $timestamp: Date.now(),
159
- $approve: async (remark?: string) => {
160
- approvedFlag = raw.flag;
161
- },
162
- $reject: async () => {},
163
- });
164
-
165
- expect(request.$type).toBe('friend_add');
166
- expect(request.$comment).toBe('你好,加个好友吧');
167
- expect(request.flag).toBe('friend_flag_001');
168
- expect(request.user_id).toBe(12345);
169
-
170
- await request.$approve();
171
- expect(approvedFlag).toBe('friend_flag_001');
172
- });
173
-
174
- it('入群申请', async () => {
175
- let rejected = false;
176
- const raw = { flag: 'group_flag_001', user_id: 111, group_id: 222, comment: '想加群' };
177
- const request = Request.from(raw, {
178
- $id: 'group_flag_001',
179
- $adapter: 'icqq' as any,
180
- $bot: 'bot2',
181
- $type: 'group_add',
182
- $subType: 'add',
183
- $channel: { id: '222', type: 'group' },
184
- $sender: { id: '111', name: '申请者' },
185
- $comment: '想加群',
186
- $timestamp: Date.now(),
187
- $approve: async () => {},
188
- $reject: async (reason?: string) => { rejected = true; },
189
- });
190
-
191
- expect(request.$type).toBe('group_add');
192
- expect(request.group_id).toBe(222);
193
-
194
- await request.$reject('暂不接受');
195
- expect(rejected).toBe(true);
196
- });
197
-
198
- it('群邀请', async () => {
199
- let approved = false;
200
- const raw = { flag: 'invite_001', user_id: 333, group_id: 444, group_name: '测试群' };
201
- const request = Request.from(raw, {
202
- $id: 'invite_001',
203
- $adapter: 'onebot11' as any,
204
- $bot: 'bot1',
205
- $type: 'group_invite',
206
- $subType: 'invite',
207
- $channel: { id: '444', type: 'group' },
208
- $sender: { id: '333', name: '邀请者' },
209
- $timestamp: Date.now(),
210
- $approve: async () => { approved = true; },
211
- $reject: async () => {},
212
- });
213
-
214
- expect(request.$type).toBe('group_invite');
215
- expect(request.group_name).toBe('测试群');
216
-
217
- await request.$approve();
218
- expect(approved).toBe(true);
219
- });
220
- });
221
- });