@mingxy/ocosay 1.0.3 → 1.0.4

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 (59) hide show
  1. package/dist/config.js +2 -2
  2. package/dist/config.js.map +1 -1
  3. package/dist/plugin.js +2 -2
  4. package/dist/plugin.js.map +1 -1
  5. package/package.json +1 -1
  6. package/TECH_PLAN.md +0 -352
  7. package/__mocks__/@opencode-ai/plugin.ts +0 -32
  8. package/jest.config.js +0 -15
  9. package/src/config.ts +0 -183
  10. package/src/core/backends/afplay-backend.ts +0 -162
  11. package/src/core/backends/aplay-backend.ts +0 -160
  12. package/src/core/backends/base.ts +0 -117
  13. package/src/core/backends/index.ts +0 -128
  14. package/src/core/backends/naudiodon-backend.ts +0 -164
  15. package/src/core/backends/powershell-backend.ts +0 -173
  16. package/src/core/player.ts +0 -322
  17. package/src/core/speaker.ts +0 -283
  18. package/src/core/stream-player.ts +0 -326
  19. package/src/core/stream-reader.ts +0 -190
  20. package/src/core/streaming-synthesizer.ts +0 -123
  21. package/src/core/types.ts +0 -185
  22. package/src/index.ts +0 -236
  23. package/src/plugin.ts +0 -178
  24. package/src/providers/base.ts +0 -150
  25. package/src/providers/minimax.ts +0 -515
  26. package/src/tools/tts.ts +0 -277
  27. package/src/types/config.ts +0 -38
  28. package/src/types/naudiodon.d.ts +0 -19
  29. package/tests/__mocks__/@opencode-ai/plugin.ts +0 -32
  30. package/tests/backends.test.ts +0 -831
  31. package/tests/config.test.ts +0 -327
  32. package/tests/index.test.ts +0 -201
  33. package/tests/integration-test.d.ts +0 -6
  34. package/tests/integration-test.d.ts.map +0 -1
  35. package/tests/integration-test.js +0 -84
  36. package/tests/integration-test.js.map +0 -1
  37. package/tests/integration-test.ts +0 -93
  38. package/tests/p1-fixes.test.ts +0 -160
  39. package/tests/plugin.test.ts +0 -312
  40. package/tests/provider.test.d.ts +0 -2
  41. package/tests/provider.test.d.ts.map +0 -1
  42. package/tests/provider.test.js +0 -69
  43. package/tests/provider.test.js.map +0 -1
  44. package/tests/provider.test.ts +0 -87
  45. package/tests/speaker.test.d.ts +0 -2
  46. package/tests/speaker.test.d.ts.map +0 -1
  47. package/tests/speaker.test.js +0 -63
  48. package/tests/speaker.test.js.map +0 -1
  49. package/tests/speaker.test.ts +0 -232
  50. package/tests/stream-player.test.ts +0 -303
  51. package/tests/stream-reader.test.ts +0 -269
  52. package/tests/streaming-synthesizer.test.ts +0 -225
  53. package/tests/tts-tools.test.ts +0 -270
  54. package/tests/types.test.d.ts +0 -2
  55. package/tests/types.test.d.ts.map +0 -1
  56. package/tests/types.test.js +0 -61
  57. package/tests/types.test.js.map +0 -1
  58. package/tests/types.test.ts +0 -63
  59. package/tsconfig.json +0 -22
@@ -1,327 +0,0 @@
1
- import * as fs from 'fs'
2
- import * as path from 'path'
3
- import * as os from 'os'
4
- import { stripComments, generateDefaultConfig, mergeWithDefaults, loadOrCreateConfig } from '../src/config'
5
- import { DEFAULT_CONFIG } from '../src/types/config'
6
- import type { OcosayConfig } from '../src/types/config'
7
-
8
- jest.mock('fs')
9
- jest.mock('path')
10
- jest.mock('os')
11
-
12
- describe('config.ts', () => {
13
- const mockHomedir = '/home/testuser'
14
- const mockConfigPath = path.join(mockHomedir, '.config', 'opencode', 'ocosay.jsonc')
15
-
16
- beforeEach(() => {
17
- jest.clearAllMocks()
18
- ;(path.join as jest.Mock).mockReturnValue(mockConfigPath)
19
- ;(path.dirname as jest.Mock).mockReturnValue(path.dirname(mockConfigPath))
20
- ;(os.homedir as jest.Mock).mockReturnValue(mockHomedir)
21
- })
22
-
23
- describe('stripComments', () => {
24
- it('should strip single-line comments //', () => {
25
- const input = '{"enabled": true // comment'
26
- const result = stripComments(input)
27
- expect(result).toBe('{"enabled": true ')
28
- })
29
-
30
- it('should strip multi-line comments /* */', () => {
31
- const input = '{"enabled": true /* comment */}'
32
- const result = stripComments(input)
33
- expect(result).toBe('{"enabled": true }')
34
- })
35
-
36
- it('should strip multiple comments', () => {
37
- const input = `
38
- {
39
- // single line comment
40
- "enabled": true,
41
- /* multi
42
- line
43
- comment */
44
- "speed": 1.0
45
- }
46
- `
47
- const result = stripComments(input)
48
- expect(result).not.toContain('//')
49
- expect(result).not.toContain('/*')
50
- expect(result).not.toContain('*/')
51
- expect(result).toContain('"enabled": true')
52
- expect(result).toContain('"speed": 1.0')
53
- })
54
-
55
- it('should preserve JSON content', () => {
56
- const input = '{"enabled": true, "speed": 1.0}'
57
- const result = stripComments(input)
58
- expect(JSON.parse(result)).toEqual({ enabled: true, speed: 1.0 })
59
- })
60
-
61
- it('should preserve quoted strings containing // and /* */', () => {
62
- const input = '{"url": "https://example.com/api?foo=1&bar=2"}'
63
- const result = stripComments(input)
64
- expect(JSON.parse(result)).toEqual({ url: 'https://example.com/api?foo=1&bar=2' })
65
- })
66
-
67
- it('should preserve single-quoted strings', () => {
68
- const input = "{'key': 'value with // comment'}"
69
- const result = stripComments(input)
70
- expect(result).toContain('value with // comment')
71
- })
72
-
73
- it('should preserve template literals', () => {
74
- const input = '`string with // comment`'
75
- const result = stripComments(input)
76
- expect(result).toBe('`string with // comment`')
77
- })
78
-
79
- it('should handle comment at end of content', () => {
80
- const input = '{"key": "value"} // trailing'
81
- const result = stripComments(input)
82
- expect(result).toBe('{"key": "value"} ')
83
- })
84
-
85
- it('should handle empty string', () => {
86
- const result = stripComments('')
87
- expect(result).toBe('')
88
- })
89
- })
90
-
91
- describe('generateDefaultConfig', () => {
92
- it('should return complete OcosayConfig object', () => {
93
- const config = generateDefaultConfig()
94
- expect(config).toHaveProperty('enabled')
95
- expect(config).toHaveProperty('autoPlay')
96
- expect(config).toHaveProperty('autoRead')
97
- expect(config).toHaveProperty('streamMode')
98
- expect(config).toHaveProperty('streamBufferSize')
99
- expect(config).toHaveProperty('streamBufferTimeout')
100
- expect(config).toHaveProperty('speed')
101
- expect(config).toHaveProperty('volume')
102
- expect(config).toHaveProperty('pitch')
103
- expect(config).toHaveProperty('providers')
104
- expect(config).toHaveProperty('providers.minimax')
105
- })
106
-
107
- it('should have apiKey and baseURL as empty strings', () => {
108
- const config = generateDefaultConfig()
109
- expect(config.providers.minimax.apiKey).toBe('')
110
- expect(config.providers.minimax.baseURL).toBe('')
111
- expect(config.providers.minimax.voiceId).toBe('')
112
- })
113
-
114
- it('should have correct default values from DEFAULT_CONFIG', () => {
115
- const config = generateDefaultConfig()
116
- expect(config.enabled).toBe(DEFAULT_CONFIG.enabled)
117
- expect(config.autoPlay).toBe(DEFAULT_CONFIG.autoPlay)
118
- expect(config.autoRead).toBe(DEFAULT_CONFIG.autoRead)
119
- expect(config.streamMode).toBe(DEFAULT_CONFIG.streamMode)
120
- expect(config.streamBufferSize).toBe(DEFAULT_CONFIG.streamBufferSize)
121
- expect(config.streamBufferTimeout).toBe(DEFAULT_CONFIG.streamBufferTimeout)
122
- expect(config.speed).toBe(DEFAULT_CONFIG.speed)
123
- expect(config.volume).toBe(DEFAULT_CONFIG.volume)
124
- expect(config.pitch).toBe(DEFAULT_CONFIG.pitch)
125
- })
126
-
127
- it('should have correct minimax provider defaults', () => {
128
- const config = generateDefaultConfig()
129
- expect(config.providers.minimax.model).toBe('stream')
130
- expect(config.providers.minimax.ttsModel).toBe('speech-2.8-hd')
131
- expect(config.providers.minimax.audioFormat).toBe('mp3')
132
- })
133
- })
134
-
135
- describe('mergeWithDefaults', () => {
136
- it('should override defaults with user config', () => {
137
- const userConfig = { enabled: false, speed: 2.0 }
138
- const result = mergeWithDefaults(userConfig, DEFAULT_CONFIG)
139
- expect(result.enabled).toBe(false)
140
- expect(result.speed).toBe(2.0)
141
- })
142
-
143
- it('should use defaults for unspecified fields', () => {
144
- const userConfig: Partial<OcosayConfig> = { enabled: false }
145
- const result = mergeWithDefaults(userConfig, DEFAULT_CONFIG)
146
- expect(result.enabled).toBe(false)
147
- expect(result.autoPlay).toBe(DEFAULT_CONFIG.autoPlay)
148
- expect(result.autoRead).toBe(DEFAULT_CONFIG.autoRead)
149
- expect(result.streamMode).toBe(DEFAULT_CONFIG.streamMode)
150
- expect(result.speed).toBe(DEFAULT_CONFIG.speed)
151
- expect(result.volume).toBe(DEFAULT_CONFIG.volume)
152
- expect(result.pitch).toBe(DEFAULT_CONFIG.pitch)
153
- })
154
-
155
- it('should return defaults when no user config provided', () => {
156
- const result = mergeWithDefaults({}, DEFAULT_CONFIG)
157
- expect(result.enabled).toBe(DEFAULT_CONFIG.enabled)
158
- expect(result.autoPlay).toBe(DEFAULT_CONFIG.autoPlay)
159
- expect(result.autoRead).toBe(DEFAULT_CONFIG.autoRead)
160
- expect(result.streamBufferSize).toBe(DEFAULT_CONFIG.streamBufferSize)
161
- expect(result.streamBufferTimeout).toBe(DEFAULT_CONFIG.streamBufferTimeout)
162
- expect(result.speed).toBe(DEFAULT_CONFIG.speed)
163
- expect(result.volume).toBe(DEFAULT_CONFIG.volume)
164
- expect(result.pitch).toBe(DEFAULT_CONFIG.pitch)
165
- })
166
-
167
- it('should preserve all default fields', () => {
168
- const result = mergeWithDefaults({}, DEFAULT_CONFIG)
169
- expect(Object.keys(result).sort()).toEqual(Object.keys(DEFAULT_CONFIG).sort())
170
- })
171
- })
172
-
173
- describe('loadOrCreateConfig', () => {
174
- beforeEach(() => {
175
- // Reset module to clear any cached state
176
- jest.resetModules()
177
- jest.clearAllMocks()
178
- ;(path.join as jest.Mock).mockReturnValue(mockConfigPath)
179
- ;(path.dirname as jest.Mock).mockReturnValue(path.dirname(mockConfigPath))
180
- ;(os.homedir as jest.Mock).mockReturnValue(mockHomedir)
181
- })
182
-
183
- it('should create default config when config file does not exist', () => {
184
- ;(fs.existsSync as jest.Mock).mockReturnValue(false)
185
- ;(fs.mkdirSync as jest.Mock).mockReturnValue(undefined)
186
- ;(fs.writeFileSync as jest.Mock).mockReturnValue(undefined)
187
- ;(fs.chmodSync as jest.Mock).mockReturnValue(undefined)
188
-
189
- const config = loadOrCreateConfig()
190
-
191
- expect(fs.mkdirSync).toHaveBeenCalledWith(path.dirname(mockConfigPath), { recursive: true })
192
- expect(fs.writeFileSync).toHaveBeenCalled()
193
- expect(fs.chmodSync).toHaveBeenCalledWith(mockConfigPath, 0o600)
194
- expect(config.providers.minimax.apiKey).toBe('')
195
- expect(config.providers.minimax.baseURL).toBe('')
196
- })
197
-
198
- it('should create directory if it does not exist', () => {
199
- ;(fs.existsSync as jest.Mock).mockImplementation((p: string) => {
200
- if (p === path.dirname(mockConfigPath)) return false
201
- if (p === mockConfigPath) return false
202
- return false
203
- })
204
- ;(fs.mkdirSync as jest.Mock).mockReturnValue(undefined)
205
- ;(fs.writeFileSync as jest.Mock).mockReturnValue(undefined)
206
- ;(fs.chmodSync as jest.Mock).mockReturnValue(undefined)
207
-
208
- loadOrCreateConfig()
209
-
210
- expect(fs.mkdirSync).toHaveBeenCalledWith(path.dirname(mockConfigPath), { recursive: true })
211
- })
212
-
213
- it('should read and merge existing config file', () => {
214
- const existingConfig = {
215
- enabled: false,
216
- speed: 1.5,
217
- providers: {
218
- minimax: {
219
- apiKey: 'test-key',
220
- baseURL: 'https://api.minimax.io'
221
- }
222
- }
223
- }
224
-
225
- ;(fs.existsSync as jest.Mock).mockImplementation((p: string) => {
226
- return p === mockConfigPath || p === path.dirname(mockConfigPath)
227
- })
228
- ;(fs.readFileSync as jest.Mock).mockReturnValue(JSON.stringify(existingConfig))
229
-
230
- const config = loadOrCreateConfig()
231
-
232
- expect(fs.readFileSync).toHaveBeenCalledWith(mockConfigPath, 'utf-8')
233
- expect(config.enabled).toBe(false)
234
- expect(config.speed).toBe(1.5)
235
- expect(config.providers.minimax.apiKey).toBe('test-key')
236
- expect(config.providers.minimax.baseURL).toBe('https://api.minimax.io')
237
- })
238
-
239
- it('should merge user config with defaults', () => {
240
- const userConfig = {
241
- enabled: false
242
- // other fields missing
243
- }
244
-
245
- ;(fs.existsSync as jest.Mock).mockImplementation((p: string) => {
246
- return p === mockConfigPath || p === path.dirname(mockConfigPath)
247
- })
248
- ;(fs.readFileSync as jest.Mock).mockReturnValue(JSON.stringify(userConfig))
249
-
250
- const config = loadOrCreateConfig()
251
-
252
- expect(config.enabled).toBe(false)
253
- expect(config.autoPlay).toBe(DEFAULT_CONFIG.autoPlay)
254
- expect(config.speed).toBe(DEFAULT_CONFIG.speed)
255
- })
256
-
257
- it('should handle config file with comments', () => {
258
- const jsoncContent = `{
259
- // This is a comment
260
- "enabled": false,
261
- /* Another comment */
262
- "speed": 1.8
263
- }`
264
-
265
- ;(fs.existsSync as jest.Mock).mockImplementation((p: string) => {
266
- return p === mockConfigPath || p === path.dirname(mockConfigPath)
267
- })
268
- ;(fs.readFileSync as jest.Mock).mockReturnValue(jsoncContent)
269
-
270
- const config = loadOrCreateConfig()
271
-
272
- expect(config.enabled).toBe(false)
273
- expect(config.speed).toBe(1.8)
274
- })
275
-
276
- it('should use default config on parse error', () => {
277
- ;(fs.existsSync as jest.Mock).mockImplementation((p: string) => {
278
- return p === mockConfigPath || p === path.dirname(mockConfigPath)
279
- })
280
- ;(fs.readFileSync as jest.Mock).mockReturnValue('invalid json {')
281
-
282
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation()
283
- const config = loadOrCreateConfig()
284
-
285
- expect(consoleErrorSpy).toHaveBeenCalled()
286
- expect(config.providers.minimax.apiKey).toBe('')
287
- expect(config.providers.minimax.baseURL).toBe('')
288
-
289
- consoleErrorSpy.mockRestore()
290
- })
291
-
292
- it('should handle minimax provider partial config', () => {
293
- const userConfig = {
294
- providers: {
295
- minimax: {
296
- apiKey: 'my-key'
297
- // baseURL, voiceId, model, ttsModel, audioFormat missing
298
- }
299
- }
300
- }
301
-
302
- ;(fs.existsSync as jest.Mock).mockImplementation((p: string) => {
303
- return p === mockConfigPath || p === path.dirname(mockConfigPath)
304
- })
305
- ;(fs.readFileSync as jest.Mock).mockReturnValue(JSON.stringify(userConfig))
306
-
307
- const config = loadOrCreateConfig()
308
-
309
- expect(config.providers.minimax.apiKey).toBe('my-key')
310
- expect(config.providers.minimax.baseURL).toBe('')
311
- expect(config.providers.minimax.model).toBe('stream')
312
- expect(config.providers.minimax.ttsModel).toBe('speech-2.8-hd')
313
- expect(config.providers.minimax.audioFormat).toBe('mp3')
314
- })
315
-
316
- it('should set correct file permissions on new config', () => {
317
- ;(fs.existsSync as jest.Mock).mockReturnValue(false)
318
- ;(fs.mkdirSync as jest.Mock).mockReturnValue(undefined)
319
- ;(fs.writeFileSync as jest.Mock).mockReturnValue(undefined)
320
- ;(fs.chmodSync as jest.Mock).mockReturnValue(undefined)
321
-
322
- loadOrCreateConfig()
323
-
324
- expect(fs.chmodSync).toHaveBeenCalledWith(mockConfigPath, 0o600)
325
- })
326
- })
327
- })
@@ -1,201 +0,0 @@
1
- import { pluginInfo, toolNames, initialize, destroy, isStreamEnabled, getStreamReader } from '../src/index'
2
- import { registerProvider, unregisterProvider, BaseTTSProvider } from '../src/providers/base'
3
- import { TTSCapabilities } from '../src/core/types'
4
-
5
- class MockProvider extends BaseTTSProvider {
6
- name = 'mock'
7
- capabilities: TTSCapabilities = { speak: true, stream: true }
8
-
9
- protected async doSpeak(text: string, voice: string | undefined, model: any) {
10
- return {
11
- audioData: Buffer.from([1, 2, 3]),
12
- format: 'mp3',
13
- isStream: model === 'stream',
14
- duration: 1.0
15
- }
16
- }
17
- }
18
-
19
- describe('index module exports', () => {
20
- describe('pluginInfo', () => {
21
- it('should export correct plugin info', () => {
22
- expect(pluginInfo.name).toBe('ocosay')
23
- expect(pluginInfo.version).toBe('1.0.0')
24
- expect(pluginInfo.description).toContain('TTS')
25
- })
26
- })
27
-
28
- describe('toolNames', () => {
29
- it('should export array of tool names', () => {
30
- expect(Array.isArray(toolNames)).toBe(true)
31
- expect(toolNames.length).toBeGreaterThan(0)
32
- })
33
-
34
- it('should include tts_speak', () => {
35
- expect(toolNames).toContain('tts_speak')
36
- })
37
-
38
- it('should include tts_stop', () => {
39
- expect(toolNames).toContain('tts_stop')
40
- })
41
-
42
- it('should include tts_stream_speak', () => {
43
- expect(toolNames).toContain('tts_stream_speak')
44
- })
45
- })
46
- })
47
-
48
- describe('TuiEventBus integration', () => {
49
- const originalGlobal = global as any
50
- let mockProvider: MockProvider
51
-
52
- beforeEach(() => {
53
- mockProvider = new MockProvider()
54
- registerProvider('mock', mockProvider)
55
- })
56
-
57
- afterEach(async () => {
58
- delete originalGlobal.__opencode_tuieventbus__
59
- await destroy()
60
- unregisterProvider('mock')
61
- })
62
-
63
- describe('P1-1: eventBus available', () => {
64
- it('should subscribe to message.part.delta and message.part.end events', async () => {
65
- const mockOn = jest.fn()
66
- const mockOff = jest.fn()
67
- const MockTuiEventBus = jest.fn().mockImplementation(() => ({
68
- on: mockOn,
69
- off: mockOff
70
- }))
71
- originalGlobal.__opencode_tuieventbus__ = MockTuiEventBus
72
-
73
- await initialize({
74
- autoRead: true,
75
- defaultProvider: 'mock'
76
- })
77
-
78
- expect(mockOn).toHaveBeenCalledWith('message.part.delta', expect.any(Function))
79
- expect(mockOn).toHaveBeenCalledWith('message.part.end', expect.any(Function))
80
- })
81
-
82
- it('should handle delta events via streamReader', async () => {
83
- const mockOn = jest.fn()
84
- const mockOff = jest.fn()
85
- let deltaHandler: Function | undefined
86
-
87
- mockOn.mockImplementation((event: string, handler: Function) => {
88
- if (event === 'message.part.delta') {
89
- deltaHandler = handler
90
- }
91
- })
92
-
93
- const MockTuiEventBus = jest.fn().mockImplementation(() => ({
94
- on: mockOn,
95
- off: mockOff
96
- }))
97
- originalGlobal.__opencode_tuieventbus__ = MockTuiEventBus
98
-
99
- await initialize({
100
- autoRead: true,
101
- defaultProvider: 'mock'
102
- })
103
-
104
- const mockEvent = {
105
- sessionId: 'session-1',
106
- messageId: 'msg-1',
107
- partId: 'part-1',
108
- properties: { delta: 'Hello' }
109
- }
110
-
111
- expect(deltaHandler).toBeDefined()
112
- deltaHandler!(mockEvent)
113
- })
114
- })
115
-
116
- describe('P1-1: eventBus unavailable (graceful fallback)', () => {
117
- it('should not throw when eventBus is not available', async () => {
118
- delete originalGlobal.__opencode_tuieventbus__
119
-
120
- await expect(initialize({
121
- autoRead: true,
122
- defaultProvider: 'mock'
123
- })).resolves.not.toThrow()
124
- })
125
-
126
- it('should have stream components initialized even without eventBus', async () => {
127
- delete originalGlobal.__opencode_tuieventbus__
128
-
129
- await initialize({
130
- autoRead: true,
131
- defaultProvider: 'mock'
132
- })
133
-
134
- expect(isStreamEnabled()).toBe(true)
135
- expect(getStreamReader()).toBeDefined()
136
- })
137
- })
138
- })
139
-
140
- describe('initialize() idempotency', () => {
141
- let mockProvider: MockProvider
142
-
143
- beforeEach(() => {
144
- mockProvider = new MockProvider()
145
- registerProvider('mock', mockProvider)
146
- })
147
-
148
- afterEach(async () => {
149
- await destroy()
150
- unregisterProvider('mock')
151
- })
152
-
153
- describe('P1-2: repeated initialize() calls', () => {
154
- it('should be safe to call initialize() multiple times', async () => {
155
- await initialize({
156
- defaultProvider: 'mock'
157
- })
158
-
159
- await expect(initialize({
160
- defaultProvider: 'mock'
161
- })).resolves.not.toThrow()
162
-
163
- await expect(initialize({
164
- defaultProvider: 'mock'
165
- })).resolves.not.toThrow()
166
- })
167
-
168
- it('should not re-initialize components on repeated calls', async () => {
169
- await initialize({
170
- autoRead: true,
171
- defaultProvider: 'mock'
172
- })
173
-
174
- const firstStreamReader = getStreamReader()
175
- expect(firstStreamReader).toBeDefined()
176
-
177
- await initialize({
178
- defaultProvider: 'mock'
179
- })
180
-
181
- const secondStreamReader = getStreamReader()
182
- expect(secondStreamReader).toBe(firstStreamReader)
183
- })
184
-
185
- it('should return early if already initialized', async () => {
186
- const spyInitialize = jest.spyOn(mockProvider, 'initialize')
187
-
188
- await initialize({
189
- defaultProvider: 'mock'
190
- })
191
-
192
- spyInitialize.mockClear()
193
-
194
- await initialize({
195
- defaultProvider: 'mock'
196
- })
197
-
198
- expect(spyInitialize).not.toHaveBeenCalled()
199
- })
200
- })
201
- })
@@ -1,6 +0,0 @@
1
- /**
2
- * 真实 TTS 集成测试
3
- * 需要设置环境变量: MINIMAX_API_KEY
4
- */
5
- export {};
6
- //# sourceMappingURL=integration-test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integration-test.d.ts","sourceRoot":"","sources":["integration-test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -1,84 +0,0 @@
1
- const { initialize } = require('../dist/index')
2
- const { getProvider } = require('../dist/providers/base')
3
-
4
- const API_KEY = process.env.MINIMAX_API_KEY
5
-
6
- if (!API_KEY) {
7
- console.error('❌ 请设置环境变量 MINIMAX_API_KEY')
8
- console.log('示例: MINIMAX_API_KEY=your-api-key node tests/integration-test.js')
9
- process.exit(1)
10
- }
11
-
12
- async function test() {
13
- console.log('🔧 初始化 ocosay...')
14
-
15
- await initialize({
16
- providers: {
17
- minimax: {
18
- apiKey: API_KEY,
19
- voiceId: 'male-qn-qingse',
20
- model: 'stream'
21
- }
22
- }
23
- })
24
-
25
- console.log('✅ 初始化成功!\n')
26
-
27
- console.log('📝 测试 1: 同步合成 (model: sync)')
28
- try {
29
- const provider = getProvider('minimax')
30
- const result = await provider.speak('你好,这是同步合成测试!', { model: 'sync' })
31
- const data = Buffer.isBuffer(result.audioData) ? result.audioData : Buffer.from([])
32
- console.log('✅ 同步合成成功! 音频大小: ' + data.length + ' bytes, 格式: ' + result.format)
33
- } catch (error) {
34
- console.error('❌ 同步合成失败:', error.message || error)
35
- }
36
-
37
- console.log('')
38
-
39
- console.log('📝 测试 2: 流式合成 (model: stream)')
40
- try {
41
- const provider = getProvider('minimax')
42
- const result = await provider.speak('你好,这是流式合成测试!', { model: 'stream' })
43
- const data = Buffer.isBuffer(result.audioData) ? result.audioData : Buffer.from([])
44
- console.log('✅ 流式合成成功! 音频大小: ' + data.length + ' bytes, 格式: ' + result.format)
45
- } catch (error) {
46
- console.error('❌ 流式合成失败:', error.message || error)
47
- }
48
-
49
- console.log('')
50
-
51
- console.log('📝 测试 3: 异步合成 (model: async)')
52
- try {
53
- const provider = getProvider('minimax')
54
- const result = await provider.speak('你好,这是异步合成测试!', { model: 'async' })
55
- const data = Buffer.isBuffer(result.audioData) ? result.audioData : Buffer.from([])
56
- console.log('✅ 异步合成成功! 音频大小: ' + data.length + ' bytes, 格式: ' + result.format)
57
- } catch (error) {
58
- console.error('❌ 异步合成失败:', error.message || error)
59
- }
60
-
61
- console.log('')
62
-
63
- console.log('📝 测试 4: 列出音色')
64
- try {
65
- const provider = getProvider('minimax')
66
- const voices = await provider.listVoices()
67
- console.log('✅ 获取到 ' + voices.length + ' 个音色:')
68
- voices.slice(0, 5).forEach(v => {
69
- console.log(' - ' + v.id + ': ' + v.name + ' (' + (v.language || 'unknown') + ')')
70
- })
71
- } catch (error) {
72
- console.error('❌ 列出音色失败:', error.message || error)
73
- }
74
-
75
- console.log('')
76
- console.log('🎉 集成测试完成!')
77
-
78
- process.exit(0)
79
- }
80
-
81
- test().catch(err => {
82
- console.error('❌ 测试失败:', err)
83
- process.exit(1)
84
- })
@@ -1 +0,0 @@
1
- {"version":3,"file":"integration-test.js","sourceRoot":"","sources":["integration-test.ts"],"names":[],"mappings":"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"}