@charivo/realtime-core 0.0.1 โ 0.1.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 +30 -234
- package/dist/index.d.mts +5 -37
- package/dist/index.d.ts +5 -37
- package/dist/index.js +3 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -1,252 +1,48 @@
|
|
|
1
1
|
# @charivo/realtime-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Realtime session manager and typed OpenAI Realtime helpers for Charivo.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
- ๐ **Session Management** - Start/stop Realtime API sessions
|
|
8
|
-
- ๐ก **Event Relay** - Bridge between Realtime client and Charivo event system
|
|
9
|
-
- ๐ **Lip-Sync Support** - Real-time RMS values for character mouth animation
|
|
10
|
-
- ๐ **Client Agnostic** - Works with any Realtime client implementation
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
5
|
+
## Install
|
|
13
6
|
|
|
14
7
|
```bash
|
|
15
|
-
pnpm add @charivo/realtime-core
|
|
8
|
+
pnpm add @charivo/realtime-core
|
|
16
9
|
```
|
|
17
10
|
|
|
18
11
|
## Usage
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
```ts
|
|
14
|
+
import {
|
|
15
|
+
createRealtimeManager,
|
|
16
|
+
getEmotionSessionConfig,
|
|
17
|
+
} from "@charivo/realtime-core";
|
|
24
18
|
import { createOpenAIRealtimeClient } from "@charivo/realtime-client-openai";
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
apiEndpoint: "/api/realtime" // Your WebRTC handshake endpoint
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Wrap with RealtimeManager for state management
|
|
32
|
-
const realtimeManager = createRealtimeManager(client);
|
|
33
|
-
|
|
34
|
-
// Start Realtime session
|
|
35
|
-
await realtimeManager.startSession({
|
|
36
|
-
model: "gpt-4o-realtime-preview-2024-12-17",
|
|
37
|
-
voice: "verse"
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Send text message
|
|
41
|
-
await realtimeManager.sendMessage("Hello!");
|
|
42
|
-
|
|
43
|
-
// Stop session when done
|
|
44
|
-
await realtimeManager.stopSession();
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### With Charivo Integration
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import { Charivo } from "@charivo/core";
|
|
51
|
-
import { createRealtimeManager } from "@charivo/realtime-core";
|
|
52
|
-
import { createOpenAIRealtimeClient } from "@charivo/realtime-client-openai";
|
|
53
|
-
|
|
54
|
-
const charivo = new Charivo();
|
|
55
|
-
|
|
56
|
-
// Create and attach Realtime manager
|
|
57
|
-
const client = createOpenAIRealtimeClient({
|
|
58
|
-
apiEndpoint: "/api/realtime"
|
|
59
|
-
});
|
|
60
|
-
const realtimeManager = createRealtimeManager(client);
|
|
61
|
-
charivo.attachRealtime(realtimeManager);
|
|
62
|
-
|
|
63
|
-
// Start session
|
|
64
|
-
await realtimeManager.startSession({
|
|
65
|
-
model: "gpt-4o-realtime-preview-2024-12-17",
|
|
66
|
-
voice: "verse"
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Enable lip-sync on renderer
|
|
70
|
-
charivo.emit("tts:audio:start", { audioElement: new Audio() });
|
|
71
|
-
|
|
72
|
-
// Listen to events
|
|
73
|
-
charivo.on("realtime:text:delta", ({ text }) => {
|
|
74
|
-
console.log("Streaming text:", text);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
charivo.on("tts:lipsync:update", ({ rms }) => {
|
|
78
|
-
console.log("Lip-sync RMS:", rms);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Cleanup
|
|
82
|
-
await realtimeManager.stopSession();
|
|
83
|
-
charivo.emit("tts:audio:end", {});
|
|
84
|
-
charivo.detachRealtime();
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Custom Realtime Client
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
90
|
-
import { RealtimeClient } from "@charivo/realtime-core";
|
|
91
|
-
import { createRealtimeManager } from "@charivo/realtime-core";
|
|
92
|
-
|
|
93
|
-
class MyRealtimeClient implements RealtimeClient {
|
|
94
|
-
async connect(): Promise<void> {
|
|
95
|
-
// Connect to your Realtime service
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async disconnect(): Promise<void> {
|
|
99
|
-
// Disconnect
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async sendText(text: string): Promise<void> {
|
|
103
|
-
// Send text message
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async sendAudio(audio: ArrayBuffer): Promise<void> {
|
|
107
|
-
// Send audio chunk
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
onTextDelta(callback: (text: string) => void): void {
|
|
111
|
-
// Register text streaming callback
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
onAudioDelta(callback: (base64Audio: string) => void): void {
|
|
115
|
-
// Register audio streaming callback
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
onLipSyncUpdate?(callback: (rms: number) => void): void {
|
|
119
|
-
// Optional: Register direct RMS callback for WebRTC clients
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
onAudioDone(callback: () => void): void {
|
|
123
|
-
// Register audio end callback
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
onError(callback: (error: Error) => void): void {
|
|
127
|
-
// Register error callback
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const realtimeManager = createRealtimeManager(new MyRealtimeClient());
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## API Reference
|
|
135
|
-
|
|
136
|
-
### `RealtimeManager`
|
|
137
|
-
|
|
138
|
-
#### Methods
|
|
139
|
-
|
|
140
|
-
##### `setEventEmitter(eventEmitter)`
|
|
141
|
-
|
|
142
|
-
Connect to Charivo's event system.
|
|
143
|
-
|
|
144
|
-
**Parameters:**
|
|
145
|
-
- `eventEmitter` - Object with `emit(event, data)` method
|
|
20
|
+
const client = createOpenAIRealtimeClient({ apiEndpoint: "/api/realtime" });
|
|
21
|
+
const manager = createRealtimeManager(client);
|
|
146
22
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
- `config.voice` - Voice name (e.g., "verse", "alloy", "echo")
|
|
154
|
-
|
|
155
|
-
**Returns:** `Promise<void>`
|
|
156
|
-
|
|
157
|
-
##### `stopSession()`
|
|
158
|
-
|
|
159
|
-
Stop the current Realtime session.
|
|
160
|
-
|
|
161
|
-
**Returns:** `Promise<void>`
|
|
162
|
-
|
|
163
|
-
##### `sendMessage(text)`
|
|
164
|
-
|
|
165
|
-
Send a text message to the Realtime API.
|
|
166
|
-
|
|
167
|
-
**Parameters:**
|
|
168
|
-
- `text` - Message text
|
|
169
|
-
|
|
170
|
-
**Returns:** `Promise<void>`
|
|
171
|
-
|
|
172
|
-
##### `sendAudioChunk(audio)`
|
|
173
|
-
|
|
174
|
-
Send an audio chunk (user's voice).
|
|
175
|
-
|
|
176
|
-
**Parameters:**
|
|
177
|
-
- `audio` - Audio data as ArrayBuffer
|
|
178
|
-
|
|
179
|
-
**Returns:** `Promise<void>`
|
|
180
|
-
|
|
181
|
-
### Events
|
|
182
|
-
|
|
183
|
-
When integrated with Charivo, the following events are emitted:
|
|
184
|
-
|
|
185
|
-
#### `realtime:text:delta`
|
|
186
|
-
|
|
187
|
-
Streamed text response from the AI.
|
|
188
|
-
|
|
189
|
-
**Payload:**
|
|
190
|
-
```typescript
|
|
191
|
-
{ text: string }
|
|
23
|
+
await manager.startSession(
|
|
24
|
+
getEmotionSessionConfig({
|
|
25
|
+
model: "gpt-realtime-mini",
|
|
26
|
+
voice: "marin",
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
192
29
|
```
|
|
193
30
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Real-time lip-sync RMS values (0.0 - 1.0).
|
|
197
|
-
|
|
198
|
-
**Payload:**
|
|
199
|
-
```typescript
|
|
200
|
-
{ rms: number }
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### `tts:audio:end`
|
|
204
|
-
|
|
205
|
-
Audio playback finished.
|
|
206
|
-
|
|
207
|
-
**Payload:**
|
|
208
|
-
```typescript
|
|
209
|
-
{}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
#### `realtime:error`
|
|
213
|
-
|
|
214
|
-
Error occurred during Realtime session.
|
|
215
|
-
|
|
216
|
-
**Payload:**
|
|
217
|
-
```typescript
|
|
218
|
-
{ error: Error }
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
## Architecture
|
|
222
|
-
|
|
223
|
-
The Realtime Manager follows Charivo's **Manager Pattern**:
|
|
224
|
-
|
|
225
|
-
- **Stateful Manager** (`RealtimeManager`) - Manages session lifecycle and events
|
|
226
|
-
- **Stateless Client** (e.g., `OpenAIRealtimeClient`) - Handles WebRTC/WebSocket connection
|
|
227
|
-
|
|
228
|
-
```
|
|
229
|
-
โโโโโโโโโโโโโโโโโโโโโโโ
|
|
230
|
-
โ RealtimeManager โ โโ Stateful (session, events)
|
|
231
|
-
โโโโโโโโโโโโฌโโโโโโโโโโโ
|
|
232
|
-
โผ
|
|
233
|
-
โโโโโโโโโโโโโโโโโโโโโโโ
|
|
234
|
-
โ RealtimeClient โ โโ Stateless (WebRTC/WS)
|
|
235
|
-
โโโโโโโโโโโโโโโโโโโโโโโ
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
### Why This Design?
|
|
239
|
-
|
|
240
|
-
- **Separation of Concerns**: Manager handles state, client handles protocol
|
|
241
|
-
- **Testability**: Easy to mock clients for testing
|
|
242
|
-
- **Flexibility**: Swap clients without changing app code
|
|
243
|
-
- **Reusability**: Same client can be used in different contexts
|
|
31
|
+
## Exports
|
|
244
32
|
|
|
245
|
-
|
|
33
|
+
- `createRealtimeManager(client)`
|
|
34
|
+
- `getEmotionSessionConfig(overrides?)`
|
|
35
|
+
- `setEmotionTool`
|
|
36
|
+
- `DEFAULT_EMOTION_INSTRUCTIONS`
|
|
37
|
+
- realtime-related types re-exported from `@charivo/core`
|
|
246
38
|
|
|
247
|
-
|
|
248
|
-
- [@charivo/core](../core) - Core types and interfaces
|
|
39
|
+
## Event Bridge
|
|
249
40
|
|
|
250
|
-
|
|
41
|
+
When connected to the Charivo event bus, the manager relays:
|
|
251
42
|
|
|
252
|
-
|
|
43
|
+
- `realtime:text:delta`
|
|
44
|
+
- `realtime:emotion`
|
|
45
|
+
- `realtime:error`
|
|
46
|
+
- `tts:lipsync:update`
|
|
47
|
+
- `tts:audio:start`
|
|
48
|
+
- `tts:audio:end`
|
package/dist/index.d.mts
CHANGED
|
@@ -1,27 +1,6 @@
|
|
|
1
|
-
import { Emotion } from '@charivo/core';
|
|
1
|
+
import { RealtimeSessionConfig, RealtimeManager, CharivoEventEmitter, RealtimeTool, Emotion } from '@charivo/core';
|
|
2
|
+
export { CharivoEventEmitter, RealtimeManager, RealtimeSessionConfig, RealtimeTool } from '@charivo/core';
|
|
2
3
|
|
|
3
|
-
/**
|
|
4
|
-
* Realtime API Types
|
|
5
|
-
*/
|
|
6
|
-
interface RealtimeTool {
|
|
7
|
-
type: "function";
|
|
8
|
-
name: string;
|
|
9
|
-
description: string;
|
|
10
|
-
parameters: {
|
|
11
|
-
type: "object";
|
|
12
|
-
properties: Record<string, any>;
|
|
13
|
-
required?: string[];
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
interface RealtimeSessionConfig {
|
|
17
|
-
voice?: string;
|
|
18
|
-
model?: string;
|
|
19
|
-
instructions?: string;
|
|
20
|
-
temperature?: number;
|
|
21
|
-
maxTokens?: number;
|
|
22
|
-
tools?: RealtimeTool[];
|
|
23
|
-
tool_choice?: "auto" | "none" | "required";
|
|
24
|
-
}
|
|
25
4
|
interface RealtimeClient {
|
|
26
5
|
connect(config?: RealtimeSessionConfig): Promise<void>;
|
|
27
6
|
disconnect(): Promise<void>;
|
|
@@ -31,18 +10,9 @@ interface RealtimeClient {
|
|
|
31
10
|
onAudioDelta(callback: (base64Audio: string) => void): void;
|
|
32
11
|
onLipSyncUpdate?(callback: (rms: number) => void): void;
|
|
33
12
|
onAudioDone(callback: () => void): void;
|
|
34
|
-
onToolCall?(callback: (name: string, args:
|
|
13
|
+
onToolCall?(callback: (name: string, args: Record<string, unknown>) => void): void;
|
|
35
14
|
onError(callback: (error: Error) => void): void;
|
|
36
15
|
}
|
|
37
|
-
interface RealtimeManager {
|
|
38
|
-
startSession(config: RealtimeSessionConfig): Promise<void>;
|
|
39
|
-
stopSession(): Promise<void>;
|
|
40
|
-
sendMessage(text: string): Promise<void>;
|
|
41
|
-
sendAudioChunk(audio: ArrayBuffer): Promise<void>;
|
|
42
|
-
setEventEmitter(eventEmitter: {
|
|
43
|
-
emit: (event: string, data: any) => void;
|
|
44
|
-
}): void;
|
|
45
|
-
}
|
|
46
16
|
|
|
47
17
|
/**
|
|
48
18
|
* Realtime Manager - Realtime API ์ธ์
๊ด๋ฆฌ
|
|
@@ -64,9 +34,7 @@ declare class RealtimeManagerImpl implements RealtimeManager {
|
|
|
64
34
|
/**
|
|
65
35
|
* ์ด๋ฒคํธ ๋ฐ์ ์ ์ค์
|
|
66
36
|
*/
|
|
67
|
-
setEventEmitter(eventEmitter:
|
|
68
|
-
emit: (event: string, data: any) => void;
|
|
69
|
-
}): void;
|
|
37
|
+
setEventEmitter(eventEmitter: CharivoEventEmitter): void;
|
|
70
38
|
/**
|
|
71
39
|
* Realtime ์ธ์
์์
|
|
72
40
|
*/
|
|
@@ -131,4 +99,4 @@ declare function getEmotionSessionConfig(overrides?: RealtimeSessionConfig): {
|
|
|
131
99
|
tool_choice: "auto" | "none" | "required";
|
|
132
100
|
};
|
|
133
101
|
|
|
134
|
-
export { DEFAULT_EMOTION_INSTRUCTIONS, type EmotionArgs, type RealtimeClient,
|
|
102
|
+
export { DEFAULT_EMOTION_INSTRUCTIONS, type EmotionArgs, type RealtimeClient, RealtimeManagerImpl, createRealtimeManager, getEmotionSessionConfig, setEmotionTool };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,6 @@
|
|
|
1
|
-
import { Emotion } from '@charivo/core';
|
|
1
|
+
import { RealtimeSessionConfig, RealtimeManager, CharivoEventEmitter, RealtimeTool, Emotion } from '@charivo/core';
|
|
2
|
+
export { CharivoEventEmitter, RealtimeManager, RealtimeSessionConfig, RealtimeTool } from '@charivo/core';
|
|
2
3
|
|
|
3
|
-
/**
|
|
4
|
-
* Realtime API Types
|
|
5
|
-
*/
|
|
6
|
-
interface RealtimeTool {
|
|
7
|
-
type: "function";
|
|
8
|
-
name: string;
|
|
9
|
-
description: string;
|
|
10
|
-
parameters: {
|
|
11
|
-
type: "object";
|
|
12
|
-
properties: Record<string, any>;
|
|
13
|
-
required?: string[];
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
interface RealtimeSessionConfig {
|
|
17
|
-
voice?: string;
|
|
18
|
-
model?: string;
|
|
19
|
-
instructions?: string;
|
|
20
|
-
temperature?: number;
|
|
21
|
-
maxTokens?: number;
|
|
22
|
-
tools?: RealtimeTool[];
|
|
23
|
-
tool_choice?: "auto" | "none" | "required";
|
|
24
|
-
}
|
|
25
4
|
interface RealtimeClient {
|
|
26
5
|
connect(config?: RealtimeSessionConfig): Promise<void>;
|
|
27
6
|
disconnect(): Promise<void>;
|
|
@@ -31,18 +10,9 @@ interface RealtimeClient {
|
|
|
31
10
|
onAudioDelta(callback: (base64Audio: string) => void): void;
|
|
32
11
|
onLipSyncUpdate?(callback: (rms: number) => void): void;
|
|
33
12
|
onAudioDone(callback: () => void): void;
|
|
34
|
-
onToolCall?(callback: (name: string, args:
|
|
13
|
+
onToolCall?(callback: (name: string, args: Record<string, unknown>) => void): void;
|
|
35
14
|
onError(callback: (error: Error) => void): void;
|
|
36
15
|
}
|
|
37
|
-
interface RealtimeManager {
|
|
38
|
-
startSession(config: RealtimeSessionConfig): Promise<void>;
|
|
39
|
-
stopSession(): Promise<void>;
|
|
40
|
-
sendMessage(text: string): Promise<void>;
|
|
41
|
-
sendAudioChunk(audio: ArrayBuffer): Promise<void>;
|
|
42
|
-
setEventEmitter(eventEmitter: {
|
|
43
|
-
emit: (event: string, data: any) => void;
|
|
44
|
-
}): void;
|
|
45
|
-
}
|
|
46
16
|
|
|
47
17
|
/**
|
|
48
18
|
* Realtime Manager - Realtime API ์ธ์
๊ด๋ฆฌ
|
|
@@ -64,9 +34,7 @@ declare class RealtimeManagerImpl implements RealtimeManager {
|
|
|
64
34
|
/**
|
|
65
35
|
* ์ด๋ฒคํธ ๋ฐ์ ์ ์ค์
|
|
66
36
|
*/
|
|
67
|
-
setEventEmitter(eventEmitter:
|
|
68
|
-
emit: (event: string, data: any) => void;
|
|
69
|
-
}): void;
|
|
37
|
+
setEventEmitter(eventEmitter: CharivoEventEmitter): void;
|
|
70
38
|
/**
|
|
71
39
|
* Realtime ์ธ์
์์
|
|
72
40
|
*/
|
|
@@ -131,4 +99,4 @@ declare function getEmotionSessionConfig(overrides?: RealtimeSessionConfig): {
|
|
|
131
99
|
tool_choice: "auto" | "none" | "required";
|
|
132
100
|
};
|
|
133
101
|
|
|
134
|
-
export { DEFAULT_EMOTION_INSTRUCTIONS, type EmotionArgs, type RealtimeClient,
|
|
102
|
+
export { DEFAULT_EMOTION_INSTRUCTIONS, type EmotionArgs, type RealtimeClient, RealtimeManagerImpl, createRealtimeManager, getEmotionSessionConfig, setEmotionTool };
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,6 @@ var RealtimeManagerImpl = class {
|
|
|
17
17
|
*/
|
|
18
18
|
setEventEmitter(eventEmitter) {
|
|
19
19
|
this.eventEmitter = eventEmitter;
|
|
20
|
-
console.log("\u{1F517} Realtime Manager: Event emitter connected");
|
|
21
20
|
}
|
|
22
21
|
/**
|
|
23
22
|
* Realtime ์ธ์
์์
|
|
@@ -26,21 +25,17 @@ var RealtimeManagerImpl = class {
|
|
|
26
25
|
if (this.isSessionActive) {
|
|
27
26
|
throw new Error("Realtime session already active");
|
|
28
27
|
}
|
|
29
|
-
console.log("\u{1F680} Starting Realtime session with config:", config);
|
|
30
28
|
await this.client.connect(config);
|
|
31
29
|
this.isSessionActive = true;
|
|
32
|
-
console.log("\u2705 Realtime session started");
|
|
33
30
|
}
|
|
34
31
|
/**
|
|
35
32
|
* Realtime ์ธ์
์ข
๋ฃ
|
|
36
33
|
*/
|
|
37
34
|
async stopSession() {
|
|
38
35
|
if (!this.isSessionActive) return;
|
|
39
|
-
console.log("\u{1F6D1} Stopping Realtime session");
|
|
40
36
|
await this.client.disconnect();
|
|
41
37
|
this.emitAudioEnd();
|
|
42
38
|
this.isSessionActive = false;
|
|
43
|
-
console.log("\u2705 Realtime session stopped");
|
|
44
39
|
}
|
|
45
40
|
/**
|
|
46
41
|
* ํ
์คํธ ๋ฉ์์ง ์ ์ก
|
|
@@ -90,7 +85,6 @@ var RealtimeManagerImpl = class {
|
|
|
90
85
|
});
|
|
91
86
|
}
|
|
92
87
|
this.client.onError((error) => {
|
|
93
|
-
console.error("Realtime client error:", error);
|
|
94
88
|
this.emitAudioEnd();
|
|
95
89
|
this.eventEmitter?.emit("realtime:error", { error });
|
|
96
90
|
});
|
|
@@ -99,10 +93,10 @@ var RealtimeManagerImpl = class {
|
|
|
99
93
|
* Tool call ์ฒ๋ฆฌ
|
|
100
94
|
*/
|
|
101
95
|
handleToolCall(name, args) {
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
const emotion = args.emotion;
|
|
97
|
+
if (name === "setEmotion" && typeof emotion === "string") {
|
|
104
98
|
this.eventEmitter?.emit("realtime:emotion", {
|
|
105
|
-
emotion
|
|
99
|
+
emotion
|
|
106
100
|
});
|
|
107
101
|
}
|
|
108
102
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-manager.ts","../src/tools.ts"],"names":["Emotion"],"mappings":";;;;;AAiBO,IAAM,sBAAN,MAAsD;AAAA,EACnD,MAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA,GAAkB,KAAA;AAAA,EAClB,qBAAA,GAAwB,KAAA;AAAA,EAEhC,YAAY,MAAA,EAAwB;AAClC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,oBAAA,EAAqB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,YAAA,EAEP;AACP,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,OAAA,CAAQ,IAAI,qDAA8C,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,MAAA,EAA8C;AAC/D,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,IACnD;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAI,oDAA6C,MAAM,CAAA;AAG/D,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA;AAEhC,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAEvB,IAAA,OAAA,CAAQ,IAAI,iCAA4B,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,GAA6B;AACjC,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AAE3B,IAAA,OAAA,CAAQ,IAAI,qCAA8B,CAAA;AAG1C,IAAA,MAAM,IAAA,CAAK,OAAO,UAAA,EAAW;AAC7B,IAAA,IAAA,CAAK,YAAA,EAAa;AAElB,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAEvB,IAAA,OAAA,CAAQ,IAAI,iCAA4B,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,IAAA,EAA6B;AAC7C,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AACzB,MAAA,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAAA,IAC/C;AAEA,IAAA,IAAA,CAAK,cAAA,EAAe;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA;AAAA,IACjC,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,YAAA,EAAa;AAClB,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,KAAA,EAAmC;AACtD,IAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AACzB,MAAA,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAA,GAA6B;AAEnC,IAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,CAAC,IAAA,KAAiB;AACxC,MAAA,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,qBAAA,EAAuB,EAAE,MAAM,CAAA;AAAA,IACzD,CAAC,CAAA;AAGD,IAAA,IAAI,IAAA,CAAK,OAAO,eAAA,EAAiB;AAC/B,MAAA,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,CAAC,GAAA,KAAgB;AAC3C,QAAA,IAAI,GAAA,GAAM,IAAA,IAAS,CAAC,IAAA,CAAK,qBAAA,EAAuB;AAC9C,UAAA,IAAA,CAAK,cAAA,EAAe;AAAA,QACtB;AACA,QAAA,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,oBAAA,EAAsB,EAAE,KAAK,CAAA;AAAA,MACvD,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,IAAA,CAAK,MAAA,CAAO,YAAY,MAAM;AAC5B,MAAA,IAAA,CAAK,YAAA,EAAa;AAAA,IACpB,CAAC,CAAA;AAGD,IAAA,IAAI,IAAA,CAAK,OAAO,UAAA,EAAY;AAC1B,MAAA,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,CAAC,IAAA,EAAc,IAAA,KAAc;AAClD,QAAA,IAAA,CAAK,cAAA,CAAe,MAAM,IAAI,CAAA;AAAA,MAChC,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAiB;AACpC,MAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,KAAK,CAAA;AAC7C,MAAA,IAAA,CAAK,YAAA,EAAa;AAClB,MAAA,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,gBAAA,EAAkB,EAAE,OAAO,CAAA;AAAA,IACrD,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAA,CAAe,MAAc,IAAA,EAAiB;AACpD,IAAA,IAAI,SAAS,YAAA,EAAc;AACzB,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oCAAA,CAAA,EAAiC,IAAA,CAAK,OAAO,CAAA;AAEzD,MAAA,IAAA,CAAK,YAAA,EAAc,KAAK,kBAAA,EAAoB;AAAA,QAC1C,SAAS,IAAA,CAAK;AAAA,OACf,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAI,KAAK,qBAAA,EAAuB;AAC9B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,qBAAA,GAAwB,IAAA;AAC7B,IAAA,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,iBAAA,EAAmB,EAAE,CAAA;AAAA,EAC/C;AAAA,EAEQ,YAAA,GAAqB;AAC3B,IAAA,IAAI,CAAC,KAAK,qBAAA,EAAuB;AAC/B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,qBAAA,GAAwB,KAAA;AAC7B,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,oBAAA,EAAsB,EAAE,GAAA,EAAK,GAAG,CAAA;AACxD,IAAA,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,eAAA,EAAiB,EAAE,CAAA;AAAA,EAC7C;AACF;AAKO,SAAS,sBACd,MAAA,EACkB;AAClB,EAAA,OAAO,IAAI,oBAAoB,MAAM,CAAA;AACvC;AC5KA,IAAM,cAAA,GAAiB,MAAA,CAAO,MAAA,CAAOA,YAAO,CAAA;AAOrC,IAAM,cAAA,GAA+B;AAAA,EAC1C,IAAA,EAAM,UAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,WAAA,EACE,2FAAA;AAAA,EACF,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,QAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,2BAAA;AAAA,QACb,IAAA,EAAM;AAAA;AACR,KACF;AAAA,IACA,QAAA,EAAU,CAAC,SAAS;AAAA;AAExB;AAYO,IAAM,4BAAA,GAA+B;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAK1C,IAAA;AAKK,SAAS,wBAAwB,SAAA,EAOtC;AACA,EAAA,MAAM,eAAA,GAAkB,SAAA,EAAW,KAAA,IAAS,EAAC;AAC7C,EAAA,MAAM,iBAAiB,eAAA,CAAgB,IAAA;AAAA,IACrC,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,UAAA,IAAc,IAAA,CAAK,SAAS,cAAA,CAAe;AAAA,GACrE;AACA,EAAA,MAAM,QAAQ,cAAA,GACV,eAAA,GACA,CAAC,cAAA,EAAgB,GAAG,eAAe,CAAA;AAEvC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,KAAA,EAAO,WAAW,KAAA,IAAS,mBAAA;AAAA,IAC3B,KAAA,EAAO;AAAA,MACL,MAAA,EAAQ;AAAA,QACN,KAAA,EAAO,WAAW,KAAA,IAAS;AAAA;AAC7B,KACF;AAAA,IACA,YAAA,EAAc,WAAW,YAAA,IAAgB,4BAAA;AAAA,IACzC,KAAA;AAAA,IACA,WAAA,EAAa,WAAW,WAAA,IAAe;AAAA,GACzC;AACF","file":"index.js","sourcesContent":["import {\n RealtimeClient,\n RealtimeManager as IRealtimeManager,\n RealtimeSessionConfig,\n} from \"./types\";\n\n/**\n * Realtime Manager - Realtime API ์ธ์
๊ด๋ฆฌ\n *\n * ์ญํ :\n * - Realtime ํด๋ผ์ด์ธํธ ๊ด๋ฆฌ (WebRTC)\n * - ๋ฆฝ์ฑํฌ ์ด๋ฒคํธ ์ค๊ณ\n * - ํ
์คํธ ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ\n *\n * Note: WebRTC ํด๋ผ์ด์ธํธ๋ ์ค๋์ค๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก\n * ์ด Manager๋ ์ด๋ฒคํธ ์ค๊ณ์ ์ง์คํฉ๋๋ค.\n */\nexport class RealtimeManagerImpl implements IRealtimeManager {\n private client: RealtimeClient;\n private eventEmitter?: { emit: (event: string, data: any) => void };\n private isSessionActive = false;\n private isAudioPlaybackActive = false;\n\n constructor(client: RealtimeClient) {\n this.client = client;\n this.setupClientListeners();\n }\n\n /**\n * ์ด๋ฒคํธ ๋ฐ์ ์ ์ค์ \n */\n setEventEmitter(eventEmitter: {\n emit: (event: string, data: any) => void;\n }): void {\n this.eventEmitter = eventEmitter;\n console.log(\"๐ Realtime Manager: Event emitter connected\");\n }\n\n /**\n * Realtime ์ธ์
์์\n */\n async startSession(config: RealtimeSessionConfig): Promise<void> {\n if (this.isSessionActive) {\n throw new Error(\"Realtime session already active\");\n }\n\n console.log(\"๐ Starting Realtime session with config:\", config);\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ\n await this.client.connect(config);\n\n this.isSessionActive = true;\n\n console.log(\"โ
Realtime session started\");\n }\n\n /**\n * Realtime ์ธ์
์ข
๋ฃ\n */\n async stopSession(): Promise<void> {\n if (!this.isSessionActive) return;\n\n console.log(\"๐ Stopping Realtime session\");\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ํด์ \n await this.client.disconnect();\n this.emitAudioEnd();\n\n this.isSessionActive = false;\n\n console.log(\"โ
Realtime session stopped\");\n }\n\n /**\n * ํ
์คํธ ๋ฉ์์ง ์ ์ก\n */\n async sendMessage(text: string): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n this.emitAudioStart();\n try {\n await this.client.sendText(text);\n } catch (error) {\n this.emitAudioEnd();\n throw error;\n }\n }\n\n /**\n * ์ค๋์ค ์ฒญํฌ ์ ์ก (์ฌ์ฉ์ ์์ฑ)\n */\n async sendAudioChunk(audio: ArrayBuffer): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n await this.client.sendAudio(audio);\n }\n\n /**\n * ํด๋ผ์ด์ธํธ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์ \n */\n private setupClientListeners(): void {\n // ํ
์คํธ ์คํธ๋ฆฌ๋ฐ\n this.client.onTextDelta((text: string) => {\n this.eventEmitter?.emit(\"realtime:text:delta\", { text });\n });\n\n // Direct RMS callback (for WebRTC clients)\n if (this.client.onLipSyncUpdate) {\n this.client.onLipSyncUpdate((rms: number) => {\n if (rms > 0.001 && !this.isAudioPlaybackActive) {\n this.emitAudioStart();\n }\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms });\n });\n }\n\n // ์ค๋์ค ์คํธ๋ฆฌ๋ฐ ์ข
๋ฃ\n this.client.onAudioDone(() => {\n this.emitAudioEnd();\n });\n\n // Tool call ์ฒ๋ฆฌ\n if (this.client.onToolCall) {\n this.client.onToolCall((name: string, args: any) => {\n this.handleToolCall(name, args);\n });\n }\n\n // ์๋ฌ ์ฒ๋ฆฌ\n this.client.onError((error: Error) => {\n console.error(\"Realtime client error:\", error);\n this.emitAudioEnd();\n this.eventEmitter?.emit(\"realtime:error\", { error });\n });\n }\n\n /**\n * Tool call ์ฒ๋ฆฌ\n */\n private handleToolCall(name: string, args: any): void {\n if (name === \"setEmotion\") {\n console.log(`๐ญ [Realtime] Emotion update:`, args.emotion);\n // Emit emotion event for RenderManager\n this.eventEmitter?.emit(\"realtime:emotion\", {\n emotion: args.emotion,\n });\n }\n }\n\n private emitAudioStart(): void {\n if (this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = true;\n this.eventEmitter?.emit(\"tts:audio:start\", {});\n }\n\n private emitAudioEnd(): void {\n if (!this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = false;\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms: 0 });\n this.eventEmitter?.emit(\"tts:audio:end\", {});\n }\n}\n\n/**\n * Realtime Manager ์์ฑ ํฌํผ ํจ์\n */\nexport function createRealtimeManager(\n client: RealtimeClient,\n): IRealtimeManager {\n return new RealtimeManagerImpl(client);\n}\n","import type { RealtimeSessionConfig, RealtimeTool } from \"./types\";\nimport { Emotion } from \"@charivo/core\";\n\n/**\n * Get emotion enum values for tool definition\n */\nconst EMOTION_VALUES = Object.values(Emotion);\n\n/**\n * setEmotion tool definition for OpenAI Realtime API\n *\n * This tool allows the LLM to update the Live2D character's emotion.\n */\nexport const setEmotionTool: RealtimeTool = {\n type: \"function\",\n name: \"setEmotion\",\n description:\n \"Update Live2D character emotion. Call this when the conversation mood or emotion changes.\",\n parameters: {\n type: \"object\",\n properties: {\n emotion: {\n type: \"string\",\n description: \"Emotion of the character.\",\n enum: EMOTION_VALUES,\n },\n },\n required: [\"emotion\"],\n },\n};\n\n/**\n * Emotion tool call arguments type\n */\nexport interface EmotionArgs {\n emotion: Emotion;\n}\n\n/**\n * Default instructions for character with emotion support\n */\nexport const DEFAULT_EMOTION_INSTRUCTIONS = `\nYou are a Live2D character with emotions and expressions.\nRespond naturally to the user's messages.\nWhen the conversation mood or emotion changes, call the 'setEmotion' tool to update your expression and motion.\nDo NOT mention the tool call in your response - just respond naturally and let the emotion show through your character.\n`.trim();\n\n/**\n * Get default Realtime session config with emotion support\n */\nexport function getEmotionSessionConfig(overrides?: RealtimeSessionConfig): {\n type: string;\n model: string;\n audio: { output: { voice: string } };\n instructions: string;\n tools: RealtimeTool[];\n tool_choice: \"auto\" | \"none\" | \"required\";\n} {\n const toolsFromConfig = overrides?.tools ?? [];\n const hasEmotionTool = toolsFromConfig.some(\n (tool) => tool.type === \"function\" && tool.name === setEmotionTool.name,\n );\n const tools = hasEmotionTool\n ? toolsFromConfig\n : [setEmotionTool, ...toolsFromConfig];\n\n return {\n type: \"realtime\",\n model: overrides?.model || \"gpt-realtime-mini\",\n audio: {\n output: {\n voice: overrides?.voice || \"marin\",\n },\n },\n instructions: overrides?.instructions || DEFAULT_EMOTION_INSTRUCTIONS,\n tools,\n tool_choice: overrides?.tool_choice ?? \"auto\",\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/realtime-manager.ts","../src/tools.ts"],"names":["Emotion"],"mappings":"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","file":"index.js","sourcesContent":["import {\n CharivoEventEmitter,\n RealtimeManager as CoreRealtimeManager,\n RealtimeSessionConfig,\n RealtimeClient,\n} from \"./types\";\nimport { Emotion } from \"@charivo/core\";\n\n/**\n * Realtime Manager - Realtime API ์ธ์
๊ด๋ฆฌ\n *\n * ์ญํ :\n * - Realtime ํด๋ผ์ด์ธํธ ๊ด๋ฆฌ (WebRTC)\n * - ๋ฆฝ์ฑํฌ ์ด๋ฒคํธ ์ค๊ณ\n * - ํ
์คํธ ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ\n *\n * Note: WebRTC ํด๋ผ์ด์ธํธ๋ ์ค๋์ค๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก\n * ์ด Manager๋ ์ด๋ฒคํธ ์ค๊ณ์ ์ง์คํฉ๋๋ค.\n */\nexport class RealtimeManagerImpl implements CoreRealtimeManager {\n private client: RealtimeClient;\n private eventEmitter?: CharivoEventEmitter;\n private isSessionActive = false;\n private isAudioPlaybackActive = false;\n\n constructor(client: RealtimeClient) {\n this.client = client;\n this.setupClientListeners();\n }\n\n /**\n * ์ด๋ฒคํธ ๋ฐ์ ์ ์ค์ \n */\n setEventEmitter(eventEmitter: CharivoEventEmitter): void {\n this.eventEmitter = eventEmitter;\n }\n\n /**\n * Realtime ์ธ์
์์\n */\n async startSession(config: RealtimeSessionConfig): Promise<void> {\n if (this.isSessionActive) {\n throw new Error(\"Realtime session already active\");\n }\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ\n await this.client.connect(config);\n\n this.isSessionActive = true;\n }\n\n /**\n * Realtime ์ธ์
์ข
๋ฃ\n */\n async stopSession(): Promise<void> {\n if (!this.isSessionActive) return;\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ํด์ \n await this.client.disconnect();\n this.emitAudioEnd();\n\n this.isSessionActive = false;\n }\n\n /**\n * ํ
์คํธ ๋ฉ์์ง ์ ์ก\n */\n async sendMessage(text: string): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n this.emitAudioStart();\n try {\n await this.client.sendText(text);\n } catch (error) {\n this.emitAudioEnd();\n throw error;\n }\n }\n\n /**\n * ์ค๋์ค ์ฒญํฌ ์ ์ก (์ฌ์ฉ์ ์์ฑ)\n */\n async sendAudioChunk(audio: ArrayBuffer): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n await this.client.sendAudio(audio);\n }\n\n /**\n * ํด๋ผ์ด์ธํธ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์ \n */\n private setupClientListeners(): void {\n // ํ
์คํธ ์คํธ๋ฆฌ๋ฐ\n this.client.onTextDelta((text: string) => {\n this.eventEmitter?.emit(\"realtime:text:delta\", { text });\n });\n\n // Direct RMS callback (for WebRTC clients)\n if (this.client.onLipSyncUpdate) {\n this.client.onLipSyncUpdate((rms: number) => {\n if (rms > 0.001 && !this.isAudioPlaybackActive) {\n this.emitAudioStart();\n }\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms });\n });\n }\n\n // ์ค๋์ค ์คํธ๋ฆฌ๋ฐ ์ข
๋ฃ\n this.client.onAudioDone(() => {\n this.emitAudioEnd();\n });\n\n // Tool call ์ฒ๋ฆฌ\n if (this.client.onToolCall) {\n this.client.onToolCall((name: string, args: Record<string, unknown>) => {\n this.handleToolCall(name, args);\n });\n }\n\n // ์๋ฌ ์ฒ๋ฆฌ\n this.client.onError((error: Error) => {\n this.emitAudioEnd();\n this.eventEmitter?.emit(\"realtime:error\", { error });\n });\n }\n\n /**\n * Tool call ์ฒ๋ฆฌ\n */\n private handleToolCall(name: string, args: Record<string, unknown>): void {\n const emotion = args.emotion;\n\n if (name === \"setEmotion\" && typeof emotion === \"string\") {\n this.eventEmitter?.emit(\"realtime:emotion\", {\n emotion: emotion as Emotion,\n });\n }\n }\n\n private emitAudioStart(): void {\n if (this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = true;\n this.eventEmitter?.emit(\"tts:audio:start\", {});\n }\n\n private emitAudioEnd(): void {\n if (!this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = false;\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms: 0 });\n this.eventEmitter?.emit(\"tts:audio:end\", {});\n }\n}\n\n/**\n * Realtime Manager ์์ฑ ํฌํผ ํจ์\n */\nexport function createRealtimeManager(\n client: RealtimeClient,\n): CoreRealtimeManager {\n return new RealtimeManagerImpl(client);\n}\n","import {\n Emotion,\n type RealtimeSessionConfig,\n type RealtimeTool,\n} from \"@charivo/core\";\n\n/**\n * Get emotion enum values for tool definition\n */\nconst EMOTION_VALUES = Object.values(Emotion);\n\n/**\n * setEmotion tool definition for OpenAI Realtime API\n *\n * This tool allows the LLM to update the Live2D character's emotion.\n */\nexport const setEmotionTool: RealtimeTool = {\n type: \"function\",\n name: \"setEmotion\",\n description:\n \"Update Live2D character emotion. Call this when the conversation mood or emotion changes.\",\n parameters: {\n type: \"object\",\n properties: {\n emotion: {\n type: \"string\",\n description: \"Emotion of the character.\",\n enum: EMOTION_VALUES,\n },\n },\n required: [\"emotion\"],\n },\n};\n\n/**\n * Emotion tool call arguments type\n */\nexport interface EmotionArgs {\n emotion: Emotion;\n}\n\n/**\n * Default instructions for character with emotion support\n */\nexport const DEFAULT_EMOTION_INSTRUCTIONS = `\nYou are a Live2D character with emotions and expressions.\nRespond naturally to the user's messages.\nWhen the conversation mood or emotion changes, call the 'setEmotion' tool to update your expression and motion.\nDo NOT mention the tool call in your response - just respond naturally and let the emotion show through your character.\n`.trim();\n\n/**\n * Get default Realtime session config with emotion support\n */\nexport function getEmotionSessionConfig(overrides?: RealtimeSessionConfig): {\n type: string;\n model: string;\n audio: { output: { voice: string } };\n instructions: string;\n tools: RealtimeTool[];\n tool_choice: \"auto\" | \"none\" | \"required\";\n} {\n const toolsFromConfig = overrides?.tools ?? [];\n const hasEmotionTool = toolsFromConfig.some(\n (tool) => tool.type === \"function\" && tool.name === setEmotionTool.name,\n );\n const tools = hasEmotionTool\n ? toolsFromConfig\n : [setEmotionTool, ...toolsFromConfig];\n\n return {\n type: \"realtime\",\n model: overrides?.model || \"gpt-realtime-mini\",\n audio: {\n output: {\n voice: overrides?.voice || \"marin\",\n },\n },\n instructions: overrides?.instructions || DEFAULT_EMOTION_INSTRUCTIONS,\n tools,\n tool_choice: overrides?.tool_choice ?? \"auto\",\n };\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -15,7 +15,6 @@ var RealtimeManagerImpl = class {
|
|
|
15
15
|
*/
|
|
16
16
|
setEventEmitter(eventEmitter) {
|
|
17
17
|
this.eventEmitter = eventEmitter;
|
|
18
|
-
console.log("\u{1F517} Realtime Manager: Event emitter connected");
|
|
19
18
|
}
|
|
20
19
|
/**
|
|
21
20
|
* Realtime ์ธ์
์์
|
|
@@ -24,21 +23,17 @@ var RealtimeManagerImpl = class {
|
|
|
24
23
|
if (this.isSessionActive) {
|
|
25
24
|
throw new Error("Realtime session already active");
|
|
26
25
|
}
|
|
27
|
-
console.log("\u{1F680} Starting Realtime session with config:", config);
|
|
28
26
|
await this.client.connect(config);
|
|
29
27
|
this.isSessionActive = true;
|
|
30
|
-
console.log("\u2705 Realtime session started");
|
|
31
28
|
}
|
|
32
29
|
/**
|
|
33
30
|
* Realtime ์ธ์
์ข
๋ฃ
|
|
34
31
|
*/
|
|
35
32
|
async stopSession() {
|
|
36
33
|
if (!this.isSessionActive) return;
|
|
37
|
-
console.log("\u{1F6D1} Stopping Realtime session");
|
|
38
34
|
await this.client.disconnect();
|
|
39
35
|
this.emitAudioEnd();
|
|
40
36
|
this.isSessionActive = false;
|
|
41
|
-
console.log("\u2705 Realtime session stopped");
|
|
42
37
|
}
|
|
43
38
|
/**
|
|
44
39
|
* ํ
์คํธ ๋ฉ์์ง ์ ์ก
|
|
@@ -88,7 +83,6 @@ var RealtimeManagerImpl = class {
|
|
|
88
83
|
});
|
|
89
84
|
}
|
|
90
85
|
this.client.onError((error) => {
|
|
91
|
-
console.error("Realtime client error:", error);
|
|
92
86
|
this.emitAudioEnd();
|
|
93
87
|
this.eventEmitter?.emit("realtime:error", { error });
|
|
94
88
|
});
|
|
@@ -97,10 +91,10 @@ var RealtimeManagerImpl = class {
|
|
|
97
91
|
* Tool call ์ฒ๋ฆฌ
|
|
98
92
|
*/
|
|
99
93
|
handleToolCall(name, args) {
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
const emotion = args.emotion;
|
|
95
|
+
if (name === "setEmotion" && typeof emotion === "string") {
|
|
102
96
|
this.eventEmitter?.emit("realtime:emotion", {
|
|
103
|
-
emotion
|
|
97
|
+
emotion
|
|
104
98
|
});
|
|
105
99
|
}
|
|
106
100
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/realtime-manager.ts","../src/tools.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import {\n RealtimeClient,\n RealtimeManager as IRealtimeManager,\n RealtimeSessionConfig,\n} from \"./types\";\n\n/**\n * Realtime Manager - Realtime API ์ธ์
๊ด๋ฆฌ\n *\n * ์ญํ :\n * - Realtime ํด๋ผ์ด์ธํธ ๊ด๋ฆฌ (WebRTC)\n * - ๋ฆฝ์ฑํฌ ์ด๋ฒคํธ ์ค๊ณ\n * - ํ
์คํธ ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ\n *\n * Note: WebRTC ํด๋ผ์ด์ธํธ๋ ์ค๋์ค๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก\n * ์ด Manager๋ ์ด๋ฒคํธ ์ค๊ณ์ ์ง์คํฉ๋๋ค.\n */\nexport class RealtimeManagerImpl implements IRealtimeManager {\n private client: RealtimeClient;\n private eventEmitter?: { emit: (event: string, data: any) => void };\n private isSessionActive = false;\n private isAudioPlaybackActive = false;\n\n constructor(client: RealtimeClient) {\n this.client = client;\n this.setupClientListeners();\n }\n\n /**\n * ์ด๋ฒคํธ ๋ฐ์ ์ ์ค์ \n */\n setEventEmitter(eventEmitter: {\n emit: (event: string, data: any) => void;\n }): void {\n this.eventEmitter = eventEmitter;\n console.log(\"๐ Realtime Manager: Event emitter connected\");\n }\n\n /**\n * Realtime ์ธ์
์์\n */\n async startSession(config: RealtimeSessionConfig): Promise<void> {\n if (this.isSessionActive) {\n throw new Error(\"Realtime session already active\");\n }\n\n console.log(\"๐ Starting Realtime session with config:\", config);\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ\n await this.client.connect(config);\n\n this.isSessionActive = true;\n\n console.log(\"โ
Realtime session started\");\n }\n\n /**\n * Realtime ์ธ์
์ข
๋ฃ\n */\n async stopSession(): Promise<void> {\n if (!this.isSessionActive) return;\n\n console.log(\"๐ Stopping Realtime session\");\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ํด์ \n await this.client.disconnect();\n this.emitAudioEnd();\n\n this.isSessionActive = false;\n\n console.log(\"โ
Realtime session stopped\");\n }\n\n /**\n * ํ
์คํธ ๋ฉ์์ง ์ ์ก\n */\n async sendMessage(text: string): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n this.emitAudioStart();\n try {\n await this.client.sendText(text);\n } catch (error) {\n this.emitAudioEnd();\n throw error;\n }\n }\n\n /**\n * ์ค๋์ค ์ฒญํฌ ์ ์ก (์ฌ์ฉ์ ์์ฑ)\n */\n async sendAudioChunk(audio: ArrayBuffer): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n await this.client.sendAudio(audio);\n }\n\n /**\n * ํด๋ผ์ด์ธํธ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์ \n */\n private setupClientListeners(): void {\n // ํ
์คํธ ์คํธ๋ฆฌ๋ฐ\n this.client.onTextDelta((text: string) => {\n this.eventEmitter?.emit(\"realtime:text:delta\", { text });\n });\n\n // Direct RMS callback (for WebRTC clients)\n if (this.client.onLipSyncUpdate) {\n this.client.onLipSyncUpdate((rms: number) => {\n if (rms > 0.001 && !this.isAudioPlaybackActive) {\n this.emitAudioStart();\n }\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms });\n });\n }\n\n // ์ค๋์ค ์คํธ๋ฆฌ๋ฐ ์ข
๋ฃ\n this.client.onAudioDone(() => {\n this.emitAudioEnd();\n });\n\n // Tool call ์ฒ๋ฆฌ\n if (this.client.onToolCall) {\n this.client.onToolCall((name: string, args: any) => {\n this.handleToolCall(name, args);\n });\n }\n\n // ์๋ฌ ์ฒ๋ฆฌ\n this.client.onError((error: Error) => {\n console.error(\"Realtime client error:\", error);\n this.emitAudioEnd();\n this.eventEmitter?.emit(\"realtime:error\", { error });\n });\n }\n\n /**\n * Tool call ์ฒ๋ฆฌ\n */\n private handleToolCall(name: string, args: any): void {\n if (name === \"setEmotion\") {\n console.log(`๐ญ [Realtime] Emotion update:`, args.emotion);\n // Emit emotion event for RenderManager\n this.eventEmitter?.emit(\"realtime:emotion\", {\n emotion: args.emotion,\n });\n }\n }\n\n private emitAudioStart(): void {\n if (this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = true;\n this.eventEmitter?.emit(\"tts:audio:start\", {});\n }\n\n private emitAudioEnd(): void {\n if (!this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = false;\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms: 0 });\n this.eventEmitter?.emit(\"tts:audio:end\", {});\n }\n}\n\n/**\n * Realtime Manager ์์ฑ ํฌํผ ํจ์\n */\nexport function createRealtimeManager(\n client: RealtimeClient,\n): IRealtimeManager {\n return new RealtimeManagerImpl(client);\n}\n","import type { RealtimeSessionConfig, RealtimeTool } from \"./types\";\nimport { Emotion } from \"@charivo/core\";\n\n/**\n * Get emotion enum values for tool definition\n */\nconst EMOTION_VALUES = Object.values(Emotion);\n\n/**\n * setEmotion tool definition for OpenAI Realtime API\n *\n * This tool allows the LLM to update the Live2D character's emotion.\n */\nexport const setEmotionTool: RealtimeTool = {\n type: \"function\",\n name: \"setEmotion\",\n description:\n \"Update Live2D character emotion. Call this when the conversation mood or emotion changes.\",\n parameters: {\n type: \"object\",\n properties: {\n emotion: {\n type: \"string\",\n description: \"Emotion of the character.\",\n enum: EMOTION_VALUES,\n },\n },\n required: [\"emotion\"],\n },\n};\n\n/**\n * Emotion tool call arguments type\n */\nexport interface EmotionArgs {\n emotion: Emotion;\n}\n\n/**\n * Default instructions for character with emotion support\n */\nexport const DEFAULT_EMOTION_INSTRUCTIONS = `\nYou are a Live2D character with emotions and expressions.\nRespond naturally to the user's messages.\nWhen the conversation mood or emotion changes, call the 'setEmotion' tool to update your expression and motion.\nDo NOT mention the tool call in your response - just respond naturally and let the emotion show through your character.\n`.trim();\n\n/**\n * Get default Realtime session config with emotion support\n */\nexport function getEmotionSessionConfig(overrides?: RealtimeSessionConfig): {\n type: string;\n model: string;\n audio: { output: { voice: string } };\n instructions: string;\n tools: RealtimeTool[];\n tool_choice: \"auto\" | \"none\" | \"required\";\n} {\n const toolsFromConfig = overrides?.tools ?? [];\n const hasEmotionTool = toolsFromConfig.some(\n (tool) => tool.type === \"function\" && tool.name === setEmotionTool.name,\n );\n const tools = hasEmotionTool\n ? toolsFromConfig\n : [setEmotionTool, ...toolsFromConfig];\n\n return {\n type: \"realtime\",\n model: overrides?.model || \"gpt-realtime-mini\",\n audio: {\n output: {\n voice: overrides?.voice || \"marin\",\n },\n },\n instructions: overrides?.instructions || DEFAULT_EMOTION_INSTRUCTIONS,\n tools,\n tool_choice: overrides?.tool_choice ?? \"auto\",\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/realtime-manager.ts","../src/tools.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import {\n CharivoEventEmitter,\n RealtimeManager as CoreRealtimeManager,\n RealtimeSessionConfig,\n RealtimeClient,\n} from \"./types\";\nimport { Emotion } from \"@charivo/core\";\n\n/**\n * Realtime Manager - Realtime API ์ธ์
๊ด๋ฆฌ\n *\n * ์ญํ :\n * - Realtime ํด๋ผ์ด์ธํธ ๊ด๋ฆฌ (WebRTC)\n * - ๋ฆฝ์ฑํฌ ์ด๋ฒคํธ ์ค๊ณ\n * - ํ
์คํธ ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ\n *\n * Note: WebRTC ํด๋ผ์ด์ธํธ๋ ์ค๋์ค๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก\n * ์ด Manager๋ ์ด๋ฒคํธ ์ค๊ณ์ ์ง์คํฉ๋๋ค.\n */\nexport class RealtimeManagerImpl implements CoreRealtimeManager {\n private client: RealtimeClient;\n private eventEmitter?: CharivoEventEmitter;\n private isSessionActive = false;\n private isAudioPlaybackActive = false;\n\n constructor(client: RealtimeClient) {\n this.client = client;\n this.setupClientListeners();\n }\n\n /**\n * ์ด๋ฒคํธ ๋ฐ์ ์ ์ค์ \n */\n setEventEmitter(eventEmitter: CharivoEventEmitter): void {\n this.eventEmitter = eventEmitter;\n }\n\n /**\n * Realtime ์ธ์
์์\n */\n async startSession(config: RealtimeSessionConfig): Promise<void> {\n if (this.isSessionActive) {\n throw new Error(\"Realtime session already active\");\n }\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ\n await this.client.connect(config);\n\n this.isSessionActive = true;\n }\n\n /**\n * Realtime ์ธ์
์ข
๋ฃ\n */\n async stopSession(): Promise<void> {\n if (!this.isSessionActive) return;\n\n // ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ํด์ \n await this.client.disconnect();\n this.emitAudioEnd();\n\n this.isSessionActive = false;\n }\n\n /**\n * ํ
์คํธ ๋ฉ์์ง ์ ์ก\n */\n async sendMessage(text: string): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n this.emitAudioStart();\n try {\n await this.client.sendText(text);\n } catch (error) {\n this.emitAudioEnd();\n throw error;\n }\n }\n\n /**\n * ์ค๋์ค ์ฒญํฌ ์ ์ก (์ฌ์ฉ์ ์์ฑ)\n */\n async sendAudioChunk(audio: ArrayBuffer): Promise<void> {\n if (!this.isSessionActive) {\n throw new Error(\"Realtime session not active\");\n }\n\n await this.client.sendAudio(audio);\n }\n\n /**\n * ํด๋ผ์ด์ธํธ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์ \n */\n private setupClientListeners(): void {\n // ํ
์คํธ ์คํธ๋ฆฌ๋ฐ\n this.client.onTextDelta((text: string) => {\n this.eventEmitter?.emit(\"realtime:text:delta\", { text });\n });\n\n // Direct RMS callback (for WebRTC clients)\n if (this.client.onLipSyncUpdate) {\n this.client.onLipSyncUpdate((rms: number) => {\n if (rms > 0.001 && !this.isAudioPlaybackActive) {\n this.emitAudioStart();\n }\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms });\n });\n }\n\n // ์ค๋์ค ์คํธ๋ฆฌ๋ฐ ์ข
๋ฃ\n this.client.onAudioDone(() => {\n this.emitAudioEnd();\n });\n\n // Tool call ์ฒ๋ฆฌ\n if (this.client.onToolCall) {\n this.client.onToolCall((name: string, args: Record<string, unknown>) => {\n this.handleToolCall(name, args);\n });\n }\n\n // ์๋ฌ ์ฒ๋ฆฌ\n this.client.onError((error: Error) => {\n this.emitAudioEnd();\n this.eventEmitter?.emit(\"realtime:error\", { error });\n });\n }\n\n /**\n * Tool call ์ฒ๋ฆฌ\n */\n private handleToolCall(name: string, args: Record<string, unknown>): void {\n const emotion = args.emotion;\n\n if (name === \"setEmotion\" && typeof emotion === \"string\") {\n this.eventEmitter?.emit(\"realtime:emotion\", {\n emotion: emotion as Emotion,\n });\n }\n }\n\n private emitAudioStart(): void {\n if (this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = true;\n this.eventEmitter?.emit(\"tts:audio:start\", {});\n }\n\n private emitAudioEnd(): void {\n if (!this.isAudioPlaybackActive) {\n return;\n }\n this.isAudioPlaybackActive = false;\n this.eventEmitter?.emit(\"tts:lipsync:update\", { rms: 0 });\n this.eventEmitter?.emit(\"tts:audio:end\", {});\n }\n}\n\n/**\n * Realtime Manager ์์ฑ ํฌํผ ํจ์\n */\nexport function createRealtimeManager(\n client: RealtimeClient,\n): CoreRealtimeManager {\n return new RealtimeManagerImpl(client);\n}\n","import {\n Emotion,\n type RealtimeSessionConfig,\n type RealtimeTool,\n} from \"@charivo/core\";\n\n/**\n * Get emotion enum values for tool definition\n */\nconst EMOTION_VALUES = Object.values(Emotion);\n\n/**\n * setEmotion tool definition for OpenAI Realtime API\n *\n * This tool allows the LLM to update the Live2D character's emotion.\n */\nexport const setEmotionTool: RealtimeTool = {\n type: \"function\",\n name: \"setEmotion\",\n description:\n \"Update Live2D character emotion. Call this when the conversation mood or emotion changes.\",\n parameters: {\n type: \"object\",\n properties: {\n emotion: {\n type: \"string\",\n description: \"Emotion of the character.\",\n enum: EMOTION_VALUES,\n },\n },\n required: [\"emotion\"],\n },\n};\n\n/**\n * Emotion tool call arguments type\n */\nexport interface EmotionArgs {\n emotion: Emotion;\n}\n\n/**\n * Default instructions for character with emotion support\n */\nexport const DEFAULT_EMOTION_INSTRUCTIONS = `\nYou are a Live2D character with emotions and expressions.\nRespond naturally to the user's messages.\nWhen the conversation mood or emotion changes, call the 'setEmotion' tool to update your expression and motion.\nDo NOT mention the tool call in your response - just respond naturally and let the emotion show through your character.\n`.trim();\n\n/**\n * Get default Realtime session config with emotion support\n */\nexport function getEmotionSessionConfig(overrides?: RealtimeSessionConfig): {\n type: string;\n model: string;\n audio: { output: { voice: string } };\n instructions: string;\n tools: RealtimeTool[];\n tool_choice: \"auto\" | \"none\" | \"required\";\n} {\n const toolsFromConfig = overrides?.tools ?? [];\n const hasEmotionTool = toolsFromConfig.some(\n (tool) => tool.type === \"function\" && tool.name === setEmotionTool.name,\n );\n const tools = hasEmotionTool\n ? toolsFromConfig\n : [setEmotionTool, ...toolsFromConfig];\n\n return {\n type: \"realtime\",\n model: overrides?.model || \"gpt-realtime-mini\",\n audio: {\n output: {\n voice: overrides?.voice || \"marin\",\n },\n },\n instructions: overrides?.instructions || DEFAULT_EMOTION_INSTRUCTIONS,\n tools,\n tool_choice: overrides?.tool_choice ?? \"auto\",\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charivo/realtime-core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Core utilities for Realtime API functionality in Charivo",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
7
15
|
"dependencies": {
|
|
8
|
-
"@charivo/core": "0.0
|
|
16
|
+
"@charivo/core": "0.1.0"
|
|
9
17
|
},
|
|
10
18
|
"devDependencies": {
|
|
11
19
|
"tsup": "^8.0.0",
|
|
@@ -34,6 +42,7 @@
|
|
|
34
42
|
"scripts": {
|
|
35
43
|
"build": "tsup",
|
|
36
44
|
"dev": "tsup --watch",
|
|
37
|
-
"clean": "rm -rf dist"
|
|
45
|
+
"clean": "rm -rf dist",
|
|
46
|
+
"typecheck": "tsc --noEmit"
|
|
38
47
|
}
|
|
39
48
|
}
|