diff --git a/lib/tasks/llm/index.js b/lib/tasks/llm/index.js index a0c93772..c625e2cb 100644 --- a/lib/tasks/llm/index.js +++ b/lib/tasks/llm/index.js @@ -49,6 +49,22 @@ class TaskLlm extends Task { await this.llmMcpService.init(); } await this.llm.exec(cs, {ep}); + + /* If the *vendor* ended the s2s session itself (WS disconnect, server error, + * etc.) rather than us kill()ing it, the freeswitch media session is still + * bound to the caller's endpoint. Its audio then bleeds into whatever verb + * runs next — most visibly a `dial` that bridges another leg onto the same + * (anchored) endpoint, so the caller/recording hears the agent mixed with the + * transferred party (issue: elevenlabs "not hanging up" / mixed audio). + * Tear the vendor session down now, before any follow-on verb executes. + * Skipped when kill() already deleted it (this.killed) or the call is gone. */ + if (!this.killed && !cs.callGone && cs?.ep?.uuid) { + try { + await this.llm.kill(cs); + } catch (err) { + this.logger.info({err}, 'TaskLlm:exec - error tearing down orphaned s2s media session'); + } + } } async kill(cs) {