@mingxy/ocosay 1.1.0 → 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.
- package/README.md +43 -653
- package/dist/config.js +2 -1
- package/dist/core/logger.d.ts +46 -0
- package/dist/core/logger.js +126 -0
- package/dist/core/notification.d.ts +27 -0
- package/dist/core/notification.js +86 -0
- package/dist/core/speaker.js +5 -35
- package/dist/core/stream-reader.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/package.json +7 -4
- package/dist/plugin.js +220 -197
- package/dist/tools/tts.js +2 -1
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.js +42 -6
- package/package.json +4 -2
- package/scripts/compile-native.cjs +48 -0
- package/scripts/install-portaudio.cjs +117 -0
- package/.idea/UniappTool.xml +0 -10
- package/.idea/inspectionProfiles/profiles_settings.xml +0 -5
- package/.idea/modules.xml +0 -8
- package/.idea/ocosay.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.sisyphus/boulder.json +0 -23
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/backends/afplay-backend.d.ts.map +0 -1
- package/dist/core/backends/afplay-backend.js.map +0 -1
- package/dist/core/backends/aplay-backend.d.ts.map +0 -1
- package/dist/core/backends/aplay-backend.js.map +0 -1
- package/dist/core/backends/base.d.ts.map +0 -1
- package/dist/core/backends/base.js.map +0 -1
- package/dist/core/backends/howler-backend.d.ts.map +0 -1
- package/dist/core/backends/howler-backend.js.map +0 -1
- package/dist/core/backends/index.d.ts.map +0 -1
- package/dist/core/backends/index.js.map +0 -1
- package/dist/core/backends/naudiodon-backend.d.ts.map +0 -1
- package/dist/core/backends/naudiodon-backend.js.map +0 -1
- package/dist/core/backends/powershell-backend.d.ts.map +0 -1
- package/dist/core/backends/powershell-backend.js.map +0 -1
- package/dist/core/player.d.ts.map +0 -1
- package/dist/core/player.js.map +0 -1
- package/dist/core/speaker.d.ts.map +0 -1
- package/dist/core/speaker.js.map +0 -1
- package/dist/core/stream-player.d.ts.map +0 -1
- package/dist/core/stream-player.js.map +0 -1
- package/dist/core/stream-reader.d.ts.map +0 -1
- package/dist/core/stream-reader.js.map +0 -1
- package/dist/core/streaming-synthesizer.d.ts.map +0 -1
- package/dist/core/streaming-synthesizer.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/plugin.d.ts.map +0 -1
- package/dist/plugin.js.map +0 -7
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/minimax.d.ts.map +0 -1
- package/dist/providers/minimax.js.map +0 -1
- package/dist/services/notification-service.d.ts.map +0 -1
- package/dist/services/notification-service.js.map +0 -1
- package/dist/services/speaker-service.d.ts.map +0 -1
- package/dist/services/speaker-service.js.map +0 -1
- package/dist/services/streaming-service.d.ts.map +0 -1
- package/dist/services/streaming-service.js.map +0 -1
- package/dist/tools/tts.d.ts.map +0 -1
- package/dist/tools/tts.js.map +0 -1
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/tsconfig.jest.json +0 -21
package/dist/config.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as os from 'os';
|
|
4
|
-
import {
|
|
4
|
+
import { createModuleLogger } from './utils/logger';
|
|
5
|
+
const logger = createModuleLogger('Config');
|
|
5
6
|
// 默认配置
|
|
6
7
|
const DEFAULT_CONFIG = {
|
|
7
8
|
enabled: true,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一日志模块
|
|
3
|
+
* 支持日志级别、控制台输出、文件输出
|
|
4
|
+
*/
|
|
5
|
+
export declare enum LogLevel {
|
|
6
|
+
DEBUG = "DEBUG",
|
|
7
|
+
INFO = "INFO",
|
|
8
|
+
WARN = "WARN",
|
|
9
|
+
ERROR = "ERROR"
|
|
10
|
+
}
|
|
11
|
+
export interface LoggerConfig {
|
|
12
|
+
/** 最小日志级别,低于此级别的日志不输出 */
|
|
13
|
+
minLevel?: LogLevel;
|
|
14
|
+
/** 是否输出到控制台 */
|
|
15
|
+
console?: boolean;
|
|
16
|
+
/** 日志文件路径,为空则不输出到文件 */
|
|
17
|
+
filePath?: string;
|
|
18
|
+
/** 日志文件最大大小(bytes),超过则轮转 */
|
|
19
|
+
maxFileSize?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class Logger {
|
|
22
|
+
private minLevel;
|
|
23
|
+
private consoleEnabled;
|
|
24
|
+
private filePath?;
|
|
25
|
+
private maxFileSize;
|
|
26
|
+
private writeStream?;
|
|
27
|
+
constructor(config?: LoggerConfig);
|
|
28
|
+
private initFileStream;
|
|
29
|
+
private shouldLog;
|
|
30
|
+
private formatTimestamp;
|
|
31
|
+
private formatMessage;
|
|
32
|
+
private stringify;
|
|
33
|
+
private log;
|
|
34
|
+
private writeToConsole;
|
|
35
|
+
private writeToFile;
|
|
36
|
+
debug(message: string, ...args: unknown[]): void;
|
|
37
|
+
info(message: string, ...args: unknown[]): void;
|
|
38
|
+
warn(message: string, ...args: unknown[]): void;
|
|
39
|
+
error(message: string, ...args: unknown[]): void;
|
|
40
|
+
/**
|
|
41
|
+
* 关闭日志系统,释放文件流
|
|
42
|
+
*/
|
|
43
|
+
close(): void;
|
|
44
|
+
}
|
|
45
|
+
export declare const logger: Logger;
|
|
46
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一日志模块
|
|
3
|
+
* 支持日志级别、控制台输出、文件输出
|
|
4
|
+
*/
|
|
5
|
+
export var LogLevel;
|
|
6
|
+
(function (LogLevel) {
|
|
7
|
+
LogLevel["DEBUG"] = "DEBUG";
|
|
8
|
+
LogLevel["INFO"] = "INFO";
|
|
9
|
+
LogLevel["WARN"] = "WARN";
|
|
10
|
+
LogLevel["ERROR"] = "ERROR";
|
|
11
|
+
})(LogLevel || (LogLevel = {}));
|
|
12
|
+
const LEVEL_PRIORITY = {
|
|
13
|
+
[LogLevel.DEBUG]: 0,
|
|
14
|
+
[LogLevel.INFO]: 1,
|
|
15
|
+
[LogLevel.WARN]: 2,
|
|
16
|
+
[LogLevel.ERROR]: 3,
|
|
17
|
+
};
|
|
18
|
+
export class Logger {
|
|
19
|
+
minLevel;
|
|
20
|
+
consoleEnabled;
|
|
21
|
+
filePath;
|
|
22
|
+
maxFileSize;
|
|
23
|
+
writeStream;
|
|
24
|
+
constructor(config = {}) {
|
|
25
|
+
this.minLevel = config.minLevel ?? LogLevel.INFO;
|
|
26
|
+
this.consoleEnabled = config.console ?? true;
|
|
27
|
+
this.filePath = config.filePath;
|
|
28
|
+
this.maxFileSize = config.maxFileSize ?? 10 * 1024 * 1024;
|
|
29
|
+
if (this.filePath) {
|
|
30
|
+
this.initFileStream();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
initFileStream() {
|
|
34
|
+
if (!this.filePath)
|
|
35
|
+
return;
|
|
36
|
+
import('fs').then((fs) => {
|
|
37
|
+
this.writeStream = fs.createWriteStream(this.filePath, { flags: 'a' });
|
|
38
|
+
}).catch(() => { });
|
|
39
|
+
}
|
|
40
|
+
shouldLog(level) {
|
|
41
|
+
return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.minLevel];
|
|
42
|
+
}
|
|
43
|
+
formatTimestamp(date) {
|
|
44
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
45
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
46
|
+
}
|
|
47
|
+
formatMessage(level, message, args) {
|
|
48
|
+
const timestamp = this.formatTimestamp(new Date());
|
|
49
|
+
const formattedArgs = args?.length ? ' ' + args.map((a) => this.stringify(a)).join(' ') : '';
|
|
50
|
+
return `[${timestamp}] [${level}] ${message}${formattedArgs}`;
|
|
51
|
+
}
|
|
52
|
+
stringify(value) {
|
|
53
|
+
if (typeof value === 'string')
|
|
54
|
+
return value;
|
|
55
|
+
if (value instanceof Error)
|
|
56
|
+
return `${value.message}\n${value.stack}`;
|
|
57
|
+
try {
|
|
58
|
+
return JSON.stringify(value);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return String(value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
log(entry) {
|
|
65
|
+
if (!this.shouldLog(entry.level))
|
|
66
|
+
return;
|
|
67
|
+
const formatted = this.formatMessage(entry.level, entry.message, entry.args);
|
|
68
|
+
if (this.consoleEnabled) {
|
|
69
|
+
this.writeToConsole(entry.level, formatted);
|
|
70
|
+
}
|
|
71
|
+
if (this.writeStream) {
|
|
72
|
+
this.writeToFile(formatted + '\n');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
writeToConsole(level, message) {
|
|
76
|
+
switch (level) {
|
|
77
|
+
case LogLevel.DEBUG:
|
|
78
|
+
console.debug(message);
|
|
79
|
+
break;
|
|
80
|
+
case LogLevel.INFO:
|
|
81
|
+
console.info(message);
|
|
82
|
+
break;
|
|
83
|
+
case LogLevel.WARN:
|
|
84
|
+
console.warn(message);
|
|
85
|
+
break;
|
|
86
|
+
case LogLevel.ERROR:
|
|
87
|
+
console.error(message);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
writeToFile(message) {
|
|
92
|
+
if (this.writeStream) {
|
|
93
|
+
this.writeStream.write(message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
debug(message, ...args) {
|
|
97
|
+
this.log({ timestamp: new Date(), level: LogLevel.DEBUG, message, args });
|
|
98
|
+
}
|
|
99
|
+
info(message, ...args) {
|
|
100
|
+
this.log({ timestamp: new Date(), level: LogLevel.INFO, message, args });
|
|
101
|
+
}
|
|
102
|
+
warn(message, ...args) {
|
|
103
|
+
this.log({ timestamp: new Date(), level: LogLevel.WARN, message, args });
|
|
104
|
+
}
|
|
105
|
+
error(message, ...args) {
|
|
106
|
+
this.log({ timestamp: new Date(), level: LogLevel.ERROR, message, args });
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 关闭日志系统,释放文件流
|
|
110
|
+
*/
|
|
111
|
+
close() {
|
|
112
|
+
if (this.writeStream) {
|
|
113
|
+
this.writeStream.end();
|
|
114
|
+
this.writeStream = undefined;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
import { homedir } from 'os';
|
|
119
|
+
import { join } from 'path';
|
|
120
|
+
const logPath = join(homedir(), '.ocosay', 'ocosay.log');
|
|
121
|
+
export const logger = new Logger({
|
|
122
|
+
minLevel: LogLevel.DEBUG,
|
|
123
|
+
console: true,
|
|
124
|
+
filePath: logPath,
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type ToastVariant = 'success' | 'error' | 'info' | 'warning';
|
|
2
|
+
export interface ToastOptions {
|
|
3
|
+
title: string;
|
|
4
|
+
message: string;
|
|
5
|
+
variant?: ToastVariant;
|
|
6
|
+
duration?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* NotificationService - 统一 Toast 通知管理
|
|
10
|
+
* 参照 DCP 实现,不做防御性检查,直接调用并用 try-catch 处理
|
|
11
|
+
*/
|
|
12
|
+
declare class NotificationService {
|
|
13
|
+
private tui;
|
|
14
|
+
private pendingToasts;
|
|
15
|
+
private retryTimer?;
|
|
16
|
+
setTui(tui: any): void;
|
|
17
|
+
showToast(options: ToastOptions): boolean;
|
|
18
|
+
private scheduleRetry;
|
|
19
|
+
private flushPending;
|
|
20
|
+
success(title: string, message: string, duration?: number): boolean;
|
|
21
|
+
error(title: string, message: string, duration?: number): boolean;
|
|
22
|
+
info(title: string, message: string, duration?: number): boolean;
|
|
23
|
+
warning(title: string, message: string, duration?: number): boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare const notificationService: NotificationService;
|
|
26
|
+
export default notificationService;
|
|
27
|
+
//# sourceMappingURL=notification.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// src/core/notification.ts
|
|
2
|
+
import { createModuleLogger } from '../utils/logger';
|
|
3
|
+
const logger = createModuleLogger('NotificationService');
|
|
4
|
+
/**
|
|
5
|
+
* NotificationService - 统一 Toast 通知管理
|
|
6
|
+
* 参照 DCP 实现,不做防御性检查,直接调用并用 try-catch 处理
|
|
7
|
+
*/
|
|
8
|
+
class NotificationService {
|
|
9
|
+
tui = null;
|
|
10
|
+
pendingToasts = [];
|
|
11
|
+
retryTimer;
|
|
12
|
+
setTui(tui) {
|
|
13
|
+
this.tui = tui;
|
|
14
|
+
logger.debug('tui reference set');
|
|
15
|
+
this.flushPending();
|
|
16
|
+
}
|
|
17
|
+
showToast(options) {
|
|
18
|
+
const { title, message, variant = 'info', duration = 5000 } = options;
|
|
19
|
+
if (!this.tui) {
|
|
20
|
+
logger.debug({ title }, 'tui not ready, queueing toast');
|
|
21
|
+
this.pendingToasts.push(options);
|
|
22
|
+
this.scheduleRetry();
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
// 参照 DCP 格式:{ body: { title, message, variant, duration } }
|
|
27
|
+
this.tui.showToast({
|
|
28
|
+
body: {
|
|
29
|
+
title,
|
|
30
|
+
message,
|
|
31
|
+
variant,
|
|
32
|
+
duration,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
logger.debug({ title, variant }, 'toast shown');
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
// 参照 DCP:捕获异常但不抛出
|
|
40
|
+
logger.warn({ err, title }, 'toast call failed, queueing for retry');
|
|
41
|
+
this.pendingToasts.push(options);
|
|
42
|
+
this.scheduleRetry();
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
scheduleRetry() {
|
|
47
|
+
if (this.retryTimer)
|
|
48
|
+
return;
|
|
49
|
+
this.retryTimer = setTimeout(() => {
|
|
50
|
+
this.retryTimer = undefined;
|
|
51
|
+
this.flushPending();
|
|
52
|
+
}, 2000);
|
|
53
|
+
}
|
|
54
|
+
flushPending() {
|
|
55
|
+
if (this.pendingToasts.length === 0 || !this.tui)
|
|
56
|
+
return;
|
|
57
|
+
logger.info({ count: this.pendingToasts.length }, 'flushing pending toasts');
|
|
58
|
+
const pending = [...this.pendingToasts];
|
|
59
|
+
this.pendingToasts = []; // 乐观清空
|
|
60
|
+
for (const toast of pending) {
|
|
61
|
+
try {
|
|
62
|
+
this.showToast(toast);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
// 保护性重新加入队列
|
|
66
|
+
this.pendingToasts.push(toast);
|
|
67
|
+
logger.warn({ err }, 'showToast threw unexpected error, re-queued');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
success(title, message, duration) {
|
|
72
|
+
return this.showToast({ title, message, variant: 'success', duration });
|
|
73
|
+
}
|
|
74
|
+
error(title, message, duration) {
|
|
75
|
+
return this.showToast({ title, message, variant: 'error', duration });
|
|
76
|
+
}
|
|
77
|
+
info(title, message, duration) {
|
|
78
|
+
return this.showToast({ title, message, variant: 'info', duration });
|
|
79
|
+
}
|
|
80
|
+
warning(title, message, duration) {
|
|
81
|
+
return this.showToast({ title, message, variant: 'warning', duration });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export const notificationService = new NotificationService();
|
|
85
|
+
export default notificationService;
|
|
86
|
+
//# sourceMappingURL=notification.js.map
|
package/dist/core/speaker.js
CHANGED
|
@@ -6,30 +6,9 @@ import { EventEmitter } from 'events';
|
|
|
6
6
|
import { TTSError, TTSErrorCode } from './types';
|
|
7
7
|
import { getProvider, listProviders, hasProvider } from '../providers/base';
|
|
8
8
|
import { AudioPlayer } from './player';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* 适配用户期望的格式: toast({ title, body, type })
|
|
13
|
-
* 注意:必须保持方法调用形式 (tui.showToast()) 而不是提取方法后调用 (showToastFn()),
|
|
14
|
-
* 否则 this 上下文丢失导致 OpenCode 内部 this._client 为 undefined
|
|
15
|
-
*/
|
|
16
|
-
function toast(options) {
|
|
17
|
-
const tui = global.__opencode_tui__;
|
|
18
|
-
if (tui?.showToast) {
|
|
19
|
-
try {
|
|
20
|
-
// SDK期望直接传参: { title, message, variant, duration },不是 { body: {...} }
|
|
21
|
-
tui.showToast({
|
|
22
|
-
title: options.title,
|
|
23
|
-
message: options.body,
|
|
24
|
-
variant: options.type,
|
|
25
|
-
duration: 3000
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
logger.warn({ err }, 'toast call failed');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
9
|
+
import { createModuleLogger } from '../utils/logger';
|
|
10
|
+
import { notificationService } from './notification';
|
|
11
|
+
const logger = createModuleLogger('Speaker');
|
|
33
12
|
/**
|
|
34
13
|
* Speaker - TTS 统一调用入口类
|
|
35
14
|
* 封装 Provider 和 Player,提供简洁的 speak/pause/resume/stop API
|
|
@@ -50,12 +29,7 @@ export class Speaker extends EventEmitter {
|
|
|
50
29
|
onEnd: () => {
|
|
51
30
|
this.isSpeaking = false;
|
|
52
31
|
this.emit('end', this.currentText);
|
|
53
|
-
|
|
54
|
-
toast({
|
|
55
|
-
title: 'TTS playback success',
|
|
56
|
-
body: 'Audio generated and playing',
|
|
57
|
-
type: 'info'
|
|
58
|
-
});
|
|
32
|
+
notificationService.info('TTS playback success', 'Audio generated and playing');
|
|
59
33
|
},
|
|
60
34
|
onError: (error) => this.emit('error', error),
|
|
61
35
|
onPause: () => {
|
|
@@ -117,11 +91,7 @@ export class Speaker extends EventEmitter {
|
|
|
117
91
|
logger.error({ error }, 'speak failed');
|
|
118
92
|
// 显示播放失败 Toast
|
|
119
93
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
120
|
-
|
|
121
|
-
title: 'TTS playback error',
|
|
122
|
-
body: errorMessage,
|
|
123
|
-
type: 'error'
|
|
124
|
-
});
|
|
94
|
+
notificationService.error('TTS playback error', errorMessage);
|
|
125
95
|
if (error instanceof TTSError) {
|
|
126
96
|
this.emit('error', error);
|
|
127
97
|
throw error;
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { EventEmitter } from 'events';
|
|
10
10
|
import { StreamState } from './types';
|
|
11
|
-
import {
|
|
11
|
+
import { createModuleLogger } from '../utils/logger';
|
|
12
|
+
const logger = createModuleLogger('StreamReader');
|
|
12
13
|
export class StreamReader extends EventEmitter {
|
|
13
14
|
bufferSize;
|
|
14
15
|
bufferTimeout;
|
package/dist/index.d.ts
CHANGED
|
@@ -36,5 +36,6 @@ export declare function getStreamingSynthesizer(): StreamingSynthesizer | undefi
|
|
|
36
36
|
export declare function getStreamPlayer(): StreamPlayer | undefined;
|
|
37
37
|
export declare function destroy(): Promise<void>;
|
|
38
38
|
export { handleToolCall };
|
|
39
|
+
export { notificationService } from './core/notification.js';
|
|
39
40
|
export declare const toolNames: string[];
|
|
40
41
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mingxy/ocosay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "OpenCode TTS 播放插件 - 支持豆包模式边接收边朗读",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin.js",
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"build:plugin": "esbuild src/plugin.ts --bundle --platform=node --format=esm --outdir=dist --sourcemap --external:@opencode-ai/plugin --external:axios --external:ws --external:zod",
|
|
30
30
|
"watch": "tsc --watch",
|
|
31
31
|
"test": "jest",
|
|
32
|
-
"lint": "eslint src --ext .ts"
|
|
32
|
+
"lint": "eslint src --ext .ts",
|
|
33
|
+
"install-deps": "node scripts/install-native-deps.js",
|
|
34
|
+
"postinstall": "node scripts/verify-audio.js"
|
|
33
35
|
},
|
|
34
36
|
"keywords": [
|
|
35
37
|
"tts",
|
|
@@ -37,7 +39,7 @@
|
|
|
37
39
|
"opencode",
|
|
38
40
|
"plugin"
|
|
39
41
|
],
|
|
40
|
-
"author": "",
|
|
42
|
+
"author": "mingxy",
|
|
41
43
|
"license": "MIT",
|
|
42
44
|
"dependencies": {
|
|
43
45
|
"@opencode-ai/plugin": "^1.3.15",
|
|
@@ -48,7 +50,8 @@
|
|
|
48
50
|
"zod": "^4.3.6"
|
|
49
51
|
},
|
|
50
52
|
"optionalDependencies": {
|
|
51
|
-
"
|
|
53
|
+
"bindings": "^1.5.0",
|
|
54
|
+
"naudiodon": "^1.0.0"
|
|
52
55
|
},
|
|
53
56
|
"devDependencies": {
|
|
54
57
|
"@types/howler": "^2.2.12",
|