@coeiro-operator/core 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 (32) hide show
  1. package/README.md +11 -0
  2. package/dist/common/config-paths.d.ts +12 -0
  3. package/dist/common/config-paths.js +43 -0
  4. package/dist/dictionary/default-dictionaries.d.ts +20 -0
  5. package/dist/dictionary/default-dictionaries.js +48 -0
  6. package/dist/dictionary/dictionary-client.d.ts +73 -0
  7. package/dist/dictionary/dictionary-client.js +115 -0
  8. package/dist/dictionary/dictionary-persistence.d.ts +48 -0
  9. package/dist/dictionary/dictionary-persistence.js +82 -0
  10. package/dist/dictionary/dictionary-service.d.ts +32 -0
  11. package/dist/dictionary/dictionary-service.js +102 -0
  12. package/dist/environment/speaker-provider.d.ts +72 -0
  13. package/dist/environment/speaker-provider.js +174 -0
  14. package/dist/index.d.ts +19 -0
  15. package/dist/index.js +27 -0
  16. package/dist/operator/character-defaults.d.ts +20 -0
  17. package/dist/operator/character-defaults.js +128 -0
  18. package/dist/operator/character-info-service.d.ts +73 -0
  19. package/dist/operator/character-info-service.js +152 -0
  20. package/dist/operator/config-manager.d.ts +145 -0
  21. package/dist/operator/config-manager.js +232 -0
  22. package/dist/operator/file-operation-manager.d.ts +82 -0
  23. package/dist/operator/file-operation-manager.js +230 -0
  24. package/dist/operator/index.d.ts +128 -0
  25. package/dist/operator/index.js +353 -0
  26. package/dist/terminal/terminal-background.d.ts +37 -0
  27. package/dist/terminal/terminal-background.js +207 -0
  28. package/dist/test-utils/test-env.d.ts +10 -0
  29. package/dist/test-utils/test-env.js +13 -0
  30. package/dist/types.d.ts +58 -0
  31. package/dist/types.js +5 -0
  32. package/package.json +54 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * src/core/environment/speaker-provider.ts: Speaker情報プロバイダ
3
+ * COEIROINKサーバーからの動的Speaker情報取得を一元管理
4
+ */
5
+ // CONNECTION_SETTINGSを直接定義(循環参照を避けるため)
6
+ const CONNECTION_SETTINGS = {
7
+ DEFAULT_HOST: 'localhost',
8
+ DEFAULT_PORT: '50032',
9
+ };
10
+ /**
11
+ * Speaker情報プロバイダクラス
12
+ * COEIROINKサーバーからのSpeaker情報取得を一元管理
13
+ */
14
+ export class SpeakerProvider {
15
+ connectionConfig;
16
+ constructor(connectionConfig) {
17
+ this.connectionConfig = {
18
+ host: connectionConfig?.host || CONNECTION_SETTINGS.DEFAULT_HOST,
19
+ port: connectionConfig?.port || CONNECTION_SETTINGS.DEFAULT_PORT,
20
+ };
21
+ }
22
+ /**
23
+ * 接続設定を更新
24
+ */
25
+ updateConnection(config) {
26
+ this.connectionConfig = {
27
+ ...this.connectionConfig,
28
+ ...config,
29
+ };
30
+ }
31
+ /**
32
+ * サーバー接続確認
33
+ */
34
+ async checkConnection() {
35
+ const url = `http://${this.connectionConfig.host}:${this.connectionConfig.port}/v1/speakers`;
36
+ try {
37
+ const response = await fetch(url, {
38
+ signal: AbortSignal.timeout(3000),
39
+ });
40
+ return response.ok;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ /**
47
+ * 利用可能な音声一覧を取得
48
+ */
49
+ async getSpeakers() {
50
+ const url = `http://${this.connectionConfig.host}:${this.connectionConfig.port}/v1/speakers`;
51
+ try {
52
+ const response = await fetch(url, {
53
+ signal: AbortSignal.timeout(5000),
54
+ });
55
+ if (!response.ok) {
56
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
57
+ }
58
+ const speakers = (await response.json());
59
+ return speakers;
60
+ }
61
+ catch (error) {
62
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
63
+ throw new Error(`Failed to fetch speakers: ${errorMessage}`);
64
+ }
65
+ }
66
+ /**
67
+ * 特定のSpeakerの立ち絵画像を取得
68
+ */
69
+ async getSpeakerPortrait(speakerId) {
70
+ const speakers = await this.getSpeakers();
71
+ const speaker = speakers.find(s => s.speakerUuid === speakerId);
72
+ return speaker?.base64Portrait || null;
73
+ }
74
+ /**
75
+ * 特定の音声のスタイル情報を取得
76
+ */
77
+ async getVoiceStyles(voiceId) {
78
+ const speakers = await this.getSpeakers();
79
+ const speaker = speakers.find(s => s.speakerUuid === voiceId);
80
+ return speaker?.styles || [];
81
+ }
82
+ /**
83
+ * 特定の音声の最初のスタイルIDを取得(フォールバック用)
84
+ */
85
+ async getFirstStyleId(voiceId) {
86
+ const styles = await this.getVoiceStyles(voiceId);
87
+ return styles.length > 0 ? styles[0].styleId : 0; // デフォルトスタイルID
88
+ }
89
+ /**
90
+ * 全Speakerを取得(エイリアス)
91
+ */
92
+ async getAllSpeakers() {
93
+ return await this.getSpeakers();
94
+ }
95
+ /**
96
+ * デバッグ用:音声一覧をコンソール出力
97
+ */
98
+ async logAvailableVoices() {
99
+ try {
100
+ const speakers = await this.getSpeakers();
101
+ console.log('Available voices:');
102
+ speakers.forEach(speaker => {
103
+ console.log(`${speaker.speakerUuid}: ${speaker.speakerName}`);
104
+ speaker.styles.forEach(style => {
105
+ console.log(` Style ${style.styleId}: ${style.styleName}`);
106
+ });
107
+ });
108
+ }
109
+ catch {
110
+ console.error(`Error: Cannot connect to COEIROINK server at http://${this.connectionConfig.host}:${this.connectionConfig.port}`);
111
+ console.error('Make sure the server is running.');
112
+ // デバッグ用メソッドなので、エラーが発生してもプログラムを停止させない
113
+ console.log('Available voices:');
114
+ // エラー時は何も表示しない(エラーメッセージは既に出力済み)
115
+ }
116
+ }
117
+ /**
118
+ * 音声名からIDを生成(英語名への変換)
119
+ */
120
+ speakerNameToId(speakerName) {
121
+ const SPEAKER_NAME_TO_ID_MAP = {
122
+ つくよみちゃん: 'tsukuyomi',
123
+ アンジーさん: 'angie',
124
+ アルマちゃん: 'alma',
125
+ 'AI声優-朱花': 'akane',
126
+ ディアちゃん: 'dia',
127
+ KANA: 'kana',
128
+ 'AI声優-KANA': 'kana',
129
+ 金苗: 'kanae',
130
+ 'AI声優-金苗': 'kanae',
131
+ リリンちゃん: 'rilin',
132
+ MANA: 'mana',
133
+ 'AI声優-MANA': 'mana',
134
+ おふとんP: 'ofutonp',
135
+ クロワちゃん: 'kurowa',
136
+ 'AI声優-青葉': 'aoba',
137
+ 'AI声優-銀芽': 'ginga',
138
+ };
139
+ // マッピングに存在しない場合の処理
140
+ if (SPEAKER_NAME_TO_ID_MAP[speakerName]) {
141
+ return SPEAKER_NAME_TO_ID_MAP[speakerName];
142
+ }
143
+ // 英数字を含む場合のみ変換を試みる
144
+ const converted = speakerName.toLowerCase().replace(/[^a-z0-9]/g, '');
145
+ if (converted.length === 0) {
146
+ // 空文字列になる場合は、名前をローマ字風に変換(簡易的な処理)
147
+ console.warn(`未登録の音声名: ${speakerName} - デフォルトIDを生成します`);
148
+ return 'unknown_' + Date.now().toString(36);
149
+ }
150
+ return converted;
151
+ }
152
+ }
153
+ /**
154
+ * シングルトンインスタンス
155
+ * プロジェクト全体で共有されるSpeakerプロバイダ
156
+ */
157
+ let globalSpeakerProvider = null;
158
+ /**
159
+ * グローバルSpeakerプロバイダを取得
160
+ * 設定ファイルから接続情報を読み込んで初期化
161
+ */
162
+ export function getSpeakerProvider(connectionConfig) {
163
+ if (!globalSpeakerProvider || connectionConfig) {
164
+ globalSpeakerProvider = new SpeakerProvider(connectionConfig);
165
+ }
166
+ return globalSpeakerProvider;
167
+ }
168
+ /**
169
+ * Speakerプロバイダをリセット(テスト用)
170
+ */
171
+ export function resetSpeakerProvider() {
172
+ globalSpeakerProvider = null;
173
+ }
174
+ //# sourceMappingURL=speaker-provider.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @coeiro-operator/core - Core utilities and shared functionality
3
+ */
4
+ export * from './common/config-paths.js';
5
+ export * from './types.js';
6
+ export { logger, LoggerPresets } from '@coeiro-operator/common';
7
+ export * from './dictionary/dictionary-service.js';
8
+ export * from './dictionary/dictionary-client.js';
9
+ export * from './dictionary/dictionary-persistence.js';
10
+ export * from './dictionary/default-dictionaries.js';
11
+ export * from './operator/index.js';
12
+ export * from './operator/character-info-service.js';
13
+ export * from './operator/character-defaults.js';
14
+ export { default as ConfigManager, TerminalBackgroundConfig } from './operator/config-manager.js';
15
+ export * from './operator/file-operation-manager.js';
16
+ export { VoiceStyle, ConnectionConfig, getSpeakerProvider, type SpeakerProvider } from './environment/speaker-provider.js';
17
+ export { TerminalBackground } from './terminal/terminal-background.js';
18
+ export * from './test-utils/test-env.js';
19
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @coeiro-operator/core - Core utilities and shared functionality
3
+ */
4
+ // Config and paths
5
+ export * from './common/config-paths.js';
6
+ // Common types
7
+ export * from './types.js';
8
+ // Logger (re-export from common)
9
+ export { logger, LoggerPresets } from '@coeiro-operator/common';
10
+ // Dictionary
11
+ export * from './dictionary/dictionary-service.js';
12
+ export * from './dictionary/dictionary-client.js';
13
+ export * from './dictionary/dictionary-persistence.js';
14
+ export * from './dictionary/default-dictionaries.js';
15
+ // Operator
16
+ export * from './operator/index.js';
17
+ export * from './operator/character-info-service.js';
18
+ export * from './operator/character-defaults.js';
19
+ export { default as ConfigManager } from './operator/config-manager.js';
20
+ export * from './operator/file-operation-manager.js';
21
+ // Environment (Speakerは除外してcharacter-info-serviceから使用)
22
+ export { getSpeakerProvider } from './environment/speaker-provider.js';
23
+ // Terminal
24
+ export { TerminalBackground } from './terminal/terminal-background.js';
25
+ // Test utilities
26
+ export * from './test-utils/test-env.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * src/operator/character-defaults.ts: 内蔵キャラクター設定
3
+ * COEIROINKキャラクターのデフォルト設定を定義
4
+ */
5
+ export interface BaseCharacterConfig {
6
+ speakerId: string;
7
+ name: string;
8
+ personality: string;
9
+ speakingStyle: string;
10
+ greeting: string;
11
+ farewell: string;
12
+ defaultStyle: string;
13
+ }
14
+ export interface CharacterConfig extends BaseCharacterConfig {
15
+ availableStyles?: string[];
16
+ disabled?: boolean;
17
+ }
18
+ export declare const BUILTIN_CHARACTER_CONFIGS: Record<string, BaseCharacterConfig>;
19
+ export declare const DEFAULT_CHARACTER_ID = "tsukuyomi";
20
+ //# sourceMappingURL=character-defaults.d.ts.map
@@ -0,0 +1,128 @@
1
+ /**
2
+ * src/operator/character-defaults.ts: 内蔵キャラクター設定
3
+ * COEIROINKキャラクターのデフォルト設定を定義
4
+ */
5
+ // characterキー(tsukuyomi等)をキーとした内蔵キャラクター設定
6
+ // speakerIdでCOEIROINKのSpeakerと紐付け
7
+ export const BUILTIN_CHARACTER_CONFIGS = {
8
+ tsukuyomi: {
9
+ speakerId: '3c37646f-3881-5374-2a83-149267990abc',
10
+ name: 'つくよみちゃん',
11
+ personality: '冷静で丁寧、報告は簡潔で正確',
12
+ speakingStyle: '敬語、落ち着いた口調',
13
+ greeting: '本日も作業をサポートさせていただきます。つくよみちゃんです。',
14
+ farewell: '本日の作業、お疲れさまでした。',
15
+ defaultStyle: 'れいせい', // 利用可能: れいせい, おしとやか, げんき
16
+ },
17
+ angie: {
18
+ speakerId: 'cc213e6d-d847-45b5-a1df-415744c890f2',
19
+ name: 'アンジーさん',
20
+ personality: '元気でフレンドリー、明るく積極的',
21
+ speakingStyle: 'カジュアルで親しみやすい口調',
22
+ greeting: 'やっほー!今日もよろしくお願いします!',
23
+ farewell: '今日もお疲れさまでした!',
24
+ defaultStyle: 'のーまる', // 利用可能: のーまる, セクシー, ささやき
25
+ },
26
+ alma: {
27
+ speakerId: 'c97966b1-d80c-04f5-aba5-d30a92843b59',
28
+ name: 'アルマちゃん',
29
+ personality: '優しく穏やか、思いやりがある',
30
+ speakingStyle: '丁寧で優しい口調',
31
+ greeting: 'こんにちは。今日もがんばりましょう。',
32
+ farewell: '今日もお疲れさまでした。',
33
+ defaultStyle: '表-v2', // 利用可能: 表-v2, 表-v1, 裏, 泣き声, 堕ちた悪魔
34
+ },
35
+ akane: {
36
+ speakerId: 'd1143ac1-c486-4273-92ef-a30938d01b91',
37
+ name: 'AI声優-朱花',
38
+ personality: 'プロフェッショナル、的確で信頼できる',
39
+ speakingStyle: '明瞭で聞き取りやすい標準的な口調',
40
+ greeting: 'こんにちは。本日もサポートいたします。',
41
+ farewell: '本日の作業、お疲れさまでした。',
42
+ defaultStyle: 'のーまるv2', // 利用可能: のーまるv2, のーまるv1
43
+ },
44
+ kana: {
45
+ speakerId: '297a5b91-f88a-6951-5841-f1e648b2e594',
46
+ name: 'KANA',
47
+ personality: '落ち着いていて知的、分析的',
48
+ speakingStyle: '理知的で冷静な口調',
49
+ greeting: 'こんにちは。効率的に作業を進めましょう。',
50
+ farewell: '本日の作業、お疲れさまでした。',
51
+ defaultStyle: 'のーまる', // 利用可能: のーまる, えんげき, ほうかご, ないしょばなし
52
+ },
53
+ kanae: {
54
+ speakerId: 'd41bcbd9-f4a9-4e10-b000-7a431568dd01',
55
+ name: 'AI声優-金苗',
56
+ personality: '上品で知的、お嬢様的な品格',
57
+ speakingStyle: '丁寧で上品な口調',
58
+ greeting: 'ごきげんよう。本日もよろしくお願いいたします。',
59
+ farewell: 'お疲れさまでございました。',
60
+ defaultStyle: 'のーまる', // 利用可能: のーまる, 愉悦 Aタイプ, 愉悦 Bタイプ, 喜び, ふわふわ, ぷんぷん
61
+ },
62
+ mana: {
63
+ speakerId: '292ea286-3d5f-f1cc-157c-66462a6a9d08',
64
+ name: 'MANA',
65
+ personality: '穏やかで包容力がある、時にはのんびり、母性的で優しい',
66
+ speakingStyle: 'ゆったりとした口調、癒し系の表現、のんびりとした話し方',
67
+ greeting: 'MANAです。今日もゆっくり一緒に作業しましょうね。',
68
+ farewell: '今日もお疲れ様でした。ゆっくり休んでくださいね。',
69
+ defaultStyle: 'のーまる', // 利用可能: のーまる, いっしょうけんめい, ごきげん, どやがお, ふくれっつら, しょんぼり, ないしょばなし, ひっさつわざ, ねむねむ, ぱじゃまぱーてぃー
70
+ },
71
+ dia: {
72
+ speakerId: 'b28bb401-bc43-c9c7-77e4-77a2bbb4b283',
73
+ name: 'ディアちゃん',
74
+ personality: '優しく思いやりがある、ユーザに寄り添う、母性的で包容力がある',
75
+ speakingStyle: '丁寧で温かみのある口調、優しく柔らかな表現を好む',
76
+ greeting: 'ディアです。今日も一緒に頑張りましょうね。',
77
+ farewell: '今日も一日お疲れ様でした。ゆっくり休んでくださいね。',
78
+ defaultStyle: 'のーまる', // 利用可能: のーまる, セクシー, ひそひそ
79
+ },
80
+ rilin: {
81
+ speakerId: 'cb11bdbd-78fc-4f16-b528-a400bae1782d',
82
+ name: 'リリンちゃん',
83
+ personality: '元気で活発、ポジティブ、生意気で強気な面もある',
84
+ speakingStyle: '明るく元気な口調、励ましの言葉が得意、時に少し生意気な発言も',
85
+ greeting: '今日も元気いっぱい!リリンが担当します!',
86
+ farewell: '今日も一日お疲れ様でした!また明日も頑張りましょう!',
87
+ defaultStyle: 'のーまる', // 利用可能: のーまる, ささやき
88
+ },
89
+ ofutonp: {
90
+ speakerId: 'a60ebf6c-626a-7ce6-5d69-c92bf2a1a1d0',
91
+ name: 'おふとんP',
92
+ personality: '落ち着いた性格、多様な感情表現が可能',
93
+ speakingStyle: '穏やかな基調、状況に応じて多彩な表現',
94
+ greeting: 'おふとんPです。今日もよろしくお願いします。',
95
+ farewell: 'お疲れ様でした。また明日もよろしくお願いします。',
96
+ defaultStyle: 'ナレーション', // 利用可能: ナレーション他、22種類のスタイル
97
+ },
98
+ kurowa: {
99
+ speakerId: 'cc1153b4-d20c-46dd-a308-73ca38c0e85a',
100
+ name: 'クロワちゃん',
101
+ personality: '騎士らしい気高さと誇り、状況に応じて異なる人格',
102
+ speakingStyle: '騎士らしい堂々とした口調、状況により変化',
103
+ greeting: '騎士クロワです。本日もお供いたします。',
104
+ farewell: '本日の任務、完了いたしました。',
105
+ defaultStyle: '素顔の女騎士', // 利用可能: 素顔の女騎士, 気高き女騎士
106
+ },
107
+ aoba: {
108
+ speakerId: 'd219f5ab-a50b-4d99-a26a-a9fc213e9100',
109
+ name: 'AI声優-青葉',
110
+ personality: 'プロフェッショナルながら感情表現も豊か',
111
+ speakingStyle: 'AI声優らしいクリアな発音、感情的な表現も可能',
112
+ greeting: 'AI声優の青葉です。今日もよろしくお願いします。',
113
+ farewell: 'お疲れ様でした。また次回もよろしくお願いします。',
114
+ defaultStyle: 'のーまる', // 利用可能: のーまる, 感情的
115
+ },
116
+ ginga: {
117
+ speakerId: 'd312d0fb-d38d-434e-825d-cbcbfd105ad0',
118
+ name: 'AI声優-銀芽',
119
+ personality: '知的でクール、感情表現のバリエーションが豊富',
120
+ speakingStyle: 'クリアな発音、多様な感情表現が可能',
121
+ greeting: 'AI声優の銀芽です。本日もよろしくお願いいたします。',
122
+ farewell: '本日の収録、お疲れ様でした。',
123
+ defaultStyle: 'のーまるv2', // 利用可能: のーまるv2, のーまるv1, 感情的, 呆れ, 叫びβ, 囁きβ
124
+ },
125
+ };
126
+ // デフォルトのキャラクターID
127
+ export const DEFAULT_CHARACTER_ID = 'tsukuyomi';
128
+ //# sourceMappingURL=character-defaults.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * src/operator/character-info-service.ts: キャラクター情報管理サービス
3
+ * キャラクター詳細情報、スタイル情報の取得を担当(読み込み専用)
4
+ *
5
+ * 用語定義:
6
+ * - Speaker: COEIROINKの声の単位(音声モデル)
7
+ * - Style: Speakerの声のバリエーション(「れいせい」「おしとやか」など)
8
+ * - Character: Speakerに性格や口調の情報を付与したもの(defaultStyleなども持つ)
9
+ * - Operator: sessionId毎に割り当てられたCharacter
10
+ */
11
+ import ConfigManager from './config-manager.js';
12
+ /**
13
+ * Style: Speakerの声のバリエーション
14
+ * COEIROINKでは一つのSpeakerが複数のStyleを持つことができる
15
+ * 例: つくよみちゃんの「れいせい」「おしとやか」「げんき」
16
+ */
17
+ export interface Style {
18
+ styleId: number;
19
+ styleName: string;
20
+ }
21
+ /**
22
+ * Speaker: COEIROINKの声の単位(純粋な音声モデル)
23
+ * COEIROINK APIから取得される情報を含む
24
+ * 音声合成時に必要な最小限の情報
25
+ */
26
+ export interface Speaker {
27
+ speakerId: string;
28
+ speakerName: string;
29
+ styles: Style[];
30
+ }
31
+ /**
32
+ * Character: Speakerに性格や口調の情報を付与したもの
33
+ * Speaker(APIから) + Character設定(ファイルから) = Character
34
+ */
35
+ export interface Character {
36
+ characterId: string;
37
+ speaker: Speaker | null;
38
+ defaultStyle: string;
39
+ greeting: string;
40
+ farewell: string;
41
+ personality: string;
42
+ speakingStyle: string;
43
+ }
44
+ export declare class CharacterInfoService {
45
+ private configManager;
46
+ private coeiroinkConfigFile;
47
+ constructor();
48
+ /**
49
+ * 初期化:ConfigManagerと設定ファイルパスを設定
50
+ */
51
+ initialize(configManager: ConfigManager, coeiroinkConfigFile: string): void;
52
+ /**
53
+ * キャラクター情報を取得
54
+ */
55
+ getCharacterInfo(characterId: string): Promise<Character | null>;
56
+ /**
57
+ * スタイルを選択
58
+ * @param character キャラクター情報
59
+ * @param specifiedStyle 指定されたスタイル名
60
+ */
61
+ selectStyle(character: Character, specifiedStyle?: string | null): Style;
62
+ /**
63
+ * 指定されたキャラクターIDからCharacter情報を取得
64
+ * オペレータ割り当て時に使用
65
+ */
66
+ getOperatorCharacterInfo(characterId: string): Promise<Character | null>;
67
+ /**
68
+ * 利用可能なキャラクターIDリストを取得
69
+ */
70
+ getAvailableCharacterIds(): Promise<string[]>;
71
+ }
72
+ export default CharacterInfoService;
73
+ //# sourceMappingURL=character-info-service.d.ts.map
@@ -0,0 +1,152 @@
1
+ /**
2
+ * src/operator/character-info-service.ts: キャラクター情報管理サービス
3
+ * キャラクター詳細情報、スタイル情報の取得を担当(読み込み専用)
4
+ *
5
+ * 用語定義:
6
+ * - Speaker: COEIROINKの声の単位(音声モデル)
7
+ * - Style: Speakerの声のバリエーション(「れいせい」「おしとやか」など)
8
+ * - Character: Speakerに性格や口調の情報を付与したもの(defaultStyleなども持つ)
9
+ * - Operator: sessionId毎に割り当てられたCharacter
10
+ */
11
+ import { getSpeakerProvider } from '../environment/speaker-provider.js';
12
+ // CharacterConfigからCharacterに変換するヘルパー関数
13
+ // Speaker情報はAPIから取得されるため、非同期処理が必要
14
+ async function convertCharacterConfigToCharacter(characterId, config) {
15
+ let speaker = null;
16
+ if (config.speakerId) {
17
+ // SpeakerProviderからスタイル情報を取得
18
+ const speakerProvider = getSpeakerProvider();
19
+ try {
20
+ const speakers = await speakerProvider.getSpeakers();
21
+ const apiSpeaker = speakers.find(s => s.speakerUuid === config.speakerId);
22
+ if (apiSpeaker) {
23
+ speaker = {
24
+ speakerId: config.speakerId,
25
+ speakerName: apiSpeaker.speakerName,
26
+ styles: apiSpeaker.styles.map(style => ({
27
+ styleId: style.styleId,
28
+ styleName: style.styleName,
29
+ })),
30
+ };
31
+ }
32
+ else {
33
+ // APIから見つからない場合、基本情報のみ設定
34
+ speaker = {
35
+ speakerId: config.speakerId,
36
+ speakerName: config.name,
37
+ styles: [],
38
+ };
39
+ }
40
+ }
41
+ catch {
42
+ // APIエラーの場合、基本情報のみ設定
43
+ speaker = {
44
+ speakerId: config.speakerId,
45
+ speakerName: config.name,
46
+ styles: [],
47
+ };
48
+ }
49
+ }
50
+ return {
51
+ characterId,
52
+ speaker,
53
+ defaultStyle: config.defaultStyle,
54
+ greeting: config.greeting || '',
55
+ farewell: config.farewell || '',
56
+ personality: config.personality,
57
+ speakingStyle: config.speakingStyle,
58
+ };
59
+ }
60
+ export class CharacterInfoService {
61
+ configManager = null;
62
+ coeiroinkConfigFile = null;
63
+ constructor() {
64
+ // キャラクター情報の読み込み専用サービス
65
+ }
66
+ /**
67
+ * 初期化:ConfigManagerと設定ファイルパスを設定
68
+ */
69
+ initialize(configManager, coeiroinkConfigFile) {
70
+ this.configManager = configManager;
71
+ this.coeiroinkConfigFile = coeiroinkConfigFile;
72
+ }
73
+ /**
74
+ * キャラクター情報を取得
75
+ */
76
+ async getCharacterInfo(characterId) {
77
+ if (!this.configManager) {
78
+ throw new Error('CharacterInfoService is not initialized');
79
+ }
80
+ const config = await this.configManager.getCharacterConfig(characterId);
81
+ if (!config) {
82
+ return null;
83
+ }
84
+ return await convertCharacterConfigToCharacter(characterId, config);
85
+ }
86
+ /**
87
+ * スタイルを選択
88
+ * @param character キャラクター情報
89
+ * @param specifiedStyle 指定されたスタイル名
90
+ */
91
+ selectStyle(character, specifiedStyle = null) {
92
+ if (!character.speaker || !character.speaker.styles || character.speaker.styles.length === 0) {
93
+ throw new Error(`キャラクター '${character.characterId}' に利用可能なスタイルがありません`);
94
+ }
95
+ const styles = character.speaker.styles;
96
+ // 明示的にスタイルが指定された場合
97
+ if (specifiedStyle && specifiedStyle !== '') {
98
+ const requestedStyle = styles.find(style => style.styleName === specifiedStyle);
99
+ if (requestedStyle) {
100
+ return requestedStyle;
101
+ }
102
+ // 指定されたスタイルが見つからない場合はエラー
103
+ const availableStyleNames = styles.map(style => style.styleName);
104
+ const errorMessage = `指定されたスタイル '${specifiedStyle}' が見つかりません。利用可能なスタイル: ${availableStyleNames.join(', ')}`;
105
+ throw new Error(errorMessage);
106
+ }
107
+ // デフォルトスタイルを検索
108
+ const defaultStyle = styles.find(style => style.styleName === character.defaultStyle);
109
+ if (defaultStyle) {
110
+ return defaultStyle;
111
+ }
112
+ // デフォルトが見つからない場合は最初のスタイルを使用
113
+ return styles[0];
114
+ }
115
+ // 削除: extractGreetingPatternsメソッド
116
+ // greetingフィールドは各キャラクターに1つずつ定義されており、
117
+ // assignOperator時に自動的に返されるため、別途抽出機能は不要
118
+ // 削除: updateVoiceSettingメソッド
119
+ // CharacterInfoServiceは読み込み専用サービスとして設計されているため、
120
+ // 設定ファイルの更新機能は削除しました。
121
+ // 設定の更新が必要な場合は、ConfigManagerを通じて行ってください。
122
+ /**
123
+ * 指定されたキャラクターIDからCharacter情報を取得
124
+ * オペレータ割り当て時に使用
125
+ */
126
+ async getOperatorCharacterInfo(characterId) {
127
+ if (!this.configManager) {
128
+ throw new Error('CharacterInfoService is not initialized');
129
+ }
130
+ try {
131
+ const config = await this.configManager.getCharacterConfig(characterId);
132
+ if (!config) {
133
+ return null;
134
+ }
135
+ return await convertCharacterConfigToCharacter(characterId, config);
136
+ }
137
+ catch {
138
+ throw new Error(`オペレータ '${characterId}' は存在しないか無効です`);
139
+ }
140
+ }
141
+ /**
142
+ * 利用可能なキャラクターIDリストを取得
143
+ */
144
+ async getAvailableCharacterIds() {
145
+ if (!this.configManager) {
146
+ throw new Error('CharacterInfoService is not initialized');
147
+ }
148
+ return await this.configManager.getAvailableCharacterIds();
149
+ }
150
+ }
151
+ export default CharacterInfoService;
152
+ //# sourceMappingURL=character-info-service.js.map