@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,372 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
- import { ConfigLoader } from '../src/built/config'
3
- import fs from 'fs'
4
- import path from 'path'
5
-
6
- describe('ConfigLoader', () => {
7
- const testConfigPath = path.join(process.cwd(), 'test-config.json')
8
-
9
- afterEach(() => {
10
- // 清理测试文件
11
- if (fs.existsSync(testConfigPath)) {
12
- fs.unlinkSync(testConfigPath)
13
- }
14
- })
15
-
16
- describe('Proxy behavior', () => {
17
- it('should handle array methods correctly', () => {
18
- const config = {
19
- items: ['item1', 'item2', 'item3'],
20
- bots: [
21
- { context: 'sandbox', name: 'bot1' },
22
- { context: 'sandbox', name: 'bot2' }
23
- ]
24
- }
25
-
26
- const loader = new ConfigLoader(testConfigPath, config)
27
- const proxiedData = loader.data
28
-
29
- // 测试数组的 map 方法
30
- expect(() => {
31
- const mapped = proxiedData.items.map((item: string) => item.toUpperCase())
32
- expect(mapped).toEqual(['ITEM1', 'ITEM2', 'ITEM3'])
33
- }).not.toThrow()
34
-
35
- // 测试数组的 filter 方法
36
- expect(() => {
37
- const filtered = proxiedData.bots.filter((bot: any) => bot.name === 'bot1')
38
- expect(filtered).toHaveLength(1)
39
- }).not.toThrow()
40
- })
41
-
42
- it('should handle nested objects', () => {
43
- const config = {
44
- database: {
45
- dialect: 'sqlite',
46
- filename: './data/bot.db'
47
- },
48
- http: {
49
- port: 8086,
50
- username: '${username}',
51
- password: '${password}'
52
- }
53
- }
54
-
55
- const loader = new ConfigLoader(testConfigPath, config)
56
- const proxiedData = loader.data
57
-
58
- expect(proxiedData.database.dialect).toBe('sqlite')
59
- expect(proxiedData.http.port).toBe(8086)
60
- })
61
-
62
- it('should resolve environment variables', () => {
63
- process.env.TEST_VAR = 'test_value'
64
-
65
- const config = {
66
- testValue: '${TEST_VAR}'
67
- }
68
-
69
- const loader = new ConfigLoader(testConfigPath, config)
70
- const proxiedData = loader.data
71
-
72
- expect(proxiedData.testValue).toBe('test_value')
73
-
74
- delete process.env.TEST_VAR
75
- })
76
-
77
- it('should handle escaped environment variables', () => {
78
- const config = {
79
- escapedValue: '\\${NOT_A_VAR}'
80
- }
81
-
82
- const loader = new ConfigLoader(testConfigPath, config)
83
- const proxiedData = loader.data
84
-
85
- expect(proxiedData.escapedValue).toBe('${NOT_A_VAR}')
86
- })
87
-
88
- it('should handle default values for missing env vars', () => {
89
- const config = {
90
- valueWithDefault: '${MISSING_VAR:default_value}'
91
- }
92
-
93
- const loader = new ConfigLoader(testConfigPath, config)
94
- const proxiedData = loader.data
95
-
96
- expect(proxiedData.valueWithDefault).toBe('default_value')
97
- })
98
-
99
- it('should not proxy function properties', () => {
100
- const config = {
101
- items: [1, 2, 3]
102
- }
103
-
104
- const loader = new ConfigLoader(testConfigPath, config)
105
- const proxiedData = loader.data
106
-
107
- // 确保数组方法可以正常调用
108
- expect(typeof proxiedData.items.map).toBe('function')
109
- expect(typeof proxiedData.items.filter).toBe('function')
110
- expect(typeof proxiedData.items.reduce).toBe('function')
111
- })
112
-
113
- it('should handle Set operations from array', () => {
114
- const config = {
115
- bots: [
116
- { context: 'sandbox', name: 'bot1' },
117
- { context: 'process', name: 'bot2' },
118
- { context: 'sandbox', name: 'bot3' }
119
- ]
120
- }
121
-
122
- const loader = new ConfigLoader(testConfigPath, config)
123
- const proxiedData = loader.data
124
-
125
- // 模拟 setup.ts 中的操作
126
- expect(() => {
127
- const contexts = new Set(proxiedData.bots.map((bot: any) => bot.context))
128
- expect(contexts.size).toBe(2)
129
- expect(contexts.has('sandbox')).toBe(true)
130
- expect(contexts.has('process')).toBe(true)
131
- }).not.toThrow()
132
- })
133
- })
134
-
135
- describe('Raw data access', () => {
136
- it('should provide raw data without proxy', () => {
137
- const config = {
138
- value: '${TEST_VAR}'
139
- }
140
-
141
- const loader = new ConfigLoader(testConfigPath, config)
142
-
143
- // raw 应该返回原始值,不解析环境变量
144
- expect(loader.raw.value).toBe('${TEST_VAR}')
145
-
146
- // data 应该尝试解析环境变量
147
- expect(loader.data.value).toBeTruthy()
148
- })
149
- })
150
-
151
- describe('File operations', () => {
152
- it('should save and load JSON config', () => {
153
- const jsonPath = path.join(process.cwd(), 'test-config.json')
154
- const config = {
155
- name: 'test',
156
- value: 123
157
- }
158
-
159
- const loader = new ConfigLoader(jsonPath, config)
160
- loader.save(jsonPath)
161
-
162
- expect(fs.existsSync(jsonPath)).toBe(true)
163
-
164
- const content = fs.readFileSync(jsonPath, 'utf-8')
165
- const parsed = JSON.parse(content)
166
- expect(parsed.name).toBe('test')
167
- expect(parsed.value).toBe(123)
168
-
169
- fs.unlinkSync(jsonPath)
170
- })
171
-
172
- it('should save and load YAML config', () => {
173
- const yamlPath = path.join(process.cwd(), 'test-config.yml')
174
- const config = {
175
- name: 'test',
176
- value: 123
177
- }
178
-
179
- const loader = new ConfigLoader(yamlPath, config)
180
- loader.save(yamlPath)
181
-
182
- expect(fs.existsSync(yamlPath)).toBe(true)
183
-
184
- fs.unlinkSync(yamlPath)
185
- })
186
-
187
- it('should auto-save on property change', () => {
188
- const config = {
189
- value: 'initial'
190
- }
191
-
192
- const loader = new ConfigLoader(testConfigPath, config)
193
- loader.save(testConfigPath)
194
-
195
- // 修改属性应该触发自动保存
196
- const proxiedData = loader.data
197
- proxiedData.value = 'changed'
198
-
199
- // 重新读取文件验证保存
200
- const content = fs.readFileSync(testConfigPath, 'utf-8')
201
- const parsed = JSON.parse(content)
202
- expect(parsed.value).toBe('changed')
203
- })
204
-
205
- it('should auto-save on property deletion', () => {
206
- const config = {
207
- value: 'test',
208
- other: 'keep'
209
- }
210
-
211
- const loader = new ConfigLoader(testConfigPath, config)
212
- loader.save(testConfigPath)
213
-
214
- // 删除属性应该触发自动保存
215
- const proxiedData = loader.data as any
216
- delete proxiedData.value
217
-
218
- // 重新读取文件验证保存
219
- const content = fs.readFileSync(testConfigPath, 'utf-8')
220
- const parsed = JSON.parse(content)
221
- expect(parsed.value).toBeUndefined()
222
- expect(parsed.other).toBe('keep')
223
- })
224
- })
225
-
226
- describe('ConfigService', () => {
227
- it('should load and cache configs', async () => {
228
- const { ConfigService } = await import('../src/built/config')
229
- const service = new ConfigService()
230
-
231
- const config = { test: 'value' }
232
- service.load('test-config.json', config)
233
-
234
- expect(service.configs.has('test-config.json')).toBe(true)
235
- })
236
-
237
- it('should throw error for unsupported format', async () => {
238
- const { ConfigService } = await import('../src/built/config')
239
- const service = new ConfigService()
240
-
241
- expect(() => {
242
- service.load('test.txt', {})
243
- }).toThrow('不支持的配置文件格式')
244
- })
245
-
246
- it('should get config data', async () => {
247
- const { ConfigService } = await import('../src/built/config')
248
- const service = new ConfigService()
249
-
250
- const config = { test: 'value' }
251
- service.load(testConfigPath, config)
252
-
253
- const data = service.get(testConfigPath)
254
- expect(data.test).toBe('value')
255
- })
256
-
257
- it('should get raw config data', async () => {
258
- const { ConfigService } = await import('../src/built/config')
259
- const service = new ConfigService()
260
-
261
- const config = { test: '${VAR}' }
262
- service.load(testConfigPath, config)
263
-
264
- const raw = service.getRaw(testConfigPath)
265
- expect(raw.test).toBe('${VAR}')
266
- })
267
-
268
- it('should update config data', async () => {
269
- const { ConfigService } = await import('../src/built/config')
270
- const service = new ConfigService()
271
-
272
- const config = { test: 'initial' }
273
- service.load(testConfigPath, config)
274
-
275
- service.set(testConfigPath, { test: 'updated' })
276
-
277
- const data = service.get(testConfigPath)
278
- expect(data.test).toBe('updated')
279
- })
280
-
281
- it('should throw error when getting non-existent config', async () => {
282
- const { ConfigService } = await import('../src/built/config')
283
- const service = new ConfigService()
284
-
285
- service.load(testConfigPath, { test: 'value' })
286
- service.configs.delete(testConfigPath) // 手动删除以模拟不存在的情况
287
-
288
- // 由于 get 会自动加载,我们需要测试 set
289
- expect(() => {
290
- service.set('non-existent.json', {})
291
- }).toThrow('配置文件 non-existent.json 未加载')
292
- })
293
-
294
- it('should auto-load config if not cached', async () => {
295
- const { ConfigService } = await import('../src/built/config')
296
- const service = new ConfigService()
297
-
298
- const config = { test: 'value' }
299
- // 先保存文件
300
- const loader = new ConfigLoader(testConfigPath, config)
301
- loader.save(testConfigPath)
302
-
303
- // 不预先加载,直接 get
304
- const data = service.get(testConfigPath, config)
305
- expect(data.test).toBe('value')
306
- expect(service.configs.has(testConfigPath)).toBe(true)
307
- })
308
- })
309
-
310
- describe('Extension detection', () => {
311
- it('should detect .json extension', () => {
312
- const loader = new ConfigLoader('config.json', {})
313
- expect(loader.extension).toBe('.json')
314
- })
315
-
316
- it('should detect .yml extension', () => {
317
- const loader = new ConfigLoader('config.yml', {})
318
- expect(loader.extension).toBe('.yml')
319
- })
320
-
321
- it('should detect .yaml extension', () => {
322
- const loader = new ConfigLoader('config.yaml', {})
323
- expect(loader.extension).toBe('.yaml')
324
- })
325
- })
326
- })
327
-
328
- // ============================================================================
329
- // ConfigFeature 补全测试
330
- // ============================================================================
331
- describe('ConfigFeature', () => {
332
- let feature: import('../src/built/config.js').ConfigFeature
333
-
334
- beforeEach(async () => {
335
- const { ConfigFeature } = await import('../src/built/config.js')
336
- feature = new ConfigFeature()
337
- })
338
-
339
- it('应有正确的元数据', () => {
340
- expect(feature.name).toBe('config')
341
- expect(feature.icon).toBe('Settings')
342
- expect(feature.desc).toBe('配置')
343
- })
344
-
345
- it('add 应添加配置记录', () => {
346
- const record = { key: 'debug', defaultValue: false }
347
- const dispose = feature.add(record, 'test-plugin')
348
- expect(feature.items).toHaveLength(1)
349
- expect(feature.items[0]).toBe(record)
350
- expect(typeof dispose).toBe('function')
351
- })
352
-
353
- it('toJSON 应返回正确结构', () => {
354
- feature.add({ key: 'debug', defaultValue: false }, 'test-plugin')
355
- feature.add({ key: 'port', defaultValue: 8080 }, 'test-plugin')
356
-
357
- const json = feature.toJSON()
358
- expect(json.name).toBe('config')
359
- expect(json.count).toBe(2)
360
- expect(json.items[0]).toEqual({ name: 'debug' })
361
- expect(json.items[1]).toEqual({ name: 'port' })
362
- })
363
-
364
- it('toJSON(pluginName) 应按插件过滤', () => {
365
- feature.add({ key: 'a', defaultValue: 1 }, 'plugin-a')
366
- feature.add({ key: 'b', defaultValue: 2 }, 'plugin-b')
367
-
368
- const json = feature.toJSON('plugin-a')
369
- expect(json.count).toBe(1)
370
- expect(json.items[0].name).toBe('a')
371
- })
372
- })
@@ -1,82 +0,0 @@
1
- /**
2
- * CronFeature 测试(Cron 类测试已迁移到 @zhin.js/kernel)
3
- */
4
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
5
- import { Cron } from '../src/cron'
6
-
7
- describe('CronFeature', () => {
8
- let feature: import('../src/built/cron.js').CronFeature
9
- let mockCallback: ReturnType<typeof vi.fn>
10
-
11
- beforeEach(async () => {
12
- vi.useFakeTimers()
13
- mockCallback = vi.fn()
14
- const { CronFeature } = await import('../src/built/cron.js')
15
- feature = new CronFeature()
16
- })
17
-
18
- afterEach(() => {
19
- feature?.dispose()
20
- vi.useRealTimers()
21
- })
22
-
23
- it('add 应自动启动任务', () => {
24
- const cron = new Cron('* * * * * *', mockCallback)
25
- feature.add(cron, 'test-plugin')
26
- expect(cron.running).toBe(true)
27
- expect(feature.items).toHaveLength(1)
28
- })
29
-
30
- it('add 应返回 dispose 函数', () => {
31
- const cron = new Cron('* * * * * *', mockCallback)
32
- const dispose = feature.add(cron, 'test-plugin')
33
- expect(typeof dispose).toBe('function')
34
- })
35
-
36
- it('remove 应自动停止任务', () => {
37
- const cron = new Cron('* * * * * *', mockCallback)
38
- feature.add(cron, 'test-plugin')
39
- feature.remove(cron)
40
- expect(cron.running).toBe(false)
41
- expect(feature.items).toHaveLength(0)
42
- })
43
-
44
- it('stopAll 应停止所有任务', () => {
45
- const cron1 = new Cron('* * * * * *', mockCallback)
46
- const cron2 = new Cron('*/2 * * * * *', mockCallback)
47
- feature.add(cron1, 'p1')
48
- feature.add(cron2, 'p2')
49
- feature.stopAll()
50
- expect(cron1.running).toBe(false)
51
- expect(cron2.running).toBe(false)
52
- })
53
-
54
- it('startAll 应启动所有已停止的任务', () => {
55
- const cron1 = new Cron('* * * * * *', mockCallback)
56
- const cron2 = new Cron('*/2 * * * * *', mockCallback)
57
- feature.add(cron1, 'p1')
58
- feature.add(cron2, 'p2')
59
- feature.stopAll()
60
- feature.startAll()
61
- expect(cron1.running).toBe(true)
62
- expect(cron2.running).toBe(true)
63
- })
64
-
65
- it('toJSON 应返回正确结构', () => {
66
- const cron = new Cron('* * * * * *', mockCallback)
67
- feature.add(cron, 'test-plugin')
68
- const json = feature.toJSON()
69
- expect(json.name).toBe('cron')
70
- expect(json.icon).toBe('Clock')
71
- expect(json.count).toBe(1)
72
- expect(json.items[0]).toHaveProperty('expression')
73
- expect(json.items[0]).toHaveProperty('running', true)
74
- })
75
-
76
- it('dispose 应停止所有任务', () => {
77
- const cron = new Cron('* * * * * *', mockCallback)
78
- feature.add(cron, 'test-plugin')
79
- feature.dispose()
80
- expect(cron.running).toBe(false)
81
- })
82
- })