codmir 0.3.3 → 0.4.1
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/dist/{chunk-LXEEBTWT.mjs → chunk-GU32P57R.mjs} +70 -0
- package/dist/cli/index.js +198 -45
- package/dist/cli/index.mjs +129 -46
- package/dist/index.d.mts +76 -1
- package/dist/index.d.ts +76 -1
- package/dist/index.js +70 -0
- package/dist/index.mjs +1 -1
- package/dist/voice-agent/index.d.mts +134 -0
- package/dist/voice-agent/index.d.ts +134 -0
- package/dist/voice-agent/index.js +220 -0
- package/dist/voice-agent/index.mjs +187 -0
- package/dist/voice-daemon/index.d.mts +354 -0
- package/dist/voice-daemon/index.d.ts +354 -0
- package/dist/voice-daemon/index.js +1089 -0
- package/dist/voice-daemon/index.mjs +1046 -0
- package/package.json +33 -16
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log level supported by the daemon logger.
|
|
3
|
+
*/
|
|
4
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
5
|
+
/**
|
|
6
|
+
* Converts a string or undefined into a valid log level.
|
|
7
|
+
* Defaults to "info" if the provided value is invalid.
|
|
8
|
+
*
|
|
9
|
+
* @param value Raw log level value, typically from environment variables.
|
|
10
|
+
*/
|
|
11
|
+
declare function normalizeLogLevel(value?: string): LogLevel;
|
|
12
|
+
/**
|
|
13
|
+
* Simple structured logger used by the voice daemon.
|
|
14
|
+
* Logs to stdout with timestamps and JSON metadata.
|
|
15
|
+
*/
|
|
16
|
+
declare class Logger {
|
|
17
|
+
private level;
|
|
18
|
+
private readonly prefix;
|
|
19
|
+
constructor(level: LogLevel, prefix?: string);
|
|
20
|
+
/**
|
|
21
|
+
* Logs a debug-level message.
|
|
22
|
+
*/
|
|
23
|
+
debug(message: string, meta?: unknown): void;
|
|
24
|
+
/**
|
|
25
|
+
* Logs an info-level message.
|
|
26
|
+
*/
|
|
27
|
+
info(message: string, meta?: unknown): void;
|
|
28
|
+
/**
|
|
29
|
+
* Logs a warning-level message.
|
|
30
|
+
*/
|
|
31
|
+
warn(message: string, meta?: unknown): void;
|
|
32
|
+
/**
|
|
33
|
+
* Logs an error-level message.
|
|
34
|
+
*/
|
|
35
|
+
error(message: string, meta?: unknown): void;
|
|
36
|
+
private log;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Runtime configuration for the codmir voice daemon.
|
|
41
|
+
*/
|
|
42
|
+
interface DaemonConfig {
|
|
43
|
+
/** TCP port for the WebSocket server (localhost only). */
|
|
44
|
+
port: number;
|
|
45
|
+
/** HTTP port for the webhook receiver (wakeword events). */
|
|
46
|
+
httpPort: number;
|
|
47
|
+
/** Log level used by the daemon. */
|
|
48
|
+
logLevel: LogLevel;
|
|
49
|
+
/** URL of the desktop-automation service. */
|
|
50
|
+
desktopAutomationUrl: string;
|
|
51
|
+
/** URL of the TTS worker service. */
|
|
52
|
+
ttsWorkerUrl: string;
|
|
53
|
+
/** URL of the orchestrator service. */
|
|
54
|
+
orchestratorUrl: string;
|
|
55
|
+
/** URL of the overlay service (Python PyQt5 ball UI). */
|
|
56
|
+
overlayUrl: string;
|
|
57
|
+
/** Whether approval is required before executing commands. */
|
|
58
|
+
approvalMode: boolean;
|
|
59
|
+
/** Whether the daemon is muted (ignores wake words). */
|
|
60
|
+
muted: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Loads daemon configuration from environment variables.
|
|
64
|
+
*
|
|
65
|
+
* @param logger Logger instance for debug output.
|
|
66
|
+
*/
|
|
67
|
+
declare function loadConfig(logger: Logger): DaemonConfig;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Voice assistant states for UI overlay.
|
|
71
|
+
*/
|
|
72
|
+
type AssistantState = "idle" | "listening" | "thinking" | "speaking" | "error";
|
|
73
|
+
/**
|
|
74
|
+
* Structured commands that can be executed by the daemon.
|
|
75
|
+
* All commands are logged and require explicit approval in safe mode.
|
|
76
|
+
*/
|
|
77
|
+
type CodmirCommand = {
|
|
78
|
+
type: "open_app";
|
|
79
|
+
name: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: "open_url";
|
|
82
|
+
url: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: "focus_window";
|
|
85
|
+
titleContains: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: "type_text";
|
|
88
|
+
text: string;
|
|
89
|
+
} | {
|
|
90
|
+
type: "press_key";
|
|
91
|
+
key: string;
|
|
92
|
+
} | {
|
|
93
|
+
type: "click";
|
|
94
|
+
button?: number;
|
|
95
|
+
} | {
|
|
96
|
+
type: "scroll";
|
|
97
|
+
direction: "up" | "down";
|
|
98
|
+
amount?: number;
|
|
99
|
+
} | {
|
|
100
|
+
type: "speak";
|
|
101
|
+
text: string;
|
|
102
|
+
voice?: string;
|
|
103
|
+
} | {
|
|
104
|
+
type: "run_script";
|
|
105
|
+
script: string;
|
|
106
|
+
allowListId?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Callback invoked when the assistant state changes.
|
|
111
|
+
*/
|
|
112
|
+
type StateChangeCallback = (newState: AssistantState, previousState: AssistantState) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Manages the voice assistant state machine.
|
|
115
|
+
* States: idle → listening → thinking → speaking → idle
|
|
116
|
+
*/
|
|
117
|
+
declare class AssistantStateMachine {
|
|
118
|
+
private state;
|
|
119
|
+
private readonly logger;
|
|
120
|
+
private readonly listeners;
|
|
121
|
+
constructor(logger: Logger);
|
|
122
|
+
/**
|
|
123
|
+
* Returns the current assistant state.
|
|
124
|
+
*/
|
|
125
|
+
getState(): AssistantState;
|
|
126
|
+
/**
|
|
127
|
+
* Transitions to a new state and notifies listeners.
|
|
128
|
+
*/
|
|
129
|
+
setState(newState: AssistantState): void;
|
|
130
|
+
/**
|
|
131
|
+
* Registers a callback to be invoked on state changes.
|
|
132
|
+
*/
|
|
133
|
+
onStateChange(callback: StateChangeCallback): () => void;
|
|
134
|
+
/**
|
|
135
|
+
* Called when wake word is detected.
|
|
136
|
+
*/
|
|
137
|
+
handleWake(): void;
|
|
138
|
+
/**
|
|
139
|
+
* Called when speech-to-text is complete.
|
|
140
|
+
*/
|
|
141
|
+
handleTranscriptComplete(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Called when AI response is ready and TTS begins.
|
|
144
|
+
*/
|
|
145
|
+
handleSpeakStart(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Called when TTS playback is complete.
|
|
148
|
+
*/
|
|
149
|
+
handleSpeakEnd(): void;
|
|
150
|
+
/**
|
|
151
|
+
* Called on any error, resets to idle.
|
|
152
|
+
*/
|
|
153
|
+
handleError(): void;
|
|
154
|
+
/**
|
|
155
|
+
* Force reset to idle.
|
|
156
|
+
*/
|
|
157
|
+
reset(): void;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Result of executing a command.
|
|
162
|
+
*/
|
|
163
|
+
interface CommandResult {
|
|
164
|
+
success: boolean;
|
|
165
|
+
error?: string;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Executes commands by calling the desktop-automation and TTS services.
|
|
169
|
+
*/
|
|
170
|
+
declare class CommandExecutor {
|
|
171
|
+
private readonly config;
|
|
172
|
+
private readonly logger;
|
|
173
|
+
constructor(config: DaemonConfig, logger: Logger);
|
|
174
|
+
/**
|
|
175
|
+
* Executes a single command.
|
|
176
|
+
*/
|
|
177
|
+
execute(command: CodmirCommand): Promise<CommandResult>;
|
|
178
|
+
private callDesktopAutomation;
|
|
179
|
+
private callTts;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* WebSocket server for the voice daemon.
|
|
184
|
+
* Clients (overlay, CLI, IDE, web) connect here to receive state updates and send commands.
|
|
185
|
+
*/
|
|
186
|
+
declare class VoiceDaemonWebSocketServer {
|
|
187
|
+
private readonly config;
|
|
188
|
+
private readonly logger;
|
|
189
|
+
private readonly stateMachine;
|
|
190
|
+
private readonly executor;
|
|
191
|
+
private readonly wss;
|
|
192
|
+
private readonly clients;
|
|
193
|
+
constructor(config: DaemonConfig, logger: Logger, stateMachine: AssistantStateMachine, executor: CommandExecutor);
|
|
194
|
+
private setupListeners;
|
|
195
|
+
private setupStateListener;
|
|
196
|
+
private sendDaemonStarted;
|
|
197
|
+
private handleMessage;
|
|
198
|
+
/**
|
|
199
|
+
* Called when wake word is detected (from wakeword-listener webhook or client).
|
|
200
|
+
*/
|
|
201
|
+
handleWakeEvent(wakeword: string): void;
|
|
202
|
+
private handleExecuteCommand;
|
|
203
|
+
/**
|
|
204
|
+
* Broadcasts a transcript update to all clients.
|
|
205
|
+
*/
|
|
206
|
+
broadcastTranscript(text: string, isFinal: boolean): void;
|
|
207
|
+
/**
|
|
208
|
+
* Broadcasts an AI response to all clients.
|
|
209
|
+
*/
|
|
210
|
+
broadcastResponse(text: string, commands?: CodmirCommand[]): void;
|
|
211
|
+
/**
|
|
212
|
+
* Broadcasts an error to all clients.
|
|
213
|
+
*/
|
|
214
|
+
broadcastError(message: string, code?: string): void;
|
|
215
|
+
private broadcast;
|
|
216
|
+
private sendToClient;
|
|
217
|
+
private sendToClientRaw;
|
|
218
|
+
/**
|
|
219
|
+
* Shuts down the WebSocket server.
|
|
220
|
+
*/
|
|
221
|
+
shutdown(): Promise<void>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* HTTP server that receives webhook events from the wakeword-listener.
|
|
226
|
+
*/
|
|
227
|
+
declare class VoiceDaemonHttpServer {
|
|
228
|
+
private readonly config;
|
|
229
|
+
private readonly logger;
|
|
230
|
+
private readonly wsServer;
|
|
231
|
+
private readonly server;
|
|
232
|
+
constructor(config: DaemonConfig, logger: Logger, wsServer: VoiceDaemonWebSocketServer);
|
|
233
|
+
/**
|
|
234
|
+
* Starts the HTTP server.
|
|
235
|
+
*/
|
|
236
|
+
start(): void;
|
|
237
|
+
private handleRequest;
|
|
238
|
+
private handleWakewordWebhook;
|
|
239
|
+
/**
|
|
240
|
+
* Shuts down the HTTP server.
|
|
241
|
+
*/
|
|
242
|
+
shutdown(): Promise<void>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Display mode for the CLI renderer.
|
|
247
|
+
*/
|
|
248
|
+
type DisplayMode = "gui" | "terminal" | "compact" | "inline" | "none";
|
|
249
|
+
/**
|
|
250
|
+
* Renderer options.
|
|
251
|
+
*/
|
|
252
|
+
interface RendererOptions {
|
|
253
|
+
/** Display mode. Auto-detected if not specified. */
|
|
254
|
+
mode?: DisplayMode;
|
|
255
|
+
/** Force a specific mode regardless of environment. */
|
|
256
|
+
forceMode?: boolean;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* CLI Renderer that adapts to the environment.
|
|
260
|
+
* Uses GUI overlay when available, falls back to terminal/compact modes.
|
|
261
|
+
*/
|
|
262
|
+
declare class CLIRenderer {
|
|
263
|
+
private readonly mode;
|
|
264
|
+
private terminalBall;
|
|
265
|
+
private inlineIndicator;
|
|
266
|
+
private state;
|
|
267
|
+
private guiProcess;
|
|
268
|
+
constructor(options?: RendererOptions);
|
|
269
|
+
/**
|
|
270
|
+
* Get the current display mode.
|
|
271
|
+
*/
|
|
272
|
+
getMode(): DisplayMode;
|
|
273
|
+
/**
|
|
274
|
+
* Start the renderer.
|
|
275
|
+
*/
|
|
276
|
+
start(): Promise<void>;
|
|
277
|
+
/**
|
|
278
|
+
* Stop the renderer.
|
|
279
|
+
*/
|
|
280
|
+
stop(): void;
|
|
281
|
+
/**
|
|
282
|
+
* Update the assistant state.
|
|
283
|
+
*/
|
|
284
|
+
setState(state: AssistantState): void;
|
|
285
|
+
/**
|
|
286
|
+
* Update transcript display.
|
|
287
|
+
*/
|
|
288
|
+
setTranscript(text: string): void;
|
|
289
|
+
/**
|
|
290
|
+
* Update response display.
|
|
291
|
+
*/
|
|
292
|
+
setResponse(text: string): void;
|
|
293
|
+
private startGUI;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Factory function to create the appropriate renderer.
|
|
297
|
+
*/
|
|
298
|
+
declare function createRenderer(options?: RendererOptions): CLIRenderer;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Terminal-based ball renderer for CLI/server environments.
|
|
302
|
+
* Renders the assistant state as ASCII art in the terminal.
|
|
303
|
+
*/
|
|
304
|
+
declare class TerminalBall {
|
|
305
|
+
private state;
|
|
306
|
+
private frameIndex;
|
|
307
|
+
private intervalId;
|
|
308
|
+
private lastTranscript;
|
|
309
|
+
private lastResponse;
|
|
310
|
+
private isRunning;
|
|
311
|
+
private readonly compact;
|
|
312
|
+
constructor(options?: {
|
|
313
|
+
compact?: boolean;
|
|
314
|
+
});
|
|
315
|
+
/**
|
|
316
|
+
* Start the terminal ball animation.
|
|
317
|
+
*/
|
|
318
|
+
start(): void;
|
|
319
|
+
/**
|
|
320
|
+
* Stop the terminal ball.
|
|
321
|
+
*/
|
|
322
|
+
stop(): void;
|
|
323
|
+
/**
|
|
324
|
+
* Update the assistant state.
|
|
325
|
+
*/
|
|
326
|
+
setState(state: AssistantState): void;
|
|
327
|
+
/**
|
|
328
|
+
* Update the transcript display.
|
|
329
|
+
*/
|
|
330
|
+
setTranscript(text: string): void;
|
|
331
|
+
/**
|
|
332
|
+
* Update the response display.
|
|
333
|
+
*/
|
|
334
|
+
setResponse(text: string): void;
|
|
335
|
+
/**
|
|
336
|
+
* Get the current state.
|
|
337
|
+
*/
|
|
338
|
+
getState(): AssistantState;
|
|
339
|
+
private render;
|
|
340
|
+
private getFrames;
|
|
341
|
+
private renderCompact;
|
|
342
|
+
private renderFull;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Simple inline status indicator for logging environments.
|
|
346
|
+
*/
|
|
347
|
+
declare class InlineBallIndicator {
|
|
348
|
+
private state;
|
|
349
|
+
setState(state: AssistantState): void;
|
|
350
|
+
getIndicator(): string;
|
|
351
|
+
getStatusLine(): string;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export { type AssistantState, AssistantStateMachine, CLIRenderer, type CodmirCommand, CommandExecutor, type DaemonConfig, type DisplayMode, InlineBallIndicator, Logger, TerminalBall, VoiceDaemonHttpServer, VoiceDaemonWebSocketServer, createRenderer, loadConfig, normalizeLogLevel };
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log level supported by the daemon logger.
|
|
3
|
+
*/
|
|
4
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
5
|
+
/**
|
|
6
|
+
* Converts a string or undefined into a valid log level.
|
|
7
|
+
* Defaults to "info" if the provided value is invalid.
|
|
8
|
+
*
|
|
9
|
+
* @param value Raw log level value, typically from environment variables.
|
|
10
|
+
*/
|
|
11
|
+
declare function normalizeLogLevel(value?: string): LogLevel;
|
|
12
|
+
/**
|
|
13
|
+
* Simple structured logger used by the voice daemon.
|
|
14
|
+
* Logs to stdout with timestamps and JSON metadata.
|
|
15
|
+
*/
|
|
16
|
+
declare class Logger {
|
|
17
|
+
private level;
|
|
18
|
+
private readonly prefix;
|
|
19
|
+
constructor(level: LogLevel, prefix?: string);
|
|
20
|
+
/**
|
|
21
|
+
* Logs a debug-level message.
|
|
22
|
+
*/
|
|
23
|
+
debug(message: string, meta?: unknown): void;
|
|
24
|
+
/**
|
|
25
|
+
* Logs an info-level message.
|
|
26
|
+
*/
|
|
27
|
+
info(message: string, meta?: unknown): void;
|
|
28
|
+
/**
|
|
29
|
+
* Logs a warning-level message.
|
|
30
|
+
*/
|
|
31
|
+
warn(message: string, meta?: unknown): void;
|
|
32
|
+
/**
|
|
33
|
+
* Logs an error-level message.
|
|
34
|
+
*/
|
|
35
|
+
error(message: string, meta?: unknown): void;
|
|
36
|
+
private log;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Runtime configuration for the codmir voice daemon.
|
|
41
|
+
*/
|
|
42
|
+
interface DaemonConfig {
|
|
43
|
+
/** TCP port for the WebSocket server (localhost only). */
|
|
44
|
+
port: number;
|
|
45
|
+
/** HTTP port for the webhook receiver (wakeword events). */
|
|
46
|
+
httpPort: number;
|
|
47
|
+
/** Log level used by the daemon. */
|
|
48
|
+
logLevel: LogLevel;
|
|
49
|
+
/** URL of the desktop-automation service. */
|
|
50
|
+
desktopAutomationUrl: string;
|
|
51
|
+
/** URL of the TTS worker service. */
|
|
52
|
+
ttsWorkerUrl: string;
|
|
53
|
+
/** URL of the orchestrator service. */
|
|
54
|
+
orchestratorUrl: string;
|
|
55
|
+
/** URL of the overlay service (Python PyQt5 ball UI). */
|
|
56
|
+
overlayUrl: string;
|
|
57
|
+
/** Whether approval is required before executing commands. */
|
|
58
|
+
approvalMode: boolean;
|
|
59
|
+
/** Whether the daemon is muted (ignores wake words). */
|
|
60
|
+
muted: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Loads daemon configuration from environment variables.
|
|
64
|
+
*
|
|
65
|
+
* @param logger Logger instance for debug output.
|
|
66
|
+
*/
|
|
67
|
+
declare function loadConfig(logger: Logger): DaemonConfig;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Voice assistant states for UI overlay.
|
|
71
|
+
*/
|
|
72
|
+
type AssistantState = "idle" | "listening" | "thinking" | "speaking" | "error";
|
|
73
|
+
/**
|
|
74
|
+
* Structured commands that can be executed by the daemon.
|
|
75
|
+
* All commands are logged and require explicit approval in safe mode.
|
|
76
|
+
*/
|
|
77
|
+
type CodmirCommand = {
|
|
78
|
+
type: "open_app";
|
|
79
|
+
name: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: "open_url";
|
|
82
|
+
url: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: "focus_window";
|
|
85
|
+
titleContains: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: "type_text";
|
|
88
|
+
text: string;
|
|
89
|
+
} | {
|
|
90
|
+
type: "press_key";
|
|
91
|
+
key: string;
|
|
92
|
+
} | {
|
|
93
|
+
type: "click";
|
|
94
|
+
button?: number;
|
|
95
|
+
} | {
|
|
96
|
+
type: "scroll";
|
|
97
|
+
direction: "up" | "down";
|
|
98
|
+
amount?: number;
|
|
99
|
+
} | {
|
|
100
|
+
type: "speak";
|
|
101
|
+
text: string;
|
|
102
|
+
voice?: string;
|
|
103
|
+
} | {
|
|
104
|
+
type: "run_script";
|
|
105
|
+
script: string;
|
|
106
|
+
allowListId?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Callback invoked when the assistant state changes.
|
|
111
|
+
*/
|
|
112
|
+
type StateChangeCallback = (newState: AssistantState, previousState: AssistantState) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Manages the voice assistant state machine.
|
|
115
|
+
* States: idle → listening → thinking → speaking → idle
|
|
116
|
+
*/
|
|
117
|
+
declare class AssistantStateMachine {
|
|
118
|
+
private state;
|
|
119
|
+
private readonly logger;
|
|
120
|
+
private readonly listeners;
|
|
121
|
+
constructor(logger: Logger);
|
|
122
|
+
/**
|
|
123
|
+
* Returns the current assistant state.
|
|
124
|
+
*/
|
|
125
|
+
getState(): AssistantState;
|
|
126
|
+
/**
|
|
127
|
+
* Transitions to a new state and notifies listeners.
|
|
128
|
+
*/
|
|
129
|
+
setState(newState: AssistantState): void;
|
|
130
|
+
/**
|
|
131
|
+
* Registers a callback to be invoked on state changes.
|
|
132
|
+
*/
|
|
133
|
+
onStateChange(callback: StateChangeCallback): () => void;
|
|
134
|
+
/**
|
|
135
|
+
* Called when wake word is detected.
|
|
136
|
+
*/
|
|
137
|
+
handleWake(): void;
|
|
138
|
+
/**
|
|
139
|
+
* Called when speech-to-text is complete.
|
|
140
|
+
*/
|
|
141
|
+
handleTranscriptComplete(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Called when AI response is ready and TTS begins.
|
|
144
|
+
*/
|
|
145
|
+
handleSpeakStart(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Called when TTS playback is complete.
|
|
148
|
+
*/
|
|
149
|
+
handleSpeakEnd(): void;
|
|
150
|
+
/**
|
|
151
|
+
* Called on any error, resets to idle.
|
|
152
|
+
*/
|
|
153
|
+
handleError(): void;
|
|
154
|
+
/**
|
|
155
|
+
* Force reset to idle.
|
|
156
|
+
*/
|
|
157
|
+
reset(): void;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Result of executing a command.
|
|
162
|
+
*/
|
|
163
|
+
interface CommandResult {
|
|
164
|
+
success: boolean;
|
|
165
|
+
error?: string;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Executes commands by calling the desktop-automation and TTS services.
|
|
169
|
+
*/
|
|
170
|
+
declare class CommandExecutor {
|
|
171
|
+
private readonly config;
|
|
172
|
+
private readonly logger;
|
|
173
|
+
constructor(config: DaemonConfig, logger: Logger);
|
|
174
|
+
/**
|
|
175
|
+
* Executes a single command.
|
|
176
|
+
*/
|
|
177
|
+
execute(command: CodmirCommand): Promise<CommandResult>;
|
|
178
|
+
private callDesktopAutomation;
|
|
179
|
+
private callTts;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* WebSocket server for the voice daemon.
|
|
184
|
+
* Clients (overlay, CLI, IDE, web) connect here to receive state updates and send commands.
|
|
185
|
+
*/
|
|
186
|
+
declare class VoiceDaemonWebSocketServer {
|
|
187
|
+
private readonly config;
|
|
188
|
+
private readonly logger;
|
|
189
|
+
private readonly stateMachine;
|
|
190
|
+
private readonly executor;
|
|
191
|
+
private readonly wss;
|
|
192
|
+
private readonly clients;
|
|
193
|
+
constructor(config: DaemonConfig, logger: Logger, stateMachine: AssistantStateMachine, executor: CommandExecutor);
|
|
194
|
+
private setupListeners;
|
|
195
|
+
private setupStateListener;
|
|
196
|
+
private sendDaemonStarted;
|
|
197
|
+
private handleMessage;
|
|
198
|
+
/**
|
|
199
|
+
* Called when wake word is detected (from wakeword-listener webhook or client).
|
|
200
|
+
*/
|
|
201
|
+
handleWakeEvent(wakeword: string): void;
|
|
202
|
+
private handleExecuteCommand;
|
|
203
|
+
/**
|
|
204
|
+
* Broadcasts a transcript update to all clients.
|
|
205
|
+
*/
|
|
206
|
+
broadcastTranscript(text: string, isFinal: boolean): void;
|
|
207
|
+
/**
|
|
208
|
+
* Broadcasts an AI response to all clients.
|
|
209
|
+
*/
|
|
210
|
+
broadcastResponse(text: string, commands?: CodmirCommand[]): void;
|
|
211
|
+
/**
|
|
212
|
+
* Broadcasts an error to all clients.
|
|
213
|
+
*/
|
|
214
|
+
broadcastError(message: string, code?: string): void;
|
|
215
|
+
private broadcast;
|
|
216
|
+
private sendToClient;
|
|
217
|
+
private sendToClientRaw;
|
|
218
|
+
/**
|
|
219
|
+
* Shuts down the WebSocket server.
|
|
220
|
+
*/
|
|
221
|
+
shutdown(): Promise<void>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* HTTP server that receives webhook events from the wakeword-listener.
|
|
226
|
+
*/
|
|
227
|
+
declare class VoiceDaemonHttpServer {
|
|
228
|
+
private readonly config;
|
|
229
|
+
private readonly logger;
|
|
230
|
+
private readonly wsServer;
|
|
231
|
+
private readonly server;
|
|
232
|
+
constructor(config: DaemonConfig, logger: Logger, wsServer: VoiceDaemonWebSocketServer);
|
|
233
|
+
/**
|
|
234
|
+
* Starts the HTTP server.
|
|
235
|
+
*/
|
|
236
|
+
start(): void;
|
|
237
|
+
private handleRequest;
|
|
238
|
+
private handleWakewordWebhook;
|
|
239
|
+
/**
|
|
240
|
+
* Shuts down the HTTP server.
|
|
241
|
+
*/
|
|
242
|
+
shutdown(): Promise<void>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Display mode for the CLI renderer.
|
|
247
|
+
*/
|
|
248
|
+
type DisplayMode = "gui" | "terminal" | "compact" | "inline" | "none";
|
|
249
|
+
/**
|
|
250
|
+
* Renderer options.
|
|
251
|
+
*/
|
|
252
|
+
interface RendererOptions {
|
|
253
|
+
/** Display mode. Auto-detected if not specified. */
|
|
254
|
+
mode?: DisplayMode;
|
|
255
|
+
/** Force a specific mode regardless of environment. */
|
|
256
|
+
forceMode?: boolean;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* CLI Renderer that adapts to the environment.
|
|
260
|
+
* Uses GUI overlay when available, falls back to terminal/compact modes.
|
|
261
|
+
*/
|
|
262
|
+
declare class CLIRenderer {
|
|
263
|
+
private readonly mode;
|
|
264
|
+
private terminalBall;
|
|
265
|
+
private inlineIndicator;
|
|
266
|
+
private state;
|
|
267
|
+
private guiProcess;
|
|
268
|
+
constructor(options?: RendererOptions);
|
|
269
|
+
/**
|
|
270
|
+
* Get the current display mode.
|
|
271
|
+
*/
|
|
272
|
+
getMode(): DisplayMode;
|
|
273
|
+
/**
|
|
274
|
+
* Start the renderer.
|
|
275
|
+
*/
|
|
276
|
+
start(): Promise<void>;
|
|
277
|
+
/**
|
|
278
|
+
* Stop the renderer.
|
|
279
|
+
*/
|
|
280
|
+
stop(): void;
|
|
281
|
+
/**
|
|
282
|
+
* Update the assistant state.
|
|
283
|
+
*/
|
|
284
|
+
setState(state: AssistantState): void;
|
|
285
|
+
/**
|
|
286
|
+
* Update transcript display.
|
|
287
|
+
*/
|
|
288
|
+
setTranscript(text: string): void;
|
|
289
|
+
/**
|
|
290
|
+
* Update response display.
|
|
291
|
+
*/
|
|
292
|
+
setResponse(text: string): void;
|
|
293
|
+
private startGUI;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Factory function to create the appropriate renderer.
|
|
297
|
+
*/
|
|
298
|
+
declare function createRenderer(options?: RendererOptions): CLIRenderer;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Terminal-based ball renderer for CLI/server environments.
|
|
302
|
+
* Renders the assistant state as ASCII art in the terminal.
|
|
303
|
+
*/
|
|
304
|
+
declare class TerminalBall {
|
|
305
|
+
private state;
|
|
306
|
+
private frameIndex;
|
|
307
|
+
private intervalId;
|
|
308
|
+
private lastTranscript;
|
|
309
|
+
private lastResponse;
|
|
310
|
+
private isRunning;
|
|
311
|
+
private readonly compact;
|
|
312
|
+
constructor(options?: {
|
|
313
|
+
compact?: boolean;
|
|
314
|
+
});
|
|
315
|
+
/**
|
|
316
|
+
* Start the terminal ball animation.
|
|
317
|
+
*/
|
|
318
|
+
start(): void;
|
|
319
|
+
/**
|
|
320
|
+
* Stop the terminal ball.
|
|
321
|
+
*/
|
|
322
|
+
stop(): void;
|
|
323
|
+
/**
|
|
324
|
+
* Update the assistant state.
|
|
325
|
+
*/
|
|
326
|
+
setState(state: AssistantState): void;
|
|
327
|
+
/**
|
|
328
|
+
* Update the transcript display.
|
|
329
|
+
*/
|
|
330
|
+
setTranscript(text: string): void;
|
|
331
|
+
/**
|
|
332
|
+
* Update the response display.
|
|
333
|
+
*/
|
|
334
|
+
setResponse(text: string): void;
|
|
335
|
+
/**
|
|
336
|
+
* Get the current state.
|
|
337
|
+
*/
|
|
338
|
+
getState(): AssistantState;
|
|
339
|
+
private render;
|
|
340
|
+
private getFrames;
|
|
341
|
+
private renderCompact;
|
|
342
|
+
private renderFull;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Simple inline status indicator for logging environments.
|
|
346
|
+
*/
|
|
347
|
+
declare class InlineBallIndicator {
|
|
348
|
+
private state;
|
|
349
|
+
setState(state: AssistantState): void;
|
|
350
|
+
getIndicator(): string;
|
|
351
|
+
getStatusLine(): string;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export { type AssistantState, AssistantStateMachine, CLIRenderer, type CodmirCommand, CommandExecutor, type DaemonConfig, type DisplayMode, InlineBallIndicator, Logger, TerminalBall, VoiceDaemonHttpServer, VoiceDaemonWebSocketServer, createRenderer, loadConfig, normalizeLogLevel };
|