@mingxy/ocosay 1.0.0 → 1.0.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 🎙️ 让 AI 开口说话 — 支持豆包模式边接收边朗读的 TTS 插件
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/@mengxy/ocosay.svg)](https://www.npmjs.com/package/@mengxy/ocosay)
5
+ [![npm version](https://img.shields.io/npm/v/@mingxy/ocosay.svg)](https://www.npmjs.com/package/@mingxy/ocosay)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
 
8
8
  ## Why This Exists
@@ -37,29 +37,65 @@
37
37
  ### 方式一:ocx 安装(推荐)
38
38
 
39
39
  ```bash
40
- ocx install @mengxy/ocosay
40
+ ocx install @mingxy/ocosay
41
41
  ```
42
42
 
43
43
  ### 方式二:手动配置
44
44
 
45
45
  ```bash
46
- npm install @mengxy/ocosay
46
+ npm install @mingxy/ocosay
47
47
  ```
48
48
 
49
- 在 OpenCode 配置文件中添加:
49
+ 在 OpenCode 配置文件中添加插件:
50
50
 
51
- ```json
51
+ ```jsonc
52
52
  {
53
- "plugins": [
54
- "@mengxy/ocosay"
55
- ],
56
- "minimax": {
57
- "apiKey": "your-api-key",
58
- "voiceId": "male-qn-qingse"
53
+ "plugin": [
54
+ "@mingxy/ocosay"
55
+ ]
56
+ }
57
+ ```
58
+
59
+ > **首次安装**:重启 OpenCode 后,插件会自动在 `~/.config/opencode/ocosay.jsonc` 生成默认配置文件。
60
+ > 请编辑该文件,填写您的 `apiKey` 和 `baseURL`。
61
+
62
+ ## 快速开始
63
+
64
+ ### 1. 添加插件
65
+
66
+ 在 `~/.config/opencode/opencode.jsonc` 中添加:
67
+
68
+ ```jsonc
69
+ {
70
+ "plugin": [
71
+ "@mingxy/ocosay"
72
+ ]
73
+ }
74
+ ```
75
+
76
+ ### 2. 重启 OpenCode
77
+
78
+ 插件会自动下载并初始化。
79
+
80
+ ### 3. 填写配置
81
+
82
+ 首次启动后,插件会自动生成 `~/.config/opencode/ocosay.jsonc` 配置文件。
83
+
84
+ 编辑该文件,填写必填项:
85
+
86
+ ```jsonc
87
+ {
88
+ "providers": {
89
+ "minimax": {
90
+ "apiKey": "您的API_KEY", // ⚠️ 必填
91
+ "baseURL": "https://api.minimaxi.com" // ⚠️ 必填
92
+ }
59
93
  }
60
94
  }
61
95
  ```
62
96
 
97
+ ### 4. 重启 OpenCode 使配置生效
98
+
63
99
  ## 快速开始
64
100
 
65
101
  ### 初始化
package/dist/config.d.ts CHANGED
@@ -1,26 +1,6 @@
1
- /**
2
- * Configuration Management
3
- * 配置管理模块
4
- */
5
- import { GlobalConfig, ProviderConfig, OcosayConfig } from './core/types';
6
- declare const DEFAULT_CONFIG: OcosayConfig;
7
- declare class ConfigManager {
8
- private config;
9
- private configPath;
10
- private providers;
11
- constructor(configPath?: string);
12
- private loadConfig;
13
- saveConfig(): void;
14
- getGlobal(): OcosayConfig;
15
- getProviderConfig(providerName: string): ProviderConfig | undefined;
16
- setProviderConfig(providerName: string, config: ProviderConfig): void;
17
- getDefaultProvider(): string;
18
- setDefaultProvider(provider: string): void;
19
- validateApiKey(provider: string, apiKey: string): void;
20
- validateStreamConfig(): void;
21
- }
22
- export declare const configManager: ConfigManager;
23
- export { ConfigManager, DEFAULT_CONFIG };
24
- export type { OcosayConfig, GlobalConfig, ProviderConfig };
25
- export default configManager;
1
+ import type { OcosayConfig } from './types/config';
2
+ export declare function generateDefaultConfig(): OcosayConfig;
3
+ export declare function stripComments(jsonc: string): string;
4
+ export declare function mergeWithDefaults(loaded: Partial<OcosayConfig>, defaults: Omit<OcosayConfig, 'providers'>): Omit<OcosayConfig, 'providers'>;
5
+ export declare function loadOrCreateConfig(): OcosayConfig;
26
6
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAKzE,QAAA,MAAM,cAAc,EAAE,YAarB,CAAA;AAED,cAAM,aAAa;IACjB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAqC;gBAE1C,UAAU,CAAC,EAAE,MAAM;IAO/B,OAAO,CAAC,UAAU;IAelB,UAAU,IAAI,IAAI;IAalB,SAAS,IAAI,YAAY;IAIzB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAInE,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI;IAKrE,kBAAkB,IAAI,MAAM;IAI5B,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK1C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAUtD,oBAAoB,IAAI,IAAI;CAgB7B;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAA;AAEhD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,CAAA;AACxC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,CAAA;AAC1D,eAAe,aAAa,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAKlD,wBAAgB,qBAAqB,IAAI,YAAY,CAcpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAmDnD;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,EAC7B,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,GACxC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAYjC;AAED,wBAAgB,kBAAkB,IAAI,YAAY,CAsDjD"}
package/dist/config.js CHANGED
@@ -1,95 +1,132 @@
1
- /**
2
- * Configuration Management
3
- * 配置管理模块
4
- */
5
- import { TTSError, TTSErrorCode } from './core/types';
6
- import fs from 'fs';
7
- import path from 'path';
8
- const DEFAULT_CONFIG = {
9
- enabled: true,
10
- autoPlay: false,
11
- autoRead: false, // 豆包模式开关
12
- streamMode: true, // 流式朗读模式
13
- streamBufferSize: 30, // 缓冲字符数
14
- streamBufferTimeout: 2000, // 缓冲区超时(ms)
15
- provider: 'minimax',
16
- ttsModel: 'speech-02-turbo',
17
- baseURL: 'https://api.minimax.io',
18
- speed: 1.0,
19
- volume: 80,
20
- pitch: 1.0
21
- };
22
- class ConfigManager {
23
- config;
24
- configPath;
25
- providers = {};
26
- constructor(configPath) {
27
- this.configPath = configPath || './config.json';
28
- const loaded = this.loadConfig();
29
- this.config = loaded;
30
- this.providers = loaded.providers || {};
31
- }
32
- loadConfig() {
33
- try {
34
- if (fs.existsSync(this.configPath)) {
35
- const content = fs.readFileSync(this.configPath, 'utf-8');
36
- const parsed = JSON.parse(content);
37
- this.providers = parsed.providers || {};
38
- const { providers, ...config } = parsed;
39
- return { ...DEFAULT_CONFIG, ...config };
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { DEFAULT_CONFIG } from './types/config';
5
+ const CONFIG_PATH = path.join(os.homedir(), '.config', 'opencode', 'ocosay.jsonc');
6
+ export function generateDefaultConfig() {
7
+ return {
8
+ ...DEFAULT_CONFIG,
9
+ providers: {
10
+ minimax: {
11
+ apiKey: '',
12
+ baseURL: '',
13
+ voiceId: '',
14
+ model: 'stream',
15
+ ttsModel: 'speech-2.8-hd',
16
+ audioFormat: 'mp3'
40
17
  }
41
18
  }
42
- catch (error) {
43
- console.warn('Failed to load config, using defaults');
19
+ };
20
+ }
21
+ export function stripComments(jsonc) {
22
+ let result = '';
23
+ let inString = false;
24
+ let stringChar = '';
25
+ let i = 0;
26
+ while (i < jsonc.length) {
27
+ const char = jsonc[i];
28
+ if (!inString && (char === '"' || char === "'" || char === '`')) {
29
+ inString = true;
30
+ stringChar = char;
31
+ result += char;
32
+ i++;
33
+ continue;
34
+ }
35
+ if (inString && char === stringChar && jsonc[i - 1] !== '\\') {
36
+ inString = false;
37
+ result += char;
38
+ i++;
39
+ continue;
44
40
  }
45
- return { ...DEFAULT_CONFIG };
46
- }
47
- saveConfig() {
48
- try {
49
- const dir = path.dirname(this.configPath);
50
- if (!fs.existsSync(dir)) {
51
- fs.mkdirSync(dir, { recursive: true });
41
+ if (inString) {
42
+ result += char;
43
+ i++;
44
+ continue;
45
+ }
46
+ if (char === '/' && jsonc[i + 1] === '/') {
47
+ while (i < jsonc.length && jsonc[i] !== '\n') {
48
+ i++;
52
49
  }
53
- const configWithProviders = { ...this.config, providers: this.providers };
54
- fs.writeFileSync(this.configPath, JSON.stringify(configWithProviders, null, 2));
50
+ continue;
55
51
  }
56
- catch (error) {
57
- console.error('Failed to save config:', error);
52
+ if (char === '/' && jsonc[i + 1] === '*') {
53
+ i += 2;
54
+ while (i < jsonc.length - 1 && !(jsonc[i] === '*' && jsonc[i + 1] === '/')) {
55
+ i++;
56
+ }
57
+ i += 2;
58
+ continue;
58
59
  }
60
+ result += char;
61
+ i++;
59
62
  }
60
- getGlobal() {
61
- return this.config;
62
- }
63
- getProviderConfig(providerName) {
64
- return this.providers[providerName];
65
- }
66
- setProviderConfig(providerName, config) {
67
- this.providers[providerName] = { enabled: true, ...config };
68
- this.saveConfig();
69
- }
70
- getDefaultProvider() {
71
- return this.config.provider || 'minimax';
72
- }
73
- setDefaultProvider(provider) {
74
- this.config.provider = provider;
75
- this.saveConfig();
76
- }
77
- validateApiKey(provider, apiKey) {
78
- if (!apiKey) {
79
- throw new TTSError(`API key is required for provider "${provider}"`, TTSErrorCode.AUTH, provider);
63
+ return result;
64
+ }
65
+ export function mergeWithDefaults(loaded, defaults) {
66
+ return {
67
+ enabled: loaded.enabled ?? defaults.enabled,
68
+ autoPlay: loaded.autoPlay ?? defaults.autoPlay,
69
+ autoRead: loaded.autoRead ?? defaults.autoRead,
70
+ streamMode: loaded.streamMode ?? defaults.streamMode,
71
+ streamBufferSize: loaded.streamBufferSize ?? defaults.streamBufferSize,
72
+ streamBufferTimeout: loaded.streamBufferTimeout ?? defaults.streamBufferTimeout,
73
+ speed: loaded.speed ?? defaults.speed,
74
+ volume: loaded.volume ?? defaults.volume,
75
+ pitch: loaded.pitch ?? defaults.pitch
76
+ };
77
+ }
78
+ export function loadOrCreateConfig() {
79
+ const configDir = path.dirname(CONFIG_PATH);
80
+ if (!fs.existsSync(configDir)) {
81
+ try {
82
+ fs.mkdirSync(configDir, { recursive: true });
83
+ }
84
+ catch (err) {
85
+ throw new Error(`[ocosay] 无法创建配置目录 ${configDir}: ${err}`);
80
86
  }
81
87
  }
82
- validateStreamConfig() {
83
- if ((this.config.streamBufferSize ?? 30) < 5) {
84
- throw new TTSError('streamBufferSize must be at least 5', TTSErrorCode.INVALID_PARAMS, 'config');
88
+ if (!fs.existsSync(CONFIG_PATH)) {
89
+ console.info('[ocosay] 配置文件不存在,正在创建默认配置...');
90
+ const defaultConfig = generateDefaultConfig();
91
+ const configContent = JSON.stringify(defaultConfig, null, 2);
92
+ try {
93
+ fs.writeFileSync(CONFIG_PATH, configContent, 'utf-8');
94
+ try {
95
+ fs.chmodSync(CONFIG_PATH, 0o600);
96
+ }
97
+ catch (err) {
98
+ console.warn(`[ocosay] 无法设置配置文件权限: ${err}`);
99
+ }
85
100
  }
86
- if ((this.config.streamBufferTimeout ?? 2000) < 500) {
87
- throw new TTSError('streamBufferTimeout must be at least 500ms', TTSErrorCode.INVALID_PARAMS, 'config');
101
+ catch (err) {
102
+ throw new Error(`[ocosay] 无法写入配置文件 ${CONFIG_PATH}: ${err}`);
88
103
  }
104
+ console.info(`[ocosay] 配置文件已创建: ${CONFIG_PATH}`);
105
+ console.info('[ocosay] 请编辑配置文件填入 API Key 和 Base URL');
106
+ return defaultConfig;
107
+ }
108
+ try {
109
+ const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
110
+ const stripped = stripComments(content);
111
+ const loaded = JSON.parse(stripped);
112
+ const merged = mergeWithDefaults(loaded, DEFAULT_CONFIG);
113
+ return {
114
+ ...merged,
115
+ providers: {
116
+ minimax: {
117
+ apiKey: loaded.providers?.minimax?.apiKey ?? '',
118
+ baseURL: loaded.providers?.minimax?.baseURL ?? '',
119
+ voiceId: loaded.providers?.minimax?.voiceId ?? '',
120
+ model: loaded.providers?.minimax?.model ?? 'stream',
121
+ ttsModel: loaded.providers?.minimax?.ttsModel ?? 'speech-2.8-hd',
122
+ audioFormat: loaded.providers?.minimax?.audioFormat ?? 'mp3'
123
+ }
124
+ }
125
+ };
126
+ }
127
+ catch (error) {
128
+ console.error('[ocosay] 配置文件读取失败,使用默认配置:', error);
129
+ return generateDefaultConfig();
89
130
  }
90
131
  }
91
- // 单例导出
92
- export const configManager = new ConfigManager();
93
- export { ConfigManager, DEFAULT_CONFIG };
94
- export default configManager;
95
132
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -1 +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"}
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,CA4B1E;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"}
package/dist/index.js CHANGED
@@ -24,6 +24,9 @@ export async function initialize(config) {
24
24
  return;
25
25
  }
26
26
  if (config?.providers?.minimax) {
27
+ if (!config.providers.minimax.apiKey) {
28
+ throw new Error('[ocosay] API Key is required. Please set minimax.apiKey in ~/.config/opencode/ocosay.jsonc');
29
+ }
27
30
  const minimaxProvider = new MiniMaxProvider(config.providers.minimax);
28
31
  registerProvider('minimax', minimaxProvider);
29
32
  await minimaxProvider.initialize();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/plugin.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { Plugin } from '@opencode-ai/plugin';
2
- declare const OcosayPlugin: Plugin;
3
- export default OcosayPlugin;
2
+ declare const _default: {
3
+ server: Plugin;
4
+ };
5
+ export default _default;
4
6
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAA8B,MAAM,qBAAqB,CAAA;AA4I7E,QAAA,MAAM,YAAY,EAAE,MAsBnB,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAA8B,MAAM,qBAAqB,CAAA;;;;AAgL7E,wBAAuC"}
package/dist/plugin.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { tool } from '@opencode-ai/plugin';
2
2
  import { handleToolCall } from './index';
3
3
  import { initialize } from './index';
4
+ import { loadOrCreateConfig } from './config';
4
5
  const pluginName = 'ocosay';
5
6
  const ttsSpeakTool = tool({
6
7
  description: '将文本转换为语音并播放',
@@ -128,8 +129,16 @@ const ttsStreamStatusTool = tool({
128
129
  });
129
130
  const OcosayPlugin = async (_input, _options) => {
130
131
  console.info(`${pluginName}: initializing...`);
132
+ const config = loadOrCreateConfig();
131
133
  await initialize({
132
- autoRead: false
134
+ autoRead: config.autoRead,
135
+ providers: {
136
+ minimax: {
137
+ apiKey: config.providers.minimax.apiKey,
138
+ baseURL: config.providers.minimax.baseURL || undefined,
139
+ voiceId: config.providers.minimax.voiceId || undefined
140
+ }
141
+ }
133
142
  });
134
143
  return {
135
144
  tool: {
@@ -144,8 +153,10 @@ const OcosayPlugin = async (_input, _options) => {
144
153
  tts_stream_stop: ttsStreamStopTool,
145
154
  tts_stream_status: ttsStreamStatusTool
146
155
  },
147
- config: async () => { }
156
+ config: async () => {
157
+ return;
158
+ }
148
159
  };
149
160
  };
150
- export default OcosayPlugin;
161
+ export default { server: OcosayPlugin };
151
162
  //# sourceMappingURL=plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Ocosay Configuration Types
3
+ * 配置文件类型定义
4
+ */
5
+ export interface OcosayConfig {
6
+ enabled: boolean;
7
+ autoPlay: boolean;
8
+ autoRead: boolean;
9
+ streamMode: boolean;
10
+ streamBufferSize: number;
11
+ streamBufferTimeout: number;
12
+ speed: number;
13
+ volume: number;
14
+ pitch: number;
15
+ providers: {
16
+ minimax: {
17
+ apiKey: string;
18
+ baseURL: string;
19
+ voiceId: string;
20
+ model: 'sync' | 'async' | 'stream';
21
+ ttsModel: string;
22
+ audioFormat: 'mp3' | 'wav' | 'flac';
23
+ };
24
+ };
25
+ }
26
+ export declare const DEFAULT_CONFIG: Omit<OcosayConfig, 'providers'>;
27
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE;QACT,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAA;YACd,OAAO,EAAE,MAAM,CAAA;YACf,OAAO,EAAE,MAAM,CAAA;YACf,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;YAClC,QAAQ,EAAE,MAAM,CAAA;YAChB,WAAW,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;SACpC,CAAA;KACF,CAAA;CACF;AAED,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,CAU1D,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Ocosay Configuration Types
3
+ * 配置文件类型定义
4
+ */
5
+ export const DEFAULT_CONFIG = {
6
+ enabled: true,
7
+ autoPlay: false,
8
+ autoRead: false,
9
+ streamMode: true,
10
+ streamBufferSize: 30,
11
+ streamBufferTimeout: 2000,
12
+ speed: 1.0,
13
+ volume: 80,
14
+ pitch: 1.0
15
+ };
16
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH,MAAM,CAAC,MAAM,cAAc,GAAoC;IAC7D,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,IAAI;IAChB,gBAAgB,EAAE,EAAE;IACpB,mBAAmB,EAAE,IAAI;IACzB,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,GAAG;CACX,CAAA"}
package/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "@mingxy/ocosay",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "OpenCode TTS 播放插件 - 支持豆包模式边接收边朗读",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/mengfanbo123/ocosay.git"
11
+ },
12
+ "homepage": "https://github.com/mengfanbo123/ocosay#readme",
8
13
  "exports": {
9
14
  ".": {
10
15
  "import": "./dist/index.js",
package/src/config.ts CHANGED
@@ -1,121 +1,149 @@
1
- /**
2
- * Configuration Management
3
- * 配置管理模块
4
- */
5
-
6
- import { GlobalConfig, ProviderConfig, OcosayConfig } from './core/types'
7
- import { TTSError, TTSErrorCode } from './core/types'
8
- import fs from 'fs'
9
- import path from 'path'
10
-
11
- const DEFAULT_CONFIG: OcosayConfig = {
12
- enabled: true,
13
- autoPlay: false,
14
- autoRead: false, // 豆包模式开关
15
- streamMode: true, // 流式朗读模式
16
- streamBufferSize: 30, // 缓冲字符数
17
- streamBufferTimeout: 2000, // 缓冲区超时(ms)
18
- provider: 'minimax',
19
- ttsModel: 'speech-02-turbo',
20
- baseURL: 'https://api.minimax.io',
21
- speed: 1.0,
22
- volume: 80,
23
- pitch: 1.0
24
- }
1
+ import * as fs from 'fs'
2
+ import * as path from 'path'
3
+ import * as os from 'os'
4
+ import type { OcosayConfig } from './types/config'
5
+ import { DEFAULT_CONFIG } from './types/config'
25
6
 
26
- class ConfigManager {
27
- private config: OcosayConfig
28
- private configPath: string
29
- private providers: Record<string, ProviderConfig> = {}
7
+ const CONFIG_PATH = path.join(os.homedir(), '.config', 'opencode', 'ocosay.jsonc')
30
8
 
31
- constructor(configPath?: string) {
32
- this.configPath = configPath || './config.json'
33
- const loaded = this.loadConfig()
34
- this.config = loaded
35
- this.providers = (loaded as Record<string, unknown>).providers as Record<string, ProviderConfig> || {}
9
+ export function generateDefaultConfig(): OcosayConfig {
10
+ return {
11
+ ...DEFAULT_CONFIG,
12
+ providers: {
13
+ minimax: {
14
+ apiKey: '',
15
+ baseURL: '',
16
+ voiceId: '',
17
+ model: 'stream',
18
+ ttsModel: 'speech-2.8-hd',
19
+ audioFormat: 'mp3'
20
+ }
21
+ }
36
22
  }
23
+ }
37
24
 
38
- private loadConfig(): OcosayConfig {
39
- try {
40
- if (fs.existsSync(this.configPath)) {
41
- const content = fs.readFileSync(this.configPath, 'utf-8')
42
- const parsed = JSON.parse(content)
43
- this.providers = parsed.providers || {}
44
- const { providers, ...config } = parsed
45
- return { ...DEFAULT_CONFIG, ...config }
25
+ export function stripComments(jsonc: string): string {
26
+ let result = ''
27
+ let inString = false
28
+ let stringChar = ''
29
+ let i = 0
30
+
31
+ while (i < jsonc.length) {
32
+ const char = jsonc[i]
33
+
34
+ if (!inString && (char === '"' || char === "'" || char === '`')) {
35
+ inString = true
36
+ stringChar = char
37
+ result += char
38
+ i++
39
+ continue
40
+ }
41
+
42
+ if (inString && char === stringChar && jsonc[i - 1] !== '\\') {
43
+ inString = false
44
+ result += char
45
+ i++
46
+ continue
47
+ }
48
+
49
+ if (inString) {
50
+ result += char
51
+ i++
52
+ continue
53
+ }
54
+
55
+ if (char === '/' && jsonc[i + 1] === '/') {
56
+ while (i < jsonc.length && jsonc[i] !== '\n') {
57
+ i++
46
58
  }
47
- } catch (error) {
48
- console.warn('Failed to load config, using defaults')
59
+ continue
49
60
  }
50
- return { ...DEFAULT_CONFIG }
51
- }
52
61
 
53
- saveConfig(): void {
54
- try {
55
- const dir = path.dirname(this.configPath)
56
- if (!fs.existsSync(dir)) {
57
- fs.mkdirSync(dir, { recursive: true })
62
+ if (char === '/' && jsonc[i + 1] === '*') {
63
+ i += 2
64
+ while (i < jsonc.length - 1 && !(jsonc[i] === '*' && jsonc[i + 1] === '/')) {
65
+ i++
58
66
  }
59
- const configWithProviders = { ...this.config, providers: this.providers }
60
- fs.writeFileSync(this.configPath, JSON.stringify(configWithProviders, null, 2))
61
- } catch (error) {
62
- console.error('Failed to save config:', error)
67
+ i += 2
68
+ continue
63
69
  }
64
- }
65
70
 
66
- getGlobal(): OcosayConfig {
67
- return this.config
71
+ result += char
72
+ i++
68
73
  }
69
74
 
70
- getProviderConfig(providerName: string): ProviderConfig | undefined {
71
- return this.providers[providerName]
72
- }
75
+ return result
76
+ }
73
77
 
74
- setProviderConfig(providerName: string, config: ProviderConfig): void {
75
- this.providers[providerName] = { enabled: true, ...config }
76
- this.saveConfig()
78
+ export function mergeWithDefaults(
79
+ loaded: Partial<OcosayConfig>,
80
+ defaults: Omit<OcosayConfig, 'providers'>
81
+ ): Omit<OcosayConfig, 'providers'> {
82
+ return {
83
+ enabled: loaded.enabled ?? defaults.enabled,
84
+ autoPlay: loaded.autoPlay ?? defaults.autoPlay,
85
+ autoRead: loaded.autoRead ?? defaults.autoRead,
86
+ streamMode: loaded.streamMode ?? defaults.streamMode,
87
+ streamBufferSize: loaded.streamBufferSize ?? defaults.streamBufferSize,
88
+ streamBufferTimeout: loaded.streamBufferTimeout ?? defaults.streamBufferTimeout,
89
+ speed: loaded.speed ?? defaults.speed,
90
+ volume: loaded.volume ?? defaults.volume,
91
+ pitch: loaded.pitch ?? defaults.pitch
77
92
  }
93
+ }
78
94
 
79
- getDefaultProvider(): string {
80
- return this.config.provider || 'minimax'
81
- }
95
+ export function loadOrCreateConfig(): OcosayConfig {
96
+ const configDir = path.dirname(CONFIG_PATH)
82
97
 
83
- setDefaultProvider(provider: string): void {
84
- this.config.provider = provider
85
- this.saveConfig()
98
+ if (!fs.existsSync(configDir)) {
99
+ try {
100
+ fs.mkdirSync(configDir, { recursive: true })
101
+ } catch (err) {
102
+ throw new Error(`[ocosay] 无法创建配置目录 ${configDir}: ${err}`)
103
+ }
86
104
  }
87
105
 
88
- validateApiKey(provider: string, apiKey: string): void {
89
- if (!apiKey) {
90
- throw new TTSError(
91
- `API key is required for provider "${provider}"`,
92
- TTSErrorCode.AUTH,
93
- provider
94
- )
106
+ if (!fs.existsSync(CONFIG_PATH)) {
107
+ console.info('[ocosay] 配置文件不存在,正在创建默认配置...')
108
+ const defaultConfig = generateDefaultConfig()
109
+ const configContent = JSON.stringify(defaultConfig, null, 2)
110
+ try {
111
+ fs.writeFileSync(CONFIG_PATH, configContent, 'utf-8')
112
+ try {
113
+ fs.chmodSync(CONFIG_PATH, 0o600)
114
+ } catch (err) {
115
+ console.warn(`[ocosay] 无法设置配置文件权限: ${err}`)
116
+ }
117
+ } catch (err) {
118
+ throw new Error(`[ocosay] 无法写入配置文件 ${CONFIG_PATH}: ${err}`)
95
119
  }
120
+ console.info(`[ocosay] 配置文件已创建: ${CONFIG_PATH}`)
121
+ console.info('[ocosay] 请编辑配置文件填入 API Key 和 Base URL')
122
+ return defaultConfig
96
123
  }
97
124
 
98
- validateStreamConfig(): void {
99
- if ((this.config.streamBufferSize ?? 30) < 5) {
100
- throw new TTSError(
101
- 'streamBufferSize must be at least 5',
102
- TTSErrorCode.INVALID_PARAMS,
103
- 'config'
104
- )
105
- }
106
- if ((this.config.streamBufferTimeout ?? 2000) < 500) {
107
- throw new TTSError(
108
- 'streamBufferTimeout must be at least 500ms',
109
- TTSErrorCode.INVALID_PARAMS,
110
- 'config'
111
- )
125
+ try {
126
+ const content = fs.readFileSync(CONFIG_PATH, 'utf-8')
127
+ const stripped = stripComments(content)
128
+ const loaded = JSON.parse(stripped) as Partial<OcosayConfig>
129
+
130
+ const merged = mergeWithDefaults(loaded, DEFAULT_CONFIG)
131
+
132
+ return {
133
+ ...merged,
134
+ providers: {
135
+ minimax: {
136
+ apiKey: loaded.providers?.minimax?.apiKey ?? '',
137
+ baseURL: loaded.providers?.minimax?.baseURL ?? '',
138
+ voiceId: loaded.providers?.minimax?.voiceId ?? '',
139
+ model: loaded.providers?.minimax?.model ?? 'stream',
140
+ ttsModel: loaded.providers?.minimax?.ttsModel ?? 'speech-2.8-hd',
141
+ audioFormat: loaded.providers?.minimax?.audioFormat ?? 'mp3'
142
+ }
143
+ }
112
144
  }
145
+ } catch (error) {
146
+ console.error('[ocosay] 配置文件读取失败,使用默认配置:', error)
147
+ return generateDefaultConfig()
113
148
  }
114
149
  }
115
-
116
- // 单例导出
117
- export const configManager = new ConfigManager()
118
-
119
- export { ConfigManager, DEFAULT_CONFIG }
120
- export type { OcosayConfig, GlobalConfig, ProviderConfig }
121
- export default configManager
package/src/index.ts CHANGED
@@ -38,8 +38,11 @@ export async function initialize(config?: InitializeOptions): Promise<void> {
38
38
  if (initialized) {
39
39
  return
40
40
  }
41
-
41
+
42
42
  if (config?.providers?.minimax) {
43
+ if (!config.providers.minimax.apiKey) {
44
+ throw new Error('[ocosay] API Key is required. Please set minimax.apiKey in ~/.config/opencode/ocosay.jsonc')
45
+ }
43
46
  const minimaxProvider = new MiniMaxProvider(config.providers.minimax)
44
47
  registerProvider('minimax', minimaxProvider)
45
48
  await minimaxProvider.initialize()
package/src/plugin.ts CHANGED
@@ -2,6 +2,7 @@ import { tool } from '@opencode-ai/plugin'
2
2
  import type { Plugin, PluginInput, PluginOptions } from '@opencode-ai/plugin'
3
3
  import { handleToolCall } from './index'
4
4
  import { initialize, destroy } from './index'
5
+ import { loadOrCreateConfig } from './config'
5
6
 
6
7
  const pluginName = 'ocosay'
7
8
 
@@ -141,11 +142,20 @@ const ttsStreamStatusTool = tool({
141
142
 
142
143
  const OcosayPlugin: Plugin = async (_input: PluginInput, _options?: PluginOptions) => {
143
144
  console.info(`${pluginName}: initializing...`)
144
-
145
+
146
+ const config = loadOrCreateConfig()
147
+
145
148
  await initialize({
146
- autoRead: false
149
+ autoRead: config.autoRead,
150
+ providers: {
151
+ minimax: {
152
+ apiKey: config.providers.minimax.apiKey,
153
+ baseURL: config.providers.minimax.baseURL || undefined,
154
+ voiceId: config.providers.minimax.voiceId || undefined
155
+ }
156
+ }
147
157
  })
148
-
158
+
149
159
  return {
150
160
  tool: {
151
161
  tts_speak: ttsSpeakTool,
@@ -159,8 +169,10 @@ const OcosayPlugin: Plugin = async (_input: PluginInput, _options?: PluginOption
159
169
  tts_stream_stop: ttsStreamStopTool,
160
170
  tts_stream_status: ttsStreamStatusTool
161
171
  },
162
- config: async () => {}
172
+ config: async () => {
173
+ return
174
+ }
163
175
  }
164
176
  }
165
177
 
166
- export default OcosayPlugin
178
+ export default { server: OcosayPlugin }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Ocosay Configuration Types
3
+ * 配置文件类型定义
4
+ */
5
+
6
+ export interface OcosayConfig {
7
+ enabled: boolean
8
+ autoPlay: boolean
9
+ autoRead: boolean
10
+ streamMode: boolean
11
+ streamBufferSize: number
12
+ streamBufferTimeout: number
13
+ speed: number
14
+ volume: number
15
+ pitch: number
16
+ providers: {
17
+ minimax: {
18
+ apiKey: string
19
+ baseURL: string
20
+ voiceId: string
21
+ model: 'sync' | 'async' | 'stream'
22
+ ttsModel: string
23
+ audioFormat: 'mp3' | 'wav' | 'flac'
24
+ }
25
+ }
26
+ }
27
+
28
+ export const DEFAULT_CONFIG: Omit<OcosayConfig, 'providers'> = {
29
+ enabled: true,
30
+ autoPlay: false,
31
+ autoRead: false,
32
+ streamMode: true,
33
+ streamBufferSize: 30,
34
+ streamBufferTimeout: 2000,
35
+ speed: 1.0,
36
+ volume: 80,
37
+ pitch: 1.0
38
+ }
@@ -0,0 +1,327 @@
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
+ })
@@ -29,7 +29,8 @@ jest.mock('../src/index', () => ({
29
29
  }))
30
30
 
31
31
  import { handleToolCall } from '../src/index'
32
- import OcosayPlugin from '../src/plugin'
32
+ import pluginExport from '../src/plugin'
33
+ const OcosayPlugin = pluginExport.server
33
34
 
34
35
  describe('plugin.ts', () => {
35
36
  beforeEach(() => {