@mingxy/ocosay 1.0.0

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/README.md +556 -0
  2. package/TECH_PLAN.md +352 -0
  3. package/__mocks__/@opencode-ai/plugin.ts +32 -0
  4. package/dist/config.d.ts +26 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +95 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/core/backends/afplay-backend.d.ts +33 -0
  9. package/dist/core/backends/afplay-backend.d.ts.map +1 -0
  10. package/dist/core/backends/afplay-backend.js +144 -0
  11. package/dist/core/backends/afplay-backend.js.map +1 -0
  12. package/dist/core/backends/aplay-backend.d.ts +33 -0
  13. package/dist/core/backends/aplay-backend.d.ts.map +1 -0
  14. package/dist/core/backends/aplay-backend.js +142 -0
  15. package/dist/core/backends/aplay-backend.js.map +1 -0
  16. package/dist/core/backends/base.d.ts +94 -0
  17. package/dist/core/backends/base.d.ts.map +1 -0
  18. package/dist/core/backends/base.js +6 -0
  19. package/dist/core/backends/base.js.map +1 -0
  20. package/dist/core/backends/index.d.ts +29 -0
  21. package/dist/core/backends/index.d.ts.map +1 -0
  22. package/dist/core/backends/index.js +114 -0
  23. package/dist/core/backends/index.js.map +1 -0
  24. package/dist/core/backends/naudiodon-backend.d.ts +52 -0
  25. package/dist/core/backends/naudiodon-backend.d.ts.map +1 -0
  26. package/dist/core/backends/naudiodon-backend.js +123 -0
  27. package/dist/core/backends/naudiodon-backend.js.map +1 -0
  28. package/dist/core/backends/powershell-backend.d.ts +34 -0
  29. package/dist/core/backends/powershell-backend.d.ts.map +1 -0
  30. package/dist/core/backends/powershell-backend.js +154 -0
  31. package/dist/core/backends/powershell-backend.js.map +1 -0
  32. package/dist/core/player.d.ts +97 -0
  33. package/dist/core/player.d.ts.map +1 -0
  34. package/dist/core/player.js +268 -0
  35. package/dist/core/player.js.map +1 -0
  36. package/dist/core/speaker.d.ts +97 -0
  37. package/dist/core/speaker.d.ts.map +1 -0
  38. package/dist/core/speaker.js +218 -0
  39. package/dist/core/speaker.js.map +1 -0
  40. package/dist/core/stream-player.d.ts +107 -0
  41. package/dist/core/stream-player.d.ts.map +1 -0
  42. package/dist/core/stream-player.js +272 -0
  43. package/dist/core/stream-player.js.map +1 -0
  44. package/dist/core/stream-reader.d.ts +86 -0
  45. package/dist/core/stream-reader.d.ts.map +1 -0
  46. package/dist/core/stream-reader.js +172 -0
  47. package/dist/core/stream-reader.js.map +1 -0
  48. package/dist/core/streaming-synthesizer.d.ts +51 -0
  49. package/dist/core/streaming-synthesizer.d.ts.map +1 -0
  50. package/dist/core/streaming-synthesizer.js +103 -0
  51. package/dist/core/streaming-synthesizer.js.map +1 -0
  52. package/dist/core/types.d.ts +141 -0
  53. package/dist/core/types.d.ts.map +1 -0
  54. package/dist/core/types.js +37 -0
  55. package/dist/core/types.js.map +1 -0
  56. package/dist/index.d.ts +40 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +179 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/plugin.d.ts +4 -0
  61. package/dist/plugin.d.ts.map +1 -0
  62. package/dist/plugin.js +151 -0
  63. package/dist/plugin.js.map +1 -0
  64. package/dist/providers/base.d.ts +55 -0
  65. package/dist/providers/base.d.ts.map +1 -0
  66. package/dist/providers/base.js +95 -0
  67. package/dist/providers/base.js.map +1 -0
  68. package/dist/providers/minimax.d.ts +84 -0
  69. package/dist/providers/minimax.d.ts.map +1 -0
  70. package/dist/providers/minimax.js +387 -0
  71. package/dist/providers/minimax.js.map +1 -0
  72. package/dist/tools/tts.d.ts +147 -0
  73. package/dist/tools/tts.d.ts.map +1 -0
  74. package/dist/tools/tts.js +232 -0
  75. package/dist/tools/tts.js.map +1 -0
  76. package/jest.config.js +15 -0
  77. package/package.json +49 -0
  78. package/src/config.ts +121 -0
  79. package/src/core/backends/afplay-backend.ts +162 -0
  80. package/src/core/backends/aplay-backend.ts +160 -0
  81. package/src/core/backends/base.ts +117 -0
  82. package/src/core/backends/index.ts +128 -0
  83. package/src/core/backends/naudiodon-backend.ts +164 -0
  84. package/src/core/backends/powershell-backend.ts +173 -0
  85. package/src/core/player.ts +322 -0
  86. package/src/core/speaker.ts +283 -0
  87. package/src/core/stream-player.ts +326 -0
  88. package/src/core/stream-reader.ts +190 -0
  89. package/src/core/streaming-synthesizer.ts +123 -0
  90. package/src/core/types.ts +185 -0
  91. package/src/index.ts +233 -0
  92. package/src/plugin.ts +166 -0
  93. package/src/providers/base.ts +150 -0
  94. package/src/providers/minimax.ts +515 -0
  95. package/src/tools/tts.ts +277 -0
  96. package/src/types/naudiodon.d.ts +19 -0
  97. package/tests/__mocks__/@opencode-ai/plugin.ts +32 -0
  98. package/tests/backends.test.ts +831 -0
  99. package/tests/index.test.ts +201 -0
  100. package/tests/integration-test.d.ts +6 -0
  101. package/tests/integration-test.d.ts.map +1 -0
  102. package/tests/integration-test.js +84 -0
  103. package/tests/integration-test.js.map +1 -0
  104. package/tests/integration-test.ts +93 -0
  105. package/tests/p1-fixes.test.ts +160 -0
  106. package/tests/plugin.test.ts +311 -0
  107. package/tests/provider.test.d.ts +2 -0
  108. package/tests/provider.test.d.ts.map +1 -0
  109. package/tests/provider.test.js +69 -0
  110. package/tests/provider.test.js.map +1 -0
  111. package/tests/provider.test.ts +87 -0
  112. package/tests/speaker.test.d.ts +2 -0
  113. package/tests/speaker.test.d.ts.map +1 -0
  114. package/tests/speaker.test.js +63 -0
  115. package/tests/speaker.test.js.map +1 -0
  116. package/tests/speaker.test.ts +232 -0
  117. package/tests/stream-player.test.ts +303 -0
  118. package/tests/stream-reader.test.ts +269 -0
  119. package/tests/streaming-synthesizer.test.ts +225 -0
  120. package/tests/tts-tools.test.ts +270 -0
  121. package/tests/types.test.d.ts +2 -0
  122. package/tests/types.test.d.ts.map +1 -0
  123. package/tests/types.test.js +61 -0
  124. package/tests/types.test.js.map +1 -0
  125. package/tests/types.test.ts +63 -0
  126. package/tsconfig.json +22 -0
@@ -0,0 +1,86 @@
1
+ /**
2
+ * StreamReader - 流式文本缓冲与句子边界检测
3
+ *
4
+ * 功能:
5
+ * - 订阅 TuiEventBus 的 message.part.delta 事件
6
+ * - 缓冲区满或遇到句子结束符时触发 textReady 事件
7
+ * - 支持超时强制发送
8
+ */
9
+ import { EventEmitter } from 'events';
10
+ import { StreamState, TTSError } from './types';
11
+ export declare class StreamReader extends EventEmitter {
12
+ private bufferSize;
13
+ private bufferTimeout;
14
+ private state;
15
+ private buffer;
16
+ private sessionID?;
17
+ private messageID?;
18
+ private partID?;
19
+ private timeoutHandle?;
20
+ constructor(bufferSize?: number, bufferTimeout?: number);
21
+ /**
22
+ * 启动流式监听
23
+ * 将状态从 IDLE 切换到 BUFFERING,开始监听事件
24
+ */
25
+ start(): void;
26
+ /**
27
+ * 处理 message.part.delta 事件
28
+ */
29
+ handleDelta(sessionID: string, messageID: string, partID: string, delta: string): void;
30
+ /**
31
+ * 处理流结束
32
+ */
33
+ handleEnd(): void;
34
+ /**
35
+ * 处理错误
36
+ */
37
+ handleError(error: TTSError): void;
38
+ /**
39
+ * 重置缓冲器
40
+ */
41
+ reset(): void;
42
+ /**
43
+ * 判断是否应该刷新缓冲区
44
+ * 条件:
45
+ * 1. 包含句子结束符(任何长度)
46
+ * 2. 缓冲区长度 >= bufferSize
47
+ */
48
+ private shouldFlush;
49
+ /**
50
+ * 刷新缓冲区,发送textReady事件
51
+ */
52
+ private flushBuffer;
53
+ /**
54
+ * 重置超时计时器
55
+ */
56
+ private resetTimeout;
57
+ /**
58
+ * 清除超时计时器
59
+ */
60
+ private clearTimeout;
61
+ /**
62
+ * 获取当前状态
63
+ */
64
+ getState(): StreamState;
65
+ /**
66
+ * 检查流是否处于活跃状态
67
+ */
68
+ isActive(): boolean;
69
+ /**
70
+ * 获取当前缓冲区内容
71
+ */
72
+ getBuffer(): string;
73
+ /**
74
+ * 获取当前会话ID
75
+ */
76
+ getSessionID(): string | undefined;
77
+ /**
78
+ * 获取当前消息ID
79
+ */
80
+ getMessageID(): string | undefined;
81
+ /**
82
+ * 获取当前分块ID
83
+ */
84
+ getPartID(): string | undefined;
85
+ }
86
+ //# sourceMappingURL=stream-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-reader.d.ts","sourceRoot":"","sources":["../../src/core/stream-reader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAgB,MAAM,SAAS,CAAA;AAE7D,qBAAa,YAAa,SAAQ,YAAY;IAS1C,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,aAAa;IATvB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAC,CAAQ;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAQ;IACvB,OAAO,CAAC,aAAa,CAAC,CAAgB;gBAG5B,UAAU,GAAE,MAAW,EACvB,aAAa,GAAE,MAAa;IAKtC;;;OAGG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAiBtF;;OAEG;IACH,SAAS,IAAI,IAAI;IAYjB;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAOlC;;OAEG;IACH,KAAK,IAAI,IAAI;IASb;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAanB;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,QAAQ,IAAI,WAAW;IAIvB;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,SAAS;IAIlC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,SAAS;IAIlC;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,SAAS;CAGhC"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * StreamReader - 流式文本缓冲与句子边界检测
3
+ *
4
+ * 功能:
5
+ * - 订阅 TuiEventBus 的 message.part.delta 事件
6
+ * - 缓冲区满或遇到句子结束符时触发 textReady 事件
7
+ * - 支持超时强制发送
8
+ */
9
+ import { EventEmitter } from 'events';
10
+ import { StreamState } from './types';
11
+ export class StreamReader extends EventEmitter {
12
+ bufferSize;
13
+ bufferTimeout;
14
+ state = StreamState.IDLE;
15
+ buffer = '';
16
+ sessionID;
17
+ messageID;
18
+ partID;
19
+ timeoutHandle;
20
+ constructor(bufferSize = 30, bufferTimeout = 2000) {
21
+ super();
22
+ this.bufferSize = bufferSize;
23
+ this.bufferTimeout = bufferTimeout;
24
+ }
25
+ /**
26
+ * 启动流式监听
27
+ * 将状态从 IDLE 切换到 BUFFERING,开始监听事件
28
+ */
29
+ start() {
30
+ if (this.state === StreamState.IDLE) {
31
+ this.state = StreamState.BUFFERING;
32
+ this.emit('streamStart');
33
+ }
34
+ }
35
+ /**
36
+ * 处理 message.part.delta 事件
37
+ */
38
+ handleDelta(sessionID, messageID, partID, delta) {
39
+ if (this.state === StreamState.IDLE) {
40
+ this.state = StreamState.BUFFERING;
41
+ this.sessionID = sessionID;
42
+ this.messageID = messageID;
43
+ this.partID = partID;
44
+ this.emit('streamStart');
45
+ }
46
+ this.buffer += delta;
47
+ this.resetTimeout();
48
+ if (this.shouldFlush()) {
49
+ this.flushBuffer();
50
+ }
51
+ }
52
+ /**
53
+ * 处理流结束
54
+ */
55
+ handleEnd() {
56
+ if (this.state === StreamState.ENDED) {
57
+ return;
58
+ }
59
+ if (this.buffer.length > 0) {
60
+ this.flushBuffer();
61
+ }
62
+ this.state = StreamState.ENDED;
63
+ this.clearTimeout();
64
+ this.emit('streamEnd');
65
+ }
66
+ /**
67
+ * 处理错误
68
+ */
69
+ handleError(error) {
70
+ this.clearTimeout();
71
+ this.state = StreamState.IDLE;
72
+ this.buffer = '';
73
+ this.emit('streamError', error);
74
+ }
75
+ /**
76
+ * 重置缓冲器
77
+ */
78
+ reset() {
79
+ this.state = StreamState.IDLE;
80
+ this.buffer = '';
81
+ this.sessionID = undefined;
82
+ this.messageID = undefined;
83
+ this.partID = undefined;
84
+ this.clearTimeout();
85
+ }
86
+ /**
87
+ * 判断是否应该刷新缓冲区
88
+ * 条件:
89
+ * 1. 包含句子结束符(任何长度)
90
+ * 2. 缓冲区长度 >= bufferSize
91
+ */
92
+ shouldFlush() {
93
+ // 句子结束标记:。!?.!?……(中文句号、感叹号、问号、省略号)
94
+ const sentenceEnd = /[。!?.!?]|……/;
95
+ if (sentenceEnd.test(this.buffer)) {
96
+ return true;
97
+ }
98
+ // 缓冲区达到阈值
99
+ if (this.buffer.length >= this.bufferSize) {
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ /**
105
+ * 刷新缓冲区,发送textReady事件
106
+ */
107
+ flushBuffer() {
108
+ const text = this.buffer.trim();
109
+ if (text.length > 0) {
110
+ this.emit('textReady', text);
111
+ }
112
+ this.buffer = '';
113
+ this.resetTimeout();
114
+ }
115
+ /**
116
+ * 重置超时计时器
117
+ */
118
+ resetTimeout() {
119
+ this.clearTimeout();
120
+ this.timeoutHandle = setTimeout(() => {
121
+ if (this.buffer.length > 0) {
122
+ this.flushBuffer();
123
+ }
124
+ }, this.bufferTimeout);
125
+ }
126
+ /**
127
+ * 清除超时计时器
128
+ */
129
+ clearTimeout() {
130
+ if (this.timeoutHandle) {
131
+ clearTimeout(this.timeoutHandle);
132
+ this.timeoutHandle = undefined;
133
+ }
134
+ }
135
+ /**
136
+ * 获取当前状态
137
+ */
138
+ getState() {
139
+ return this.state;
140
+ }
141
+ /**
142
+ * 检查流是否处于活跃状态
143
+ */
144
+ isActive() {
145
+ return this.state === StreamState.BUFFERING;
146
+ }
147
+ /**
148
+ * 获取当前缓冲区内容
149
+ */
150
+ getBuffer() {
151
+ return this.buffer;
152
+ }
153
+ /**
154
+ * 获取当前会话ID
155
+ */
156
+ getSessionID() {
157
+ return this.sessionID;
158
+ }
159
+ /**
160
+ * 获取当前消息ID
161
+ */
162
+ getMessageID() {
163
+ return this.messageID;
164
+ }
165
+ /**
166
+ * 获取当前分块ID
167
+ */
168
+ getPartID() {
169
+ return this.partID;
170
+ }
171
+ }
172
+ //# sourceMappingURL=stream-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-reader.js","sourceRoot":"","sources":["../../src/core/stream-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * StreamingSynthesizer - 流式合成器
3
+ *
4
+ * 功能:
5
+ * - 接收 StreamReader 发来的文本(通过 synthesize 方法)
6
+ * - 调用 TTSProvider 的流式合成接口
7
+ * - 将返回的音频 chunk 传递给下游(StreamPlayer)
8
+ *
9
+ * 数据流:
10
+ * StreamReader.textReady → StreamingSynthesizer.synthesize() → StreamPlayer (边收边播)
11
+ */
12
+ import { EventEmitter } from 'events';
13
+ import { TTSError, StreamingSynthesizerOptions } from './types';
14
+ export interface StreamingSynthesizerEvents {
15
+ on(event: 'chunk', handler: (chunk: Buffer) => void): void;
16
+ on(event: 'error', handler: (error: TTSError) => void): void;
17
+ on(event: 'done', handler: () => void): void;
18
+ }
19
+ export declare class StreamingSynthesizer extends EventEmitter {
20
+ private options;
21
+ private audioChunks;
22
+ constructor(options: StreamingSynthesizerOptions);
23
+ /**
24
+ * 发送文本片段进行合成
25
+ * 调用 provider.speak() 并处理返回的音频流
26
+ */
27
+ synthesize(text: string): Promise<void>;
28
+ /**
29
+ * 处理 AudioResult,根据 audioData 类型进行相应处理
30
+ */
31
+ private processAudioResult;
32
+ /**
33
+ * 处理 ReadableStream,逐chunk emit
34
+ */
35
+ private processReadableStream;
36
+ /**
37
+ * emit chunk 并累积
38
+ */
39
+ private emitChunk;
40
+ /**
41
+ * 重置状态
42
+ * 清空累积的音频数据
43
+ */
44
+ reset(): void;
45
+ /**
46
+ * 获取累积的音频数据
47
+ * 返回所有已接收的 chunk
48
+ */
49
+ getAudioChunks(): Buffer[];
50
+ }
51
+ //# sourceMappingURL=streaming-synthesizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-synthesizer.d.ts","sourceRoot":"","sources":["../../src/core/streaming-synthesizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAe,QAAQ,EAAgB,2BAA2B,EAAe,MAAM,SAAS,CAAA;AAEvG,MAAM,WAAW,0BAA0B;IACzC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;IAC1D,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI,CAAA;IAC5D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;CAC7C;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IAGxC,OAAO,CAAC,OAAO;IAF3B,OAAO,CAAC,WAAW,CAAe;gBAEd,OAAO,EAAE,2BAA2B;IAIxD;;;OAGG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B7C;;OAEG;YACW,kBAAkB;IAUhC;;OAEG;YACW,qBAAqB;IAqBnC;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,cAAc,IAAI,MAAM,EAAE;CAG3B"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * StreamingSynthesizer - 流式合成器
3
+ *
4
+ * 功能:
5
+ * - 接收 StreamReader 发来的文本(通过 synthesize 方法)
6
+ * - 调用 TTSProvider 的流式合成接口
7
+ * - 将返回的音频 chunk 传递给下游(StreamPlayer)
8
+ *
9
+ * 数据流:
10
+ * StreamReader.textReady → StreamingSynthesizer.synthesize() → StreamPlayer (边收边播)
11
+ */
12
+ import { EventEmitter } from 'events';
13
+ import { TTSError } from './types';
14
+ export class StreamingSynthesizer extends EventEmitter {
15
+ options;
16
+ audioChunks = [];
17
+ constructor(options) {
18
+ super();
19
+ this.options = options;
20
+ }
21
+ /**
22
+ * 发送文本片段进行合成
23
+ * 调用 provider.speak() 并处理返回的音频流
24
+ */
25
+ async synthesize(text) {
26
+ if (!text || text.trim().length === 0) {
27
+ return;
28
+ }
29
+ try {
30
+ const result = await this.options.provider.speak(text, {
31
+ model: 'stream',
32
+ voice: this.options.voice,
33
+ speed: this.options.speed,
34
+ volume: this.options.volume,
35
+ pitch: this.options.pitch
36
+ });
37
+ await this.processAudioResult(result);
38
+ this.emit('done');
39
+ }
40
+ catch (error) {
41
+ const ttsError = error instanceof TTSError
42
+ ? error
43
+ : new TTSError(error instanceof Error ? error.message : 'Synthesis failed', 'UNKNOWN', this.options.provider.name, error);
44
+ this.emit('error', ttsError);
45
+ }
46
+ }
47
+ /**
48
+ * 处理 AudioResult,根据 audioData 类型进行相应处理
49
+ */
50
+ async processAudioResult(result) {
51
+ if (result.isStream && result.audioData instanceof ReadableStream) {
52
+ // 流式数据:ReadableStream
53
+ await this.processReadableStream(result.audioData);
54
+ }
55
+ else if (Buffer.isBuffer(result.audioData)) {
56
+ // 非流式数据:Buffer
57
+ this.emitChunk(result.audioData);
58
+ }
59
+ }
60
+ /**
61
+ * 处理 ReadableStream,逐chunk emit
62
+ */
63
+ async processReadableStream(stream) {
64
+ const reader = stream.getReader();
65
+ try {
66
+ while (true) {
67
+ const { done, value } = await reader.read();
68
+ if (done) {
69
+ break;
70
+ }
71
+ if (value) {
72
+ const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
73
+ this.emitChunk(chunk);
74
+ }
75
+ }
76
+ }
77
+ finally {
78
+ reader.releaseLock();
79
+ }
80
+ }
81
+ /**
82
+ * emit chunk 并累积
83
+ */
84
+ emitChunk(chunk) {
85
+ this.audioChunks.push(chunk);
86
+ this.emit('chunk', chunk);
87
+ }
88
+ /**
89
+ * 重置状态
90
+ * 清空累积的音频数据
91
+ */
92
+ reset() {
93
+ this.audioChunks = [];
94
+ }
95
+ /**
96
+ * 获取累积的音频数据
97
+ * 返回所有已接收的 chunk
98
+ */
99
+ getAudioChunks() {
100
+ return [...this.audioChunks];
101
+ }
102
+ }
103
+ //# sourceMappingURL=streaming-synthesizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-synthesizer.js","sourceRoot":"","sources":["../../src/core/streaming-synthesizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAe,QAAQ,EAA0D,MAAM,SAAS,CAAA;AAQvG,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IAGhC;IAFZ,WAAW,GAAa,EAAE,CAAA;IAElC,YAAoB,OAAoC;QACtD,KAAK,EAAE,CAAA;QADW,YAAO,GAAP,OAAO,CAA6B;IAExD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE;gBACrD,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;gBACzB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;gBACzB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBAC3B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;aAC1B,CAAC,CAAA;YAEF,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAA;YAErC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,KAAK,YAAY,QAAQ;gBACxC,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,IAAI,QAAQ,CACV,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,EAC3D,SAAyB,EACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAC1B,KAAK,CACN,CAAA;YACL,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,MAAmB;QAClD,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,SAAS,YAAY,cAAc,EAAE,CAAC;YAClE,sBAAsB;YACtB,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QACpD,CAAC;aAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,eAAe;YACf,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,qBAAqB,CAAC,MAAsB;QACxD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;QAEjC,IAAI,CAAC;YACH,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;gBAE3C,IAAI,IAAI,EAAE,CAAC;oBACT,MAAK;gBACP,CAAC;gBAED,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;oBACjE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,WAAW,EAAE,CAAA;QACtB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,SAAS,CAAC,KAAa;QAC7B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC3B,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,EAAE,CAAA;IACvB,CAAC;IAED;;;OAGG;IACH,cAAc;QACZ,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAA;IAC9B,CAAC;CACF"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * TTS Core Types
3
+ * 核心类型定义
4
+ */
5
+ export declare enum TTSErrorCode {
6
+ NETWORK = "NETWORK",
7
+ AUTH = "AUTH",
8
+ QUOTA = "QUOTA",
9
+ INVALID_VOICE = "INVALID_VOICE",
10
+ INVALID_PARAMS = "INVALID_PARAMS",
11
+ PLAYER_ERROR = "PLAYER_ERROR",
12
+ UNKNOWN = "UNKNOWN"
13
+ }
14
+ export declare class TTSError extends Error {
15
+ constructor(message: string, code: TTSErrorCode, provider: string, details?: unknown);
16
+ code: TTSErrorCode;
17
+ provider: string;
18
+ details?: unknown;
19
+ }
20
+ export interface Voice {
21
+ id: string;
22
+ name: string;
23
+ language?: string;
24
+ gender?: 'male' | 'female' | 'neutral';
25
+ previewUrl?: string;
26
+ }
27
+ export interface TTSCapabilities {
28
+ speak: true;
29
+ voiceClone?: boolean;
30
+ stream?: boolean;
31
+ voiceList?: boolean;
32
+ sync?: boolean;
33
+ async?: boolean;
34
+ }
35
+ export type SynthesisModel = 'sync' | 'async' | 'stream';
36
+ export interface SpeakOptions {
37
+ voice?: string;
38
+ model?: SynthesisModel;
39
+ speed?: number;
40
+ volume?: number;
41
+ pitch?: number;
42
+ sourceVoice?: string;
43
+ }
44
+ export interface AudioResult {
45
+ audioData: Buffer | ReadableStream;
46
+ sampleRate?: number;
47
+ channels?: number;
48
+ duration?: number;
49
+ format: string;
50
+ isStream: boolean;
51
+ }
52
+ export type TTSEvent = 'start' | 'end' | 'error' | 'progress' | 'pause' | 'resume' | 'stop';
53
+ export interface SpeakerEvents {
54
+ on(event: 'start', handler: (text: string) => void): void;
55
+ on(event: 'end', handler: (text: string) => void): void;
56
+ on(event: 'error', handler: (error: TTSError) => void): void;
57
+ on(event: 'progress', handler: (progress: {
58
+ current: number;
59
+ total: number;
60
+ }) => void): void;
61
+ on(event: 'pause', handler: () => void): void;
62
+ on(event: 'resume', handler: () => void): void;
63
+ on(event: 'stop', handler: () => void): void;
64
+ off(event: TTSEvent, handler: Function): void;
65
+ }
66
+ export interface TTSProvider {
67
+ name: string;
68
+ capabilities: TTSCapabilities;
69
+ initialize(): Promise<void>;
70
+ destroy(): Promise<void>;
71
+ speak(text: string, options?: SpeakOptions): Promise<AudioResult>;
72
+ pause(): Promise<void>;
73
+ resume(): Promise<void>;
74
+ stop(): Promise<void>;
75
+ listVoices(): Promise<Voice[]>;
76
+ getCapabilities(): TTSCapabilities;
77
+ }
78
+ export interface GlobalConfig {
79
+ defaultProvider: string;
80
+ defaultModel?: SynthesisModel;
81
+ defaultVoice?: string;
82
+ }
83
+ export interface ProviderConfig {
84
+ enabled?: boolean;
85
+ apiKey?: string;
86
+ [key: string]: unknown;
87
+ }
88
+ export interface OcosayConfig {
89
+ enabled?: boolean;
90
+ autoPlay?: boolean;
91
+ autoRead?: boolean;
92
+ streamMode?: boolean;
93
+ streamBufferSize?: number;
94
+ streamBufferTimeout?: number;
95
+ provider?: string;
96
+ ttsModel?: string;
97
+ baseURL?: string;
98
+ speed?: number;
99
+ volume?: number;
100
+ pitch?: number;
101
+ }
102
+ export declare enum StreamState {
103
+ IDLE = "idle",
104
+ BUFFERING = "buffering",
105
+ STREAMING = "streaming",
106
+ ENDED = "ended"
107
+ }
108
+ export interface OcosayStreamConfig {
109
+ enabled: boolean;
110
+ autoPlay: boolean;
111
+ autoRead: boolean;
112
+ streamMode: boolean;
113
+ streamBufferSize: number;
114
+ streamBufferTimeout: number;
115
+ provider: string;
116
+ voiceId?: string;
117
+ ttsModel?: string;
118
+ baseURL?: string;
119
+ speed?: number;
120
+ volume?: number;
121
+ pitch?: number;
122
+ apiKey?: string;
123
+ }
124
+ export interface StreamReaderEvents {
125
+ onTextReady: (text: string) => void;
126
+ onStreamStart: () => void;
127
+ onStreamEnd: () => void;
128
+ onStreamError: (error: TTSError) => void;
129
+ }
130
+ export interface StreamingSynthesizerOptions {
131
+ provider: TTSProvider;
132
+ voice?: string;
133
+ speed?: number;
134
+ volume?: number;
135
+ pitch?: number;
136
+ }
137
+ export interface StreamPlayerOptions {
138
+ format?: 'mp3' | 'wav' | 'flac';
139
+ onProgress?: (bytesReceived: number) => void;
140
+ }
141
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * TTS Core Types
3
+ * 核心类型定义
4
+ */
5
+ export var TTSErrorCode;
6
+ (function (TTSErrorCode) {
7
+ TTSErrorCode["NETWORK"] = "NETWORK";
8
+ TTSErrorCode["AUTH"] = "AUTH";
9
+ TTSErrorCode["QUOTA"] = "QUOTA";
10
+ TTSErrorCode["INVALID_VOICE"] = "INVALID_VOICE";
11
+ TTSErrorCode["INVALID_PARAMS"] = "INVALID_PARAMS";
12
+ TTSErrorCode["PLAYER_ERROR"] = "PLAYER_ERROR";
13
+ TTSErrorCode["UNKNOWN"] = "UNKNOWN";
14
+ })(TTSErrorCode || (TTSErrorCode = {}));
15
+ export class TTSError extends Error {
16
+ constructor(message, code, provider, details) {
17
+ super(message);
18
+ this.name = 'TTSError';
19
+ this.code = code;
20
+ this.provider = provider;
21
+ this.details = details;
22
+ }
23
+ code;
24
+ provider;
25
+ details;
26
+ }
27
+ // ============================================================================
28
+ // 流式朗读相关类型
29
+ // ============================================================================
30
+ export var StreamState;
31
+ (function (StreamState) {
32
+ StreamState["IDLE"] = "idle";
33
+ StreamState["BUFFERING"] = "buffering";
34
+ StreamState["STREAMING"] = "streaming";
35
+ StreamState["ENDED"] = "ended";
36
+ })(StreamState || (StreamState = {}));
37
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAN,IAAY,YAQX;AARD,WAAY,YAAY;IACtB,mCAAmB,CAAA;IACnB,6BAAa,CAAA;IACb,+BAAe,CAAA;IACf,+CAA+B,CAAA;IAC/B,iDAAiC,CAAA;IACjC,6CAA6B,CAAA;IAC7B,mCAAmB,CAAA;AACrB,CAAC,EARW,YAAY,KAAZ,YAAY,QAQvB;AAED,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,YACE,OAAe,EACf,IAAkB,EAClB,QAAgB,EAChB,OAAiB;QAEjB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,UAAU,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,IAAI,CAAc;IAClB,QAAQ,CAAQ;IAChB,OAAO,CAAU;CAClB;AA0GD,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,sCAAuB,CAAA;IACvB,sCAAuB,CAAA;IACvB,8BAAe,CAAA;AACjB,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB"}
@@ -0,0 +1,40 @@
1
+ import { handleToolCall } from './tools/tts';
2
+ import { MiniMaxConfig } from './providers/minimax';
3
+ import { Speaker } from './core/speaker';
4
+ import { StreamReader } from './core/stream-reader';
5
+ import { StreamingSynthesizer } from './core/streaming-synthesizer';
6
+ import { StreamPlayer } from './core/stream-player';
7
+ export declare const pluginInfo: {
8
+ name: string;
9
+ version: string;
10
+ description: string;
11
+ author: string;
12
+ license: string;
13
+ };
14
+ export interface InitializeOptions {
15
+ defaultProvider?: string;
16
+ defaultModel?: 'sync' | 'async' | 'stream';
17
+ defaultVoice?: string;
18
+ providers?: {
19
+ minimax?: MiniMaxConfig;
20
+ };
21
+ autoRead?: boolean;
22
+ streamBufferSize?: number;
23
+ streamBufferTimeout?: number;
24
+ }
25
+ export declare function initialize(config?: InitializeOptions): Promise<void>;
26
+ export declare function getSpeaker(): Speaker;
27
+ export declare function isStreamEnabled(): boolean;
28
+ export declare function isAutoReadEnabled(): boolean;
29
+ export declare function getStreamStatus(): {
30
+ isActive: boolean;
31
+ bytesWritten: number;
32
+ state: string;
33
+ };
34
+ export declare function getStreamReader(): StreamReader | undefined;
35
+ export declare function getStreamingSynthesizer(): StreamingSynthesizer | undefined;
36
+ export declare function getStreamPlayer(): StreamPlayer | undefined;
37
+ export declare function destroy(): Promise<void>;
38
+ export { handleToolCall };
39
+ export declare const toolNames: string[];
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE5C,OAAO,EAAmB,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACpE,OAAO,EAAE,OAAO,EAAkB,MAAM,gBAAgB,CAAA;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,eAAO,MAAM,UAAU;;;;;;CAMtB,CAAA;AASD,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,aAAa,CAAA;KACxB,CAAA;IACD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,wBAAsB,UAAU,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB1E;AAsFD,wBAAgB,UAAU,IAAI,OAAO,CASpC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAgB,eAAe,IAAI;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAS5F;AAED,wBAAgB,eAAe,IAAI,YAAY,GAAG,SAAS,CAE1D;AAED,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,SAAS,CAE1E;AAED,wBAAgB,eAAe,IAAI,YAAY,GAAG,SAAS,CAE1D;AAED,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CA6B7C;AAED,OAAO,EAAE,cAAc,EAAE,CAAA;AACzB,eAAO,MAAM,SAAS,UAWrB,CAAA"}