refactor(server): centralize speech provider resolver typing
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import type pino from "pino";
|
import type pino from "pino";
|
||||||
import type { SpeechToTextProvider, TranscriptionResult } from "../speech/speech-provider.js";
|
import type { SpeechToTextProvider, TranscriptionResult } from "../speech/speech-provider.js";
|
||||||
|
import { toResolver, type Resolvable } from "../speech/provider-resolver.js";
|
||||||
import { maybePersistDebugAudio } from "./stt-debug.js";
|
import { maybePersistDebugAudio } from "./stt-debug.js";
|
||||||
import { parsePcm16MonoWav, parsePcmRateFromFormat } from "../speech/audio.js";
|
import { parsePcm16MonoWav, parsePcmRateFromFormat } from "../speech/audio.js";
|
||||||
import { Pcm16MonoResampler } from "./pcm16-resampler.js";
|
import { Pcm16MonoResampler } from "./pcm16-resampler.js";
|
||||||
@@ -44,11 +45,11 @@ export class STTManager {
|
|||||||
constructor(
|
constructor(
|
||||||
sessionId: string,
|
sessionId: string,
|
||||||
logger: pino.Logger,
|
logger: pino.Logger,
|
||||||
stt: SpeechToTextProvider | null | (() => SpeechToTextProvider | null)
|
stt: Resolvable<SpeechToTextProvider | null>
|
||||||
) {
|
) {
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.logger = logger.child({ module: "agent", component: "stt-manager", sessionId });
|
this.logger = logger.child({ module: "agent", component: "stt-manager", sessionId });
|
||||||
this.resolveStt = typeof stt === "function" ? stt : () => stt;
|
this.resolveStt = toResolver(stt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type pino from "pino";
|
import type pino from "pino";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import type { TextToSpeechProvider } from "../speech/speech-provider.js";
|
import type { TextToSpeechProvider } from "../speech/speech-provider.js";
|
||||||
|
import { toResolver, type Resolvable } from "../speech/provider-resolver.js";
|
||||||
import type { SessionOutboundMessage } from "../messages.js";
|
import type { SessionOutboundMessage } from "../messages.js";
|
||||||
|
|
||||||
interface PendingPlayback {
|
interface PendingPlayback {
|
||||||
@@ -100,10 +101,10 @@ export class TTSManager {
|
|||||||
constructor(
|
constructor(
|
||||||
sessionId: string,
|
sessionId: string,
|
||||||
logger: pino.Logger,
|
logger: pino.Logger,
|
||||||
tts: TextToSpeechProvider | null | (() => TextToSpeechProvider | null)
|
tts: Resolvable<TextToSpeechProvider | null>
|
||||||
) {
|
) {
|
||||||
this.logger = logger.child({ module: "agent", component: "tts-manager", sessionId });
|
this.logger = logger.child({ module: "agent", component: "tts-manager", sessionId });
|
||||||
this.resolveTts = typeof tts === "function" ? tts : () => tts;
|
this.resolveTts = toResolver(tts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import type {
|
|||||||
SpeechToTextProvider,
|
SpeechToTextProvider,
|
||||||
StreamingTranscriptionSession,
|
StreamingTranscriptionSession,
|
||||||
} from "../speech/speech-provider.js";
|
} from "../speech/speech-provider.js";
|
||||||
|
import { toResolver, type Resolvable } from "../speech/provider-resolver.js";
|
||||||
import { parsePcmRateFromFormat, pcm16lePeakAbs } from "../speech/audio.js";
|
import { parsePcmRateFromFormat, pcm16lePeakAbs } from "../speech/audio.js";
|
||||||
|
|
||||||
const PCM_CHANNELS = 1;
|
const PCM_CHANNELS = 1;
|
||||||
@@ -126,19 +127,14 @@ export class DictationStreamManager {
|
|||||||
logger: pino.Logger;
|
logger: pino.Logger;
|
||||||
emit: (msg: DictationStreamOutboundMessage) => void;
|
emit: (msg: DictationStreamOutboundMessage) => void;
|
||||||
sessionId: string;
|
sessionId: string;
|
||||||
stt: SpeechToTextProvider | null | (() => SpeechToTextProvider | null);
|
stt: Resolvable<SpeechToTextProvider | null>;
|
||||||
finalTimeoutMs?: number;
|
finalTimeoutMs?: number;
|
||||||
autoCommitSeconds?: number;
|
autoCommitSeconds?: number;
|
||||||
}) {
|
}) {
|
||||||
this.logger = params.logger.child({ component: "dictation-stream-manager" });
|
this.logger = params.logger.child({ component: "dictation-stream-manager" });
|
||||||
this.emit = params.emit;
|
this.emit = params.emit;
|
||||||
this.sessionId = params.sessionId;
|
this.sessionId = params.sessionId;
|
||||||
if (typeof params.stt === "function") {
|
this.resolveStt = toResolver(params.stt);
|
||||||
this.resolveStt = params.stt;
|
|
||||||
} else {
|
|
||||||
const sttProvider = params.stt;
|
|
||||||
this.resolveStt = () => sttProvider;
|
|
||||||
}
|
|
||||||
this.finalTimeoutMs = params.finalTimeoutMs ?? DEFAULT_DICTATION_FINAL_TIMEOUT_MS;
|
this.finalTimeoutMs = params.finalTimeoutMs ?? DEFAULT_DICTATION_FINAL_TIMEOUT_MS;
|
||||||
this.autoCommitSeconds =
|
this.autoCommitSeconds =
|
||||||
params.autoCommitSeconds ??
|
params.autoCommitSeconds ??
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ import {
|
|||||||
listLocalSpeechModels,
|
listLocalSpeechModels,
|
||||||
type LocalSpeechModelId,
|
type LocalSpeechModelId,
|
||||||
} from "./speech/providers/local/models.js";
|
} from "./speech/providers/local/models.js";
|
||||||
|
import type { Resolvable } from "./speech/provider-resolver.js";
|
||||||
import type { SpeechReadinessSnapshot } from "./speech/speech-runtime.js";
|
import type { SpeechReadinessSnapshot } from "./speech/speech-runtime.js";
|
||||||
import type pino from "pino";
|
import type pino from "pino";
|
||||||
|
|
||||||
@@ -324,8 +325,8 @@ export type SessionOptions = {
|
|||||||
agentManager: AgentManager;
|
agentManager: AgentManager;
|
||||||
agentStorage: AgentStorage;
|
agentStorage: AgentStorage;
|
||||||
createAgentMcpTransport: AgentMcpTransportFactory;
|
createAgentMcpTransport: AgentMcpTransportFactory;
|
||||||
stt: SpeechToTextProvider | null | (() => SpeechToTextProvider | null);
|
stt: Resolvable<SpeechToTextProvider | null>;
|
||||||
tts: TextToSpeechProvider | null | (() => TextToSpeechProvider | null);
|
tts: Resolvable<TextToSpeechProvider | null>;
|
||||||
terminalManager: TerminalManager | null;
|
terminalManager: TerminalManager | null;
|
||||||
voice?: {
|
voice?: {
|
||||||
voiceAgentMcpStdio?: VoiceMcpStdioConfig | null;
|
voiceAgentMcpStdio?: VoiceMcpStdioConfig | null;
|
||||||
@@ -340,7 +341,7 @@ export type SessionOptions = {
|
|||||||
};
|
};
|
||||||
dictation?: {
|
dictation?: {
|
||||||
finalTimeoutMs?: number;
|
finalTimeoutMs?: number;
|
||||||
stt?: SpeechToTextProvider | null | (() => SpeechToTextProvider | null);
|
stt?: Resolvable<SpeechToTextProvider | null>;
|
||||||
localModels?: {
|
localModels?: {
|
||||||
modelsDir: string;
|
modelsDir: string;
|
||||||
defaultModelIds: LocalSpeechModelId[];
|
defaultModelIds: LocalSpeechModelId[];
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export type Resolvable<T> = T | (() => T);
|
||||||
|
|
||||||
|
export function toResolver<T>(value: Resolvable<T>): () => T {
|
||||||
|
if (typeof value === "function") {
|
||||||
|
return value as () => T;
|
||||||
|
}
|
||||||
|
return () => value;
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import type { AgentProviderRuntimeSettingsMap } from "./agent/provider-launch-co
|
|||||||
import { PushTokenStore } from "./push/token-store.js";
|
import { PushTokenStore } from "./push/token-store.js";
|
||||||
import { PushService } from "./push/push-service.js";
|
import { PushService } from "./push/push-service.js";
|
||||||
import type { SpeechToTextProvider, TextToSpeechProvider } from "./speech/speech-provider.js";
|
import type { SpeechToTextProvider, TextToSpeechProvider } from "./speech/speech-provider.js";
|
||||||
|
import type { Resolvable } from "./speech/provider-resolver.js";
|
||||||
import type { SpeechReadinessSnapshot } from "./speech/speech-runtime.js";
|
import type { SpeechReadinessSnapshot } from "./speech/speech-runtime.js";
|
||||||
import type { LocalSpeechModelId } from "./speech/providers/local/models.js";
|
import type { LocalSpeechModelId } from "./speech/providers/local/models.js";
|
||||||
import type {
|
import type {
|
||||||
@@ -94,18 +95,12 @@ export class VoiceAssistantWebSocketServer {
|
|||||||
private readonly pushTokenStore: PushTokenStore;
|
private readonly pushTokenStore: PushTokenStore;
|
||||||
private readonly pushService: PushService;
|
private readonly pushService: PushService;
|
||||||
private readonly createAgentMcpTransport: AgentMcpTransportFactory;
|
private readonly createAgentMcpTransport: AgentMcpTransportFactory;
|
||||||
private readonly stt:
|
private readonly stt: Resolvable<SpeechToTextProvider | null>;
|
||||||
| SpeechToTextProvider
|
private readonly tts: Resolvable<TextToSpeechProvider | null>;
|
||||||
| null
|
|
||||||
| (() => SpeechToTextProvider | null);
|
|
||||||
private readonly tts:
|
|
||||||
| TextToSpeechProvider
|
|
||||||
| null
|
|
||||||
| (() => TextToSpeechProvider | null);
|
|
||||||
private readonly terminalManager: TerminalManager | null;
|
private readonly terminalManager: TerminalManager | null;
|
||||||
private readonly dictation: {
|
private readonly dictation: {
|
||||||
finalTimeoutMs?: number;
|
finalTimeoutMs?: number;
|
||||||
stt?: SpeechToTextProvider | null | (() => SpeechToTextProvider | null);
|
stt?: Resolvable<SpeechToTextProvider | null>;
|
||||||
localModels?: {
|
localModels?: {
|
||||||
modelsDir: string;
|
modelsDir: string;
|
||||||
defaultModelIds: LocalSpeechModelId[];
|
defaultModelIds: LocalSpeechModelId[];
|
||||||
@@ -135,8 +130,8 @@ export class VoiceAssistantWebSocketServer {
|
|||||||
createAgentMcpTransport: AgentMcpTransportFactory,
|
createAgentMcpTransport: AgentMcpTransportFactory,
|
||||||
wsConfig: WebSocketServerConfig,
|
wsConfig: WebSocketServerConfig,
|
||||||
speech?: {
|
speech?: {
|
||||||
stt: SpeechToTextProvider | null | (() => SpeechToTextProvider | null);
|
stt: Resolvable<SpeechToTextProvider | null>;
|
||||||
tts: TextToSpeechProvider | null | (() => TextToSpeechProvider | null);
|
tts: Resolvable<TextToSpeechProvider | null>;
|
||||||
},
|
},
|
||||||
terminalManager?: TerminalManager | null,
|
terminalManager?: TerminalManager | null,
|
||||||
voice?: {
|
voice?: {
|
||||||
@@ -146,7 +141,7 @@ export class VoiceAssistantWebSocketServer {
|
|||||||
},
|
},
|
||||||
dictation?: {
|
dictation?: {
|
||||||
finalTimeoutMs?: number;
|
finalTimeoutMs?: number;
|
||||||
stt?: SpeechToTextProvider | null | (() => SpeechToTextProvider | null);
|
stt?: Resolvable<SpeechToTextProvider | null>;
|
||||||
localModels?: {
|
localModels?: {
|
||||||
modelsDir: string;
|
modelsDir: string;
|
||||||
defaultModelIds: LocalSpeechModelId[];
|
defaultModelIds: LocalSpeechModelId[];
|
||||||
|
|||||||
Reference in New Issue
Block a user