mirror of
https://fastgit.cc/github.com/openclaw/openclaw
synced 2026-05-01 06:26:25 +08:00
fix(voice-call): handle Telnyx callback payloads
This commit is contained in:
@@ -27,6 +27,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Voice-call/Telnyx: preserve inbound/outbound callback metadata and read transcription text from Telnyx's current `transcription_data` payload.
|
||||
- Codex harness: route native `request_user_input` prompts back to the originating chat, preserve queued follow-up answers, and honor newer app-server command approval amendment decisions.
|
||||
- Codex status: report Codex CLI OAuth as `oauth (codex-cli)` for native `codex/*` sessions instead of showing unknown auth. Fixes #70688. Thanks @jb510.
|
||||
- Codex harness/context-engine: redact context-engine assembly failures before logging, so fallback warnings do not serialize raw error objects. (#70809) Thanks @jalehman.
|
||||
|
||||
@@ -185,4 +185,74 @@ describe("TelnyxProvider.parseWebhookEvent", () => {
|
||||
}
|
||||
expect(event.dedupeKey).toBe("telnyx:req:abc");
|
||||
});
|
||||
|
||||
it("maps call direction and phone numbers from Call Control callbacks", () => {
|
||||
const provider = new TelnyxProvider({
|
||||
apiKey: "KEY123",
|
||||
connectionId: "CONN456",
|
||||
publicKey: undefined,
|
||||
});
|
||||
const result = provider.parseWebhookEvent(
|
||||
createCtx({
|
||||
rawBody: JSON.stringify({
|
||||
data: {
|
||||
id: "evt-inbound",
|
||||
event_type: "call.initiated",
|
||||
payload: {
|
||||
call_control_id: "call-1",
|
||||
direction: "incoming",
|
||||
from: "+15551111111",
|
||||
to: "+15550000000",
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.events).toHaveLength(1);
|
||||
expect(result.events[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
type: "call.initiated",
|
||||
direction: "inbound",
|
||||
from: "+15551111111",
|
||||
to: "+15550000000",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("reads transcription text from Telnyx transcription_data payloads", () => {
|
||||
const provider = new TelnyxProvider({
|
||||
apiKey: "KEY123",
|
||||
connectionId: "CONN456",
|
||||
publicKey: undefined,
|
||||
});
|
||||
const result = provider.parseWebhookEvent(
|
||||
createCtx({
|
||||
rawBody: JSON.stringify({
|
||||
data: {
|
||||
id: "evt-transcription",
|
||||
event_type: "call.transcription",
|
||||
payload: {
|
||||
call_control_id: "call-1",
|
||||
transcription_data: {
|
||||
transcript: "hello this is a test speech",
|
||||
is_final: false,
|
||||
confidence: 0.977219,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(result.events).toHaveLength(1);
|
||||
expect(result.events[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
type: "call.speech",
|
||||
transcript: "hello this is a test speech",
|
||||
isFinal: false,
|
||||
confidence: 0.977219,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,6 +31,21 @@ export interface TelnyxProviderOptions {
|
||||
skipVerification?: boolean;
|
||||
}
|
||||
|
||||
function normalizeTelnyxDirection(
|
||||
direction: string | undefined,
|
||||
): "inbound" | "outbound" | undefined {
|
||||
switch (direction) {
|
||||
case "incoming":
|
||||
case "inbound":
|
||||
return "inbound";
|
||||
case "outgoing":
|
||||
case "outbound":
|
||||
return "outbound";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class TelnyxProvider implements VoiceCallProvider {
|
||||
readonly name = "telnyx" as const;
|
||||
|
||||
@@ -143,6 +158,9 @@ export class TelnyxProvider implements VoiceCallProvider {
|
||||
callId,
|
||||
providerCallId: data.payload?.call_control_id,
|
||||
timestamp: Date.now(),
|
||||
direction: normalizeTelnyxDirection(data.payload?.direction),
|
||||
from: data.payload?.from,
|
||||
to: data.payload?.to,
|
||||
};
|
||||
|
||||
switch (data.event_type) {
|
||||
@@ -169,9 +187,10 @@ export class TelnyxProvider implements VoiceCallProvider {
|
||||
return {
|
||||
...baseEvent,
|
||||
type: "call.speech",
|
||||
transcript: data.payload?.transcription || "",
|
||||
isFinal: data.payload?.is_final ?? true,
|
||||
confidence: data.payload?.confidence,
|
||||
transcript:
|
||||
data.payload?.transcription_data?.transcript ?? data.payload?.transcription ?? "",
|
||||
isFinal: data.payload?.transcription_data?.is_final ?? data.payload?.is_final ?? true,
|
||||
confidence: data.payload?.transcription_data?.confidence ?? data.payload?.confidence,
|
||||
};
|
||||
|
||||
case "call.hangup":
|
||||
@@ -336,10 +355,18 @@ interface TelnyxEvent {
|
||||
payload?: {
|
||||
call_control_id?: string;
|
||||
client_state?: string;
|
||||
direction?: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
text?: string;
|
||||
transcription?: string;
|
||||
is_final?: boolean;
|
||||
confidence?: number;
|
||||
transcription_data?: {
|
||||
transcript?: string;
|
||||
is_final?: boolean;
|
||||
confidence?: number;
|
||||
};
|
||||
hangup_cause?: string;
|
||||
digit?: string;
|
||||
[key: string]: unknown;
|
||||
|
||||
Reference in New Issue
Block a user