fix(server): share voice mode state across listeners
This commit is contained in:
@@ -25,6 +25,9 @@ import { resolveNetworkAddresses, resolveRemoteAddresses } from "./server/networ
|
|||||||
import { startDevReleaseMonitor } from "./releases/dev-release-monitor"
|
import { startDevReleaseMonitor } from "./releases/dev-release-monitor"
|
||||||
import { SpeechService } from "./speech/service"
|
import { SpeechService } from "./speech/service"
|
||||||
import { SideCarManager } from "./sidecars/manager"
|
import { SideCarManager } from "./sidecars/manager"
|
||||||
|
import { ClientConnectionManager } from "./clients/connection-manager"
|
||||||
|
import { PluginChannelManager } from "./plugins/channel"
|
||||||
|
import { VoiceModeManager } from "./plugins/voice-mode"
|
||||||
|
|
||||||
const require = createRequire(import.meta.url)
|
const require = createRequire(import.meta.url)
|
||||||
|
|
||||||
@@ -378,6 +381,14 @@ async function main() {
|
|||||||
|
|
||||||
const remoteAccessEnabled = options.host === "0.0.0.0" || !isLoopbackHost(options.host)
|
const remoteAccessEnabled = options.host === "0.0.0.0" || !isLoopbackHost(options.host)
|
||||||
|
|
||||||
|
const clientConnectionManager = new ClientConnectionManager(logger.child({ component: "client-connections" }))
|
||||||
|
const pluginChannel = new PluginChannelManager(logger.child({ component: "plugin-channel" }))
|
||||||
|
const voiceModeManager = new VoiceModeManager({
|
||||||
|
connections: clientConnectionManager,
|
||||||
|
channel: pluginChannel,
|
||||||
|
logger: logger.child({ component: "voice-mode" }),
|
||||||
|
})
|
||||||
|
|
||||||
const httpsPortExplicit = programHasArg(process.argv.slice(2), "--https-port") || Boolean(process.env.CLI_HTTPS_PORT)
|
const httpsPortExplicit = programHasArg(process.argv.slice(2), "--https-port") || Boolean(process.env.CLI_HTTPS_PORT)
|
||||||
const httpPortExplicit = programHasArg(process.argv.slice(2), "--http-port") || Boolean(process.env.CLI_HTTP_PORT)
|
const httpPortExplicit = programHasArg(process.argv.slice(2), "--http-port") || Boolean(process.env.CLI_HTTP_PORT)
|
||||||
|
|
||||||
@@ -408,6 +419,9 @@ async function main() {
|
|||||||
speechService,
|
speechService,
|
||||||
sidecarManager,
|
sidecarManager,
|
||||||
authManager,
|
authManager,
|
||||||
|
clientConnectionManager,
|
||||||
|
pluginChannel,
|
||||||
|
voiceModeManager,
|
||||||
uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
|
uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
|
||||||
uiDevServerUrl: uiResolution.uiDevServerUrl,
|
uiDevServerUrl: uiResolution.uiDevServerUrl,
|
||||||
logger,
|
logger,
|
||||||
@@ -430,6 +444,9 @@ async function main() {
|
|||||||
speechService,
|
speechService,
|
||||||
sidecarManager,
|
sidecarManager,
|
||||||
authManager,
|
authManager,
|
||||||
|
clientConnectionManager,
|
||||||
|
pluginChannel,
|
||||||
|
voiceModeManager,
|
||||||
uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
|
uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR,
|
||||||
uiDevServerUrl: undefined,
|
uiDevServerUrl: undefined,
|
||||||
logger,
|
logger,
|
||||||
@@ -534,6 +551,12 @@ async function main() {
|
|||||||
logger.error({ err: error }, "SideCar manager shutdown failed")
|
logger.error({ err: error }, "SideCar manager shutdown failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
clientConnectionManager.shutdown()
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn({ err: error }, "Client connection manager shutdown failed")
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await workspaceManager.shutdown()
|
await workspaceManager.shutdown()
|
||||||
logger.info("Workspace manager shutdown complete")
|
logger.info("Workspace manager shutdown complete")
|
||||||
|
|||||||
@@ -77,7 +77,10 @@ export class VoiceModeManager {
|
|||||||
this.aggregateByInstance.delete(instanceId)
|
this.aggregateByInstance.delete(instanceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.options.logger.debug({ instanceId, enabled }, "Broadcasting aggregate voice mode")
|
this.options.logger.debug(
|
||||||
|
{ instanceId, enabled },
|
||||||
|
"Broadcasting aggregate voice mode",
|
||||||
|
)
|
||||||
this.options.channel.send(instanceId, buildVoiceModeEvent(enabled))
|
this.options.channel.send(instanceId, buildVoiceModeEvent(enabled))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ interface HttpServerDeps {
|
|||||||
speechService: SpeechService
|
speechService: SpeechService
|
||||||
sidecarManager: SideCarManager
|
sidecarManager: SideCarManager
|
||||||
authManager: AuthManager
|
authManager: AuthManager
|
||||||
|
clientConnectionManager: ClientConnectionManager
|
||||||
|
pluginChannel: PluginChannelManager
|
||||||
|
voiceModeManager: VoiceModeManager
|
||||||
uiStaticDir: string
|
uiStaticDir: string
|
||||||
uiDevServerUrl?: string
|
uiDevServerUrl?: string
|
||||||
logger: Logger
|
logger: Logger
|
||||||
@@ -182,13 +185,6 @@ export function createHttpServer(deps: HttpServerDeps) {
|
|||||||
eventBus: deps.eventBus,
|
eventBus: deps.eventBus,
|
||||||
logger: deps.logger.child({ component: "background-processes" }),
|
logger: deps.logger.child({ component: "background-processes" }),
|
||||||
})
|
})
|
||||||
const clientConnectionManager = new ClientConnectionManager(deps.logger.child({ component: "client-connections" }))
|
|
||||||
const pluginChannel = new PluginChannelManager(deps.logger.child({ component: "plugin-channel" }))
|
|
||||||
const voiceModeManager = new VoiceModeManager({
|
|
||||||
connections: clientConnectionManager,
|
|
||||||
channel: pluginChannel,
|
|
||||||
logger: deps.logger.child({ component: "voice-mode" }),
|
|
||||||
})
|
|
||||||
|
|
||||||
registerAuthRoutes(app, { authManager: deps.authManager })
|
registerAuthRoutes(app, { authManager: deps.authManager })
|
||||||
|
|
||||||
@@ -268,7 +264,7 @@ export function createHttpServer(deps: HttpServerDeps) {
|
|||||||
eventBus: deps.eventBus,
|
eventBus: deps.eventBus,
|
||||||
registerClient: registerSseClient,
|
registerClient: registerSseClient,
|
||||||
logger: sseLogger,
|
logger: sseLogger,
|
||||||
connectionManager: clientConnectionManager,
|
connectionManager: deps.clientConnectionManager,
|
||||||
})
|
})
|
||||||
registerWorktreeRoutes(app, { workspaceManager: deps.workspaceManager })
|
registerWorktreeRoutes(app, { workspaceManager: deps.workspaceManager })
|
||||||
registerStorageRoutes(app, {
|
registerStorageRoutes(app, {
|
||||||
@@ -289,8 +285,8 @@ export function createHttpServer(deps: HttpServerDeps) {
|
|||||||
workspaceManager: deps.workspaceManager,
|
workspaceManager: deps.workspaceManager,
|
||||||
eventBus: deps.eventBus,
|
eventBus: deps.eventBus,
|
||||||
logger: proxyLogger,
|
logger: proxyLogger,
|
||||||
channel: pluginChannel,
|
channel: deps.pluginChannel,
|
||||||
voiceModeManager,
|
voiceModeManager: deps.voiceModeManager,
|
||||||
})
|
})
|
||||||
registerBackgroundProcessRoutes(app, { backgroundProcessManager })
|
registerBackgroundProcessRoutes(app, { backgroundProcessManager })
|
||||||
registerInstanceProxyRoutes(app, { workspaceManager: deps.workspaceManager, logger: proxyLogger })
|
registerInstanceProxyRoutes(app, { workspaceManager: deps.workspaceManager, logger: proxyLogger })
|
||||||
@@ -356,7 +352,6 @@ export function createHttpServer(deps: HttpServerDeps) {
|
|||||||
},
|
},
|
||||||
stop: () => {
|
stop: () => {
|
||||||
closeSseClients()
|
closeSseClients()
|
||||||
clientConnectionManager.shutdown()
|
|
||||||
return app.close()
|
return app.close()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user