|
1 | 1 | import { randomUUID } from "node:crypto"; |
2 | 2 | import type { OpenClawConfig } from "../config/types.js"; |
3 | 3 | import type { RealtimeVoiceProviderPlugin } from "../plugins/types.js"; |
| 4 | +import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "../shared/number-coercion.js"; |
4 | 5 | import { |
5 | 6 | REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, |
6 | 7 | buildRealtimeVoiceAgentConsultWorkingResponse, |
@@ -275,8 +276,13 @@ function closeRelaySession(session: RelaySession, reason: "completed" | "error")
|
275 | 276 | } |
276 | 277 | |
277 | 278 | function pruneExpiredRelaySessions(nowMs = Date.now()): void { |
| 279 | +const validNowMs = asDateTimestampMs(nowMs); |
| 280 | +if (validNowMs === undefined) { |
| 281 | +return; |
| 282 | +} |
278 | 283 | for (const session of relaySessions.values()) { |
279 | | -if (nowMs > session.expiresAtMs) { |
| 284 | +const expiresAtMs = asDateTimestampMs(session.expiresAtMs); |
| 285 | +if (expiresAtMs === undefined || validNowMs > expiresAtMs) { |
280 | 286 | closeRelaySession(session, "completed"); |
281 | 287 | } |
282 | 288 | } |
@@ -308,7 +314,10 @@ export function createTalkRealtimeRelaySession(
|
308 | 314 | enforceRelaySessionLimits(params.connId); |
309 | 315 | const forceAgentConsultOnFinalTranscript = params.forceAgentConsultOnFinalTranscript === true; |
310 | 316 | const relaySessionId = randomUUID(); |
311 | | -const expiresAtMs = Date.now() + RELAY_SESSION_TTL_MS; |
| 317 | +const expiresAtMs = resolveExpiresAtMsFromDurationMs(RELAY_SESSION_TTL_MS); |
| 318 | +if (expiresAtMs === undefined) { |
| 319 | +throw new Error("Realtime relay session expiry is outside the supported Date range"); |
| 320 | +} |
312 | 321 | const talk = createTalkSessionController( |
313 | 322 | { |
314 | 323 | sessionId: relaySessionId, |
@@ -688,7 +697,15 @@ function ensureRelayTurn(session: RelaySession): string {
|
688 | 697 | |
689 | 698 | function getRelaySession(relaySessionId: string, connId: string): RelaySession { |
690 | 699 | const session = relaySessions.get(relaySessionId); |
691 | | -if (!session || session.connId !== connId || Date.now() > session.expiresAtMs) { |
| 700 | +const nowMs = asDateTimestampMs(Date.now()); |
| 701 | +const expiresAtMs = session ? asDateTimestampMs(session.expiresAtMs) : undefined; |
| 702 | +if ( |
| 703 | +!session || |
| 704 | +session.connId !== connId || |
| 705 | +nowMs === undefined || |
| 706 | +expiresAtMs === undefined || |
| 707 | +nowMs > expiresAtMs |
| 708 | +) { |
692 | 709 | if (session) { |
693 | 710 | closeRelaySession(session, "completed"); |
694 | 711 | } |
|