forked from MCERQUA/OpenVoiceUI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_template.js
More file actions
133 lines (113 loc) · 6.28 KB
/
Copy path_template.js
File metadata and controls
133 lines (113 loc) · 6.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Agent Adapter Template
*
* Copy this file to create a new agent adapter.
* Replace all TODO placeholders with your implementation.
*
* Rules:
* 1. Communicate with the outside world ONLY through the bridge
* 2. Manage your own audio, WebSocket, and SDK internally
* 3. Release ALL resources in destroy()
* 4. Never import from other adapters
*
* Ref: future-dev-plans/17-MULTI-AGENT-FRAMEWORK.md
*/
import { AgentEvents, AgentActions } from '../core/EventBridge.js';
export const TemplateAdapter = {
/** Human-readable name shown in UI */
name: 'My Agent System',
/**
* What this adapter can do.
* UI shows/hides features based on this list.
*
* Available capabilities:
* 'canvas' - Agent can show HTML pages on the canvas display
* 'dj_soundboard' - Agent can play DJ sound effects
* 'caller_effects' - Agent can toggle phone filter audio effect
* 'music_sync' - Agent can control music playback
* 'multi_voice' - Agent uses multiple voices/personas
* 'emotion_detection' - Agent sends emotion scores per utterance
* 'commercials' - Agent can trigger commercial breaks
* 'vps_control' - Agent can run commands on VPS
* 'wake_word' - Agent supports wake word activation
*/
capabilities: [
// TODO: add capabilities your adapter supports
],
// ── Private state (prefix _ to mark as internal) ──────────────
_bridge: null,
_config: null,
_unsubscribers: [], // Store bridge.on() return values for cleanup
// ─────────────────────────────────────────────────────────────
// INIT — called when user selects this adapter mode
//
// Load SDKs, set up connections, subscribe to UI actions.
// DO NOT start mic or begin conversation here — that's start().
// ─────────────────────────────────────────────────────────────
async init(bridge, config) {
this._bridge = bridge;
this._config = config || {};
// TODO: load your SDK, set up audio chain, preload assets
// Subscribe to UI → Agent actions
this._unsubscribers.push(
bridge.on(AgentActions.END_SESSION, () => this.stop()),
// bridge.on(AgentActions.SEND_MESSAGE, (d) => this._handleSendMessage(d.text)),
// bridge.on(AgentActions.CONTEXT_UPDATE, (d) => this._sendContext(d.text)),
// bridge.on(AgentActions.FORCE_MESSAGE, (d) => this._forceMessage(d.text)),
);
},
// ─────────────────────────────────────────────────────────────
// START — begin conversation (called from user click)
//
// Start mic, connect to agent backend, etc.
// ─────────────────────────────────────────────────────────────
async start() {
// TODO: unlock iOS AudioContext if needed
// const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
// stream.getTracks().forEach(t => t.stop());
// TODO: connect to your agent
// Emit connected event when ready
this._bridge.emit(AgentEvents.CONNECTED);
this._bridge.emit(AgentEvents.STATE_CHANGED, { state: 'listening' });
this._bridge.emit(AgentEvents.MOOD, { mood: 'happy' });
},
// ─────────────────────────────────────────────────────────────
// STOP — end conversation gracefully (user clicks stop)
// ─────────────────────────────────────────────────────────────
async stop() {
// TODO: end session, release mic
this._bridge.emit(AgentEvents.STATE_CHANGED, { state: 'idle' });
this._bridge.emit(AgentEvents.DISCONNECTED);
this._bridge.emit(AgentEvents.MOOD, { mood: 'neutral' });
},
// ─────────────────────────────────────────────────────────────
// DESTROY — full teardown on adapter switch
//
// MUST release: mic, AudioContext, WebSocket, SDK instances.
// MUST unsubscribe all bridge.on() subscriptions.
// ─────────────────────────────────────────────────────────────
async destroy() {
await this.stop();
// Unsubscribe all bridge listeners
this._unsubscribers.forEach(unsub => unsub());
this._unsubscribers = [];
// TODO: disconnect SDK, close AudioContext, etc.
},
// ─────────────────────────────────────────────────────────────
// PRIVATE methods (prefix _ to mark as internal)
// ─────────────────────────────────────────────────────────────
// Example: emit bridge events when things happen
_onAgentSpeaking(text) {
this._bridge.emit(AgentEvents.STATE_CHANGED, { state: 'speaking' });
this._bridge.emit(AgentEvents.TTS_PLAYING);
this._bridge.emit(AgentEvents.MESSAGE, { role: 'assistant', text, final: true });
},
_onAgentListening() {
this._bridge.emit(AgentEvents.TTS_STOPPED);
this._bridge.emit(AgentEvents.STATE_CHANGED, { state: 'listening' });
},
_onToolCall(name, params, result) {
this._bridge.emit(AgentEvents.TOOL_CALLED, { name, params, result });
},
};
export default TemplateAdapter;