From 629b5b034a78a543ce67f31075780cd8e8604690 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 15:40:03 +0100 Subject: [PATCH] refactor: share openai realtime close capture --- extensions/openai/realtime-provider-shared.ts | 25 +++++++++++++++++++ .../openai/realtime-transcription-provider.ts | 17 ++++--------- extensions/openai/realtime-voice-provider.ts | 17 ++++--------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/extensions/openai/realtime-provider-shared.ts b/extensions/openai/realtime-provider-shared.ts index ebed8b2f871..478cc8f3cee 100644 --- a/extensions/openai/realtime-provider-shared.ts +++ b/extensions/openai/realtime-provider-shared.ts @@ -1,3 +1,4 @@ +import { captureWsEvent } from "openclaw/plugin-sdk/proxy-capture"; import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; export const trimToUndefined = normalizeOptionalString; @@ -31,3 +32,27 @@ export function resolveOpenAIProviderConfigRecord( asObjectRecord(providers?.openai) ?? asObjectRecord(config.openai) ?? asObjectRecord(config) ); } + +export function captureOpenAIRealtimeWsClose(params: { + url: string; + flowId: string; + capability: "realtime-transcription" | "realtime-voice"; + code: unknown; + reasonBuffer: unknown; +}): void { + captureWsEvent({ + url: params.url, + direction: "local", + kind: "ws-close", + flowId: params.flowId, + closeCode: typeof params.code === "number" ? params.code : undefined, + meta: { + provider: "openai", + capability: params.capability, + reason: + Buffer.isBuffer(params.reasonBuffer) && params.reasonBuffer.length > 0 + ? params.reasonBuffer.toString("utf8") + : undefined, + }, + }); +} diff --git a/extensions/openai/realtime-transcription-provider.ts b/extensions/openai/realtime-transcription-provider.ts index e22abf84ea2..80eaa0ca3e6 100644 --- a/extensions/openai/realtime-transcription-provider.ts +++ b/extensions/openai/realtime-transcription-provider.ts @@ -14,6 +14,7 @@ import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-i import WebSocket from "ws"; import { asFiniteNumber, + captureOpenAIRealtimeWsClose, readRealtimeErrorDetail, resolveOpenAIProviderConfigRecord, trimToUndefined, @@ -192,20 +193,12 @@ class OpenAIRealtimeTranscriptionSession implements RealtimeTranscriptionSession }); this.ws.on("close", (code, reasonBuffer) => { - captureWsEvent({ + captureOpenAIRealtimeWsClose({ url, - direction: "local", - kind: "ws-close", flowId: this.flowId, - closeCode: typeof code === "number" ? code : undefined, - meta: { - provider: "openai", - capability: "realtime-transcription", - reason: - Buffer.isBuffer(reasonBuffer) && reasonBuffer.length > 0 - ? reasonBuffer.toString("utf8") - : undefined, - }, + capability: "realtime-transcription", + code, + reasonBuffer, }); this.connected = false; if (this.closed) { diff --git a/extensions/openai/realtime-voice-provider.ts b/extensions/openai/realtime-voice-provider.ts index f508f0d9a95..e27a734fd61 100644 --- a/extensions/openai/realtime-voice-provider.ts +++ b/extensions/openai/realtime-voice-provider.ts @@ -15,6 +15,7 @@ import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-i import WebSocket from "ws"; import { asFiniteNumber, + captureOpenAIRealtimeWsClose, readRealtimeErrorDetail, resolveOpenAIProviderConfigRecord, trimToUndefined, @@ -293,20 +294,12 @@ class OpenAIRealtimeVoiceBridge implements RealtimeVoiceBridge { }); this.ws.on("close", (code, reasonBuffer) => { - captureWsEvent({ + captureOpenAIRealtimeWsClose({ url, - direction: "local", - kind: "ws-close", flowId: this.flowId, - closeCode: typeof code === "number" ? code : undefined, - meta: { - provider: "openai", - capability: "realtime-voice", - reason: - Buffer.isBuffer(reasonBuffer) && reasonBuffer.length > 0 - ? reasonBuffer.toString("utf8") - : undefined, - }, + capability: "realtime-voice", + code, + reasonBuffer, }); this.connected = false; if (this.intentionallyClosed) {