@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.
- package/README.md +11 -0
- package/dist/common/config-paths.d.ts +12 -0
- package/dist/common/config-paths.js +43 -0
- package/dist/dictionary/default-dictionaries.d.ts +20 -0
- package/dist/dictionary/default-dictionaries.js +48 -0
- package/dist/dictionary/dictionary-client.d.ts +73 -0
- package/dist/dictionary/dictionary-client.js +115 -0
- package/dist/dictionary/dictionary-persistence.d.ts +48 -0
- package/dist/dictionary/dictionary-persistence.js +82 -0
- package/dist/dictionary/dictionary-service.d.ts +32 -0
- package/dist/dictionary/dictionary-service.js +102 -0
- package/dist/environment/speaker-provider.d.ts +72 -0
- package/dist/environment/speaker-provider.js +174 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +27 -0
- package/dist/operator/character-defaults.d.ts +20 -0
- package/dist/operator/character-defaults.js +128 -0
- package/dist/operator/character-info-service.d.ts +73 -0
- package/dist/operator/character-info-service.js +152 -0
- package/dist/operator/config-manager.d.ts +145 -0
- package/dist/operator/config-manager.js +232 -0
- package/dist/operator/file-operation-manager.d.ts +82 -0
- package/dist/operator/file-operation-manager.js +230 -0
- package/dist/operator/index.d.ts +128 -0
- package/dist/operator/index.js +353 -0
- package/dist/terminal/terminal-background.d.ts +37 -0
- package/dist/terminal/terminal-background.js +207 -0
- package/dist/test-utils/test-env.d.ts +10 -0
- package/dist/test-utils/test-env.js +13 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +5 -0
- package/package.json +54 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* src/operator/index.ts: オペレータ管理システム(TypeScript実装)
|
|
4
|
+
* キャラクター:スタイル単位での管理とMCP情報提供に対応
|
|
5
|
+
*/
|
|
6
|
+
import { Character, Style } from './character-info-service.js';
|
|
7
|
+
interface CharacterSession {
|
|
8
|
+
characterId: string;
|
|
9
|
+
styleId?: number;
|
|
10
|
+
styleName?: string;
|
|
11
|
+
}
|
|
12
|
+
interface AssignResult {
|
|
13
|
+
characterId: string;
|
|
14
|
+
characterName: string;
|
|
15
|
+
currentStyle: {
|
|
16
|
+
styleId: string;
|
|
17
|
+
styleName: string;
|
|
18
|
+
personality: string;
|
|
19
|
+
speakingStyle: string;
|
|
20
|
+
};
|
|
21
|
+
speakerConfig: {
|
|
22
|
+
speakerId: string;
|
|
23
|
+
styleId: number;
|
|
24
|
+
};
|
|
25
|
+
greeting?: string;
|
|
26
|
+
message?: string;
|
|
27
|
+
}
|
|
28
|
+
interface ReleaseResult {
|
|
29
|
+
characterId?: string;
|
|
30
|
+
characterName?: string;
|
|
31
|
+
farewell?: string;
|
|
32
|
+
wasAssigned: boolean;
|
|
33
|
+
}
|
|
34
|
+
interface StatusResult {
|
|
35
|
+
characterId?: string;
|
|
36
|
+
characterName?: string;
|
|
37
|
+
currentStyle?: {
|
|
38
|
+
styleId: string;
|
|
39
|
+
styleName: string;
|
|
40
|
+
personality: string;
|
|
41
|
+
speakingStyle: string;
|
|
42
|
+
};
|
|
43
|
+
message: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class OperatorManager {
|
|
46
|
+
private sessionId;
|
|
47
|
+
private configDir;
|
|
48
|
+
private coeiroinkConfigFile;
|
|
49
|
+
private configManager;
|
|
50
|
+
private dataStore;
|
|
51
|
+
private characterInfoService;
|
|
52
|
+
constructor();
|
|
53
|
+
initialize(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* 設定の事前構築(外部からの呼び出し用)
|
|
56
|
+
*/
|
|
57
|
+
buildDynamicConfig(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* キャラクター情報を取得
|
|
60
|
+
*/
|
|
61
|
+
getCharacterInfo(characterId: string): Promise<Character | null>;
|
|
62
|
+
/**
|
|
63
|
+
* スタイルを選択
|
|
64
|
+
* @param character キャラクター情報
|
|
65
|
+
* @param specifiedStyle 指定されたスタイル名
|
|
66
|
+
*/
|
|
67
|
+
selectStyle(character: Character, specifiedStyle?: string | null): Style;
|
|
68
|
+
/**
|
|
69
|
+
* 利用可能なオペレータを取得(仕事中のオペレータ情報も含む)
|
|
70
|
+
*/
|
|
71
|
+
getAvailableOperators(): Promise<{
|
|
72
|
+
available: string[];
|
|
73
|
+
busy: string[];
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* オペレータを予約
|
|
77
|
+
*/
|
|
78
|
+
reserveOperator(characterId: string, styleId?: number, styleName?: string): Promise<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* オペレータを返却
|
|
81
|
+
* オペレータが割り当てられていない場合も正常として扱う(時間切れ自動解放のケースがあるため)
|
|
82
|
+
*/
|
|
83
|
+
releaseOperator(): Promise<ReleaseResult>;
|
|
84
|
+
/**
|
|
85
|
+
* 全ての利用状況をクリア
|
|
86
|
+
*/
|
|
87
|
+
clearAllOperators(): Promise<boolean>;
|
|
88
|
+
/**
|
|
89
|
+
* 現在のセッションに割り当てられたオペレータIDを取得
|
|
90
|
+
*/
|
|
91
|
+
getCurrentOperatorId(): Promise<string | null>;
|
|
92
|
+
/**
|
|
93
|
+
* 現在のセッション情報を取得
|
|
94
|
+
*/
|
|
95
|
+
getCurrentOperatorSession(): Promise<CharacterSession | null>;
|
|
96
|
+
/**
|
|
97
|
+
* 現在のセッションのオペレータが有効かチェック
|
|
98
|
+
*/
|
|
99
|
+
validateCurrentOperatorSession(): Promise<boolean>;
|
|
100
|
+
/**
|
|
101
|
+
* 指定されたキャラクターが利用中かチェック(全セッション対象)
|
|
102
|
+
*/
|
|
103
|
+
isOperatorBusy(characterId: string): Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* 現在のオペレータをサイレントで解放
|
|
106
|
+
*/
|
|
107
|
+
silentReleaseCurrentOperator(): Promise<string | null>;
|
|
108
|
+
/**
|
|
109
|
+
* ランダムオペレータ選択と詳細情報付きアサイン
|
|
110
|
+
*/
|
|
111
|
+
assignRandomOperator(style?: string | null): Promise<AssignResult>;
|
|
112
|
+
/**
|
|
113
|
+
* 指定されたオペレータを詳細情報付きでアサイン
|
|
114
|
+
*/
|
|
115
|
+
assignSpecificOperator(specifiedCharacter: string, style?: string | null): Promise<AssignResult>;
|
|
116
|
+
/**
|
|
117
|
+
* 現在のオペレータ情報表示
|
|
118
|
+
* 仕様書準拠: getCurrentOperatorId()の自動時間切れ処理に依存し、統一された検証ロジックを実装
|
|
119
|
+
*/
|
|
120
|
+
showCurrentOperator(): Promise<StatusResult>;
|
|
121
|
+
/**
|
|
122
|
+
* オペレータ予約のタイムアウトを延長
|
|
123
|
+
* Issue #58: sayコマンド実行時の動的タイムアウト延長
|
|
124
|
+
*/
|
|
125
|
+
refreshOperatorReservation(): Promise<boolean>;
|
|
126
|
+
}
|
|
127
|
+
export default OperatorManager;
|
|
128
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* src/operator/index.ts: オペレータ管理システム(TypeScript実装)
|
|
4
|
+
* キャラクター:スタイル単位での管理とMCP情報提供に対応
|
|
5
|
+
*/
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import ConfigManager from './config-manager.js';
|
|
8
|
+
import FileOperationManager from './file-operation-manager.js';
|
|
9
|
+
import { hostname } from 'os';
|
|
10
|
+
import CharacterInfoService from './character-info-service.js';
|
|
11
|
+
import { getConfigDir } from '../common/config-paths.js';
|
|
12
|
+
/**
|
|
13
|
+
* セッションIDを取得
|
|
14
|
+
*/
|
|
15
|
+
function getSessionId() {
|
|
16
|
+
if (process.env.ITERM_SESSION_ID) {
|
|
17
|
+
return process.env.ITERM_SESSION_ID.replace(/[:-]/g, '_');
|
|
18
|
+
}
|
|
19
|
+
else if (process.env.TERM_SESSION_ID) {
|
|
20
|
+
return process.env.TERM_SESSION_ID.replace(/[:-]/g, '_');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return process.ppid.toString();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class OperatorManager {
|
|
27
|
+
sessionId;
|
|
28
|
+
configDir = null;
|
|
29
|
+
coeiroinkConfigFile = null;
|
|
30
|
+
configManager = null;
|
|
31
|
+
dataStore;
|
|
32
|
+
characterInfoService;
|
|
33
|
+
constructor() {
|
|
34
|
+
this.sessionId = getSessionId();
|
|
35
|
+
// ファイルパス生成(tmpディレクトリ)
|
|
36
|
+
const hostnameClean = hostname().replace(/[^a-zA-Z0-9]/g, '_');
|
|
37
|
+
const filePath = `/tmp/coeiroink-operators-${hostnameClean}.json`;
|
|
38
|
+
// デフォルト4時間のタイムアウトでFileOperationManagerを初期化
|
|
39
|
+
this.dataStore = new FileOperationManager(filePath, this.sessionId);
|
|
40
|
+
this.characterInfoService = new CharacterInfoService();
|
|
41
|
+
}
|
|
42
|
+
async initialize() {
|
|
43
|
+
this.configDir = await getConfigDir();
|
|
44
|
+
this.coeiroinkConfigFile = join(this.configDir, 'coeiroink-config.json');
|
|
45
|
+
// 設定管理システムを初期化
|
|
46
|
+
this.configManager = new ConfigManager(this.configDir);
|
|
47
|
+
// ConfigManagerの動的設定を事前にビルドして初期化を完了
|
|
48
|
+
try {
|
|
49
|
+
await this.configManager.buildDynamicConfig();
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.warn(`OperatorManager dynamic config build failed:`, error.message);
|
|
53
|
+
}
|
|
54
|
+
// dataStoreを初期化(設定からタイムアウト取得)
|
|
55
|
+
try {
|
|
56
|
+
const timeoutMs = await this.configManager.getOperatorTimeout();
|
|
57
|
+
const hostnameClean = hostname().replace(/[^a-zA-Z0-9]/g, '_');
|
|
58
|
+
const filePath = `/tmp/coeiroink-operators-${hostnameClean}.json`;
|
|
59
|
+
this.dataStore = new FileOperationManager(filePath, this.sessionId, timeoutMs);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.warn('OperatorManager initialization warning:', error.message);
|
|
63
|
+
// 初期化に失敗してもデフォルト設定で続行
|
|
64
|
+
}
|
|
65
|
+
// CharacterInfoServiceを初期化
|
|
66
|
+
this.characterInfoService.initialize(this.configManager, this.coeiroinkConfigFile);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 設定の事前構築(外部からの呼び出し用)
|
|
70
|
+
*/
|
|
71
|
+
async buildDynamicConfig() {
|
|
72
|
+
if (!this.configManager) {
|
|
73
|
+
throw new Error('ConfigManager is not initialized');
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
await this.configManager.buildDynamicConfig();
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error(`OperatorManager buildDynamicConfig failed:`, error.message);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* キャラクター情報を取得
|
|
85
|
+
*/
|
|
86
|
+
async getCharacterInfo(characterId) {
|
|
87
|
+
return await this.characterInfoService.getCharacterInfo(characterId);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* スタイルを選択
|
|
91
|
+
* @param character キャラクター情報
|
|
92
|
+
* @param specifiedStyle 指定されたスタイル名
|
|
93
|
+
*/
|
|
94
|
+
selectStyle(character, specifiedStyle = null) {
|
|
95
|
+
return this.characterInfoService.selectStyle(character, specifiedStyle);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 利用可能なオペレータを取得(仕事中のオペレータ情報も含む)
|
|
99
|
+
*/
|
|
100
|
+
async getAvailableOperators() {
|
|
101
|
+
if (!this.configManager) {
|
|
102
|
+
throw new Error('State manager is not initialized');
|
|
103
|
+
}
|
|
104
|
+
const allOperators = await this.configManager.getAvailableCharacterIds();
|
|
105
|
+
const otherAssignments = await this.dataStore.getOtherEntries();
|
|
106
|
+
const busyCharacters = otherAssignments
|
|
107
|
+
? Object.values(otherAssignments).map(session => session.characterId)
|
|
108
|
+
: [];
|
|
109
|
+
const availableCharacters = allOperators.filter(op => !busyCharacters.includes(op));
|
|
110
|
+
return {
|
|
111
|
+
available: availableCharacters,
|
|
112
|
+
busy: busyCharacters,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* オペレータを予約
|
|
117
|
+
*/
|
|
118
|
+
async reserveOperator(characterId, styleId, styleName) {
|
|
119
|
+
try {
|
|
120
|
+
await this.dataStore.store({ characterId, styleId, styleName });
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
throw new Error(`オペレータ ${characterId} の予約に失敗しました: ${error.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* オペレータを返却
|
|
129
|
+
* オペレータが割り当てられていない場合も正常として扱う(時間切れ自動解放のケースがあるため)
|
|
130
|
+
*/
|
|
131
|
+
async releaseOperator() {
|
|
132
|
+
const operatorSession = await this.getCurrentOperatorSession();
|
|
133
|
+
if (!operatorSession) {
|
|
134
|
+
// オペレータが割り当てられていない場合も正常として扱う
|
|
135
|
+
return {
|
|
136
|
+
wasAssigned: false,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const characterId = operatorSession.characterId;
|
|
140
|
+
await this.dataStore.remove();
|
|
141
|
+
// お別れの挨拶情報を取得
|
|
142
|
+
let character = null;
|
|
143
|
+
try {
|
|
144
|
+
character = await this.characterInfoService.getCharacterInfo(characterId);
|
|
145
|
+
if (!character) {
|
|
146
|
+
character = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
character = null;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
characterId,
|
|
154
|
+
characterName: character?.speaker?.speakerName || characterId,
|
|
155
|
+
farewell: character?.farewell || '',
|
|
156
|
+
wasAssigned: true,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* 全ての利用状況をクリア
|
|
161
|
+
*/
|
|
162
|
+
async clearAllOperators() {
|
|
163
|
+
await this.dataStore.clear();
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* 現在のセッションに割り当てられたオペレータIDを取得
|
|
168
|
+
*/
|
|
169
|
+
async getCurrentOperatorId() {
|
|
170
|
+
const session = await this.dataStore.restore();
|
|
171
|
+
return session ? session.characterId : null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 現在のセッション情報を取得
|
|
175
|
+
*/
|
|
176
|
+
async getCurrentOperatorSession() {
|
|
177
|
+
return this.dataStore.restore();
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 現在のセッションのオペレータが有効かチェック
|
|
181
|
+
*/
|
|
182
|
+
async validateCurrentOperatorSession() {
|
|
183
|
+
const currentOperatorId = await this.getCurrentOperatorId();
|
|
184
|
+
return currentOperatorId !== null;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* 指定されたキャラクターが利用中かチェック(全セッション対象)
|
|
188
|
+
*/
|
|
189
|
+
async isOperatorBusy(characterId) {
|
|
190
|
+
const result = await this.getAvailableOperators();
|
|
191
|
+
return !result.available.includes(characterId);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* 現在のオペレータをサイレントで解放
|
|
195
|
+
*/
|
|
196
|
+
async silentReleaseCurrentOperator() {
|
|
197
|
+
try {
|
|
198
|
+
const currentSession = await this.getCurrentOperatorSession();
|
|
199
|
+
if (!currentSession) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
await this.dataStore.remove();
|
|
203
|
+
return currentSession.characterId;
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* ランダムオペレータ選択と詳細情報付きアサイン
|
|
211
|
+
*/
|
|
212
|
+
async assignRandomOperator(style = null) {
|
|
213
|
+
const result = await this.getAvailableOperators();
|
|
214
|
+
if (result.available.length === 0) {
|
|
215
|
+
throw new Error('利用可能なオペレータがありません');
|
|
216
|
+
}
|
|
217
|
+
// ランダム選択
|
|
218
|
+
const selectedCharacter = result.available[Math.floor(Math.random() * result.available.length)];
|
|
219
|
+
return await this.assignSpecificOperator(selectedCharacter, style);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 指定されたオペレータを詳細情報付きでアサイン
|
|
223
|
+
*/
|
|
224
|
+
async assignSpecificOperator(specifiedCharacter, style = null) {
|
|
225
|
+
if (!specifiedCharacter) {
|
|
226
|
+
throw new Error('キャラクターIDを指定してください');
|
|
227
|
+
}
|
|
228
|
+
if (!this.configManager) {
|
|
229
|
+
throw new Error('Manager is not initialized');
|
|
230
|
+
}
|
|
231
|
+
// キャラクター情報を取得
|
|
232
|
+
const character = await this.characterInfoService.getOperatorCharacterInfo(specifiedCharacter);
|
|
233
|
+
if (!character) {
|
|
234
|
+
throw new Error(`オペレータ '${specifiedCharacter}' は存在しないか無効です`);
|
|
235
|
+
}
|
|
236
|
+
// 既存のオペレータがいる場合は自動的にリリース(交代処理)
|
|
237
|
+
const currentCharacterId = await this.getCurrentOperatorId();
|
|
238
|
+
if (currentCharacterId) {
|
|
239
|
+
// 同じキャラクターが指定された場合は何もしない
|
|
240
|
+
if (currentCharacterId === specifiedCharacter) {
|
|
241
|
+
const selectedStyle = this.characterInfoService.selectStyle(character, style);
|
|
242
|
+
return {
|
|
243
|
+
characterId: specifiedCharacter,
|
|
244
|
+
characterName: character.speaker?.speakerName || character.characterId,
|
|
245
|
+
currentStyle: {
|
|
246
|
+
styleId: selectedStyle.styleId.toString(),
|
|
247
|
+
styleName: selectedStyle.styleName,
|
|
248
|
+
personality: character.personality,
|
|
249
|
+
speakingStyle: character.speakingStyle,
|
|
250
|
+
},
|
|
251
|
+
speakerConfig: {
|
|
252
|
+
speakerId: character.speaker?.speakerId || '',
|
|
253
|
+
styleId: selectedStyle.styleId,
|
|
254
|
+
},
|
|
255
|
+
message: `現在のオペレータ: ${character.speaker?.speakerName || character.characterId} (${specifiedCharacter})`,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
// 現在のオペレータをサイレントリリース
|
|
259
|
+
await this.silentReleaseCurrentOperator();
|
|
260
|
+
}
|
|
261
|
+
// 仕様書準拠: 統一された時間切れクリーンアップ付きで他セッション利用状況をチェック
|
|
262
|
+
if (await this.isOperatorBusy(specifiedCharacter)) {
|
|
263
|
+
throw new Error(`オペレータ '${specifiedCharacter}' は既に他のセッションで利用中です`);
|
|
264
|
+
}
|
|
265
|
+
// スタイルを選択
|
|
266
|
+
const selectedStyle = this.characterInfoService.selectStyle(character, style);
|
|
267
|
+
// キャラクターを予約(スタイル情報も含めて)
|
|
268
|
+
await this.reserveOperator(specifiedCharacter, selectedStyle.styleId, selectedStyle.styleName);
|
|
269
|
+
return {
|
|
270
|
+
characterId: specifiedCharacter,
|
|
271
|
+
characterName: character.speaker?.speakerName || character.characterId,
|
|
272
|
+
currentStyle: {
|
|
273
|
+
styleId: selectedStyle.styleId.toString(),
|
|
274
|
+
styleName: selectedStyle.styleName,
|
|
275
|
+
personality: character.personality,
|
|
276
|
+
speakingStyle: character.speakingStyle,
|
|
277
|
+
},
|
|
278
|
+
speakerConfig: {
|
|
279
|
+
speakerId: character.speaker?.speakerId || '',
|
|
280
|
+
styleId: selectedStyle.styleId,
|
|
281
|
+
},
|
|
282
|
+
greeting: character.greeting || '',
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* 現在のオペレータ情報表示
|
|
287
|
+
* 仕様書準拠: getCurrentOperatorId()の自動時間切れ処理に依存し、統一された検証ロジックを実装
|
|
288
|
+
*/
|
|
289
|
+
async showCurrentOperator() {
|
|
290
|
+
if (!this.configManager) {
|
|
291
|
+
throw new Error('Manager is not initialized');
|
|
292
|
+
}
|
|
293
|
+
// 仕様書準拠: getCurrentOperatorSession()が時間切れチェックと自動解放を実行
|
|
294
|
+
const operatorSession = await this.getCurrentOperatorSession();
|
|
295
|
+
if (!operatorSession) {
|
|
296
|
+
return {
|
|
297
|
+
message: 'オペレータは割り当てられていません',
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
const { characterId, styleId, styleName } = operatorSession;
|
|
301
|
+
let character;
|
|
302
|
+
try {
|
|
303
|
+
character = await this.characterInfoService.getCharacterInfo(characterId);
|
|
304
|
+
if (!character) {
|
|
305
|
+
return {
|
|
306
|
+
characterId,
|
|
307
|
+
message: `現在のオペレータ: ${characterId} (キャラクター情報なし)`,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return {
|
|
313
|
+
characterId,
|
|
314
|
+
message: `現在のオペレータ: ${characterId} (キャラクター情報なし)`,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
// 保存されたスタイル情報を使用するか、デフォルトを選択
|
|
318
|
+
let selectedStyle;
|
|
319
|
+
if (styleId !== undefined && styleName) {
|
|
320
|
+
// 保存されたスタイルを検索
|
|
321
|
+
const styles = character.speaker?.styles || [];
|
|
322
|
+
selectedStyle =
|
|
323
|
+
styles.find(s => s.styleId === styleId) || this.characterInfoService.selectStyle(character);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
selectedStyle = this.characterInfoService.selectStyle(character);
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
characterId,
|
|
330
|
+
characterName: character.speaker?.speakerName || character.characterId,
|
|
331
|
+
currentStyle: {
|
|
332
|
+
styleId: selectedStyle.styleId.toString(),
|
|
333
|
+
styleName: selectedStyle.styleName,
|
|
334
|
+
personality: character.personality,
|
|
335
|
+
speakingStyle: character.speakingStyle,
|
|
336
|
+
},
|
|
337
|
+
message: `現在のオペレータ: ${character.speaker?.speakerName || character.characterId} (${characterId}) - ${selectedStyle.styleName}`,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* オペレータ予約のタイムアウトを延長
|
|
342
|
+
* Issue #58: sayコマンド実行時の動的タイムアウト延長
|
|
343
|
+
*/
|
|
344
|
+
async refreshOperatorReservation() {
|
|
345
|
+
const operatorSession = await this.getCurrentOperatorSession();
|
|
346
|
+
if (!operatorSession) {
|
|
347
|
+
return false; // オペレータが割り当てられていない
|
|
348
|
+
}
|
|
349
|
+
return this.dataStore.refresh();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
export default OperatorManager;
|
|
353
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ConfigManager } from '../operator/config-manager.js';
|
|
2
|
+
export declare class TerminalBackground {
|
|
3
|
+
private currentCharacterId;
|
|
4
|
+
private configManager;
|
|
5
|
+
private termBg;
|
|
6
|
+
private sessionId;
|
|
7
|
+
constructor(configManager: ConfigManager, sessionId?: string);
|
|
8
|
+
/**
|
|
9
|
+
* セッションIDを取得(OperatorManagerと同じロジック)
|
|
10
|
+
*/
|
|
11
|
+
private getSessionId;
|
|
12
|
+
/**
|
|
13
|
+
* 背景画像が有効かチェック
|
|
14
|
+
*/
|
|
15
|
+
isEnabled(): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* キャラクター切り替え時の背景更新
|
|
18
|
+
*/
|
|
19
|
+
switchCharacter(characterId: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* 背景画像を設定
|
|
22
|
+
*/
|
|
23
|
+
private setBackgroundImage;
|
|
24
|
+
/**
|
|
25
|
+
* APIからオペレータ画像を取得
|
|
26
|
+
*/
|
|
27
|
+
private fetchOperatorImageFromAPI;
|
|
28
|
+
/**
|
|
29
|
+
* 背景をクリア
|
|
30
|
+
*/
|
|
31
|
+
clearBackground(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* 現在のキャラクターID取得
|
|
34
|
+
*/
|
|
35
|
+
getCurrentCharacter(): string | null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=terminal-background.d.ts.map
|