feat: telephony call transfer (#155)

* transfer call

* fix: ignore completed call status

* chore: refactor telephony

* chore: refactor pipecat engine custom tools and other telephony services

* chore: code refactor

* chore: put back office ambient sound files

* chore: remove transport from engine

* fix: fix alembic revision

* chore: remove set_transferring_call from engine

* fix: send OutputAudio frame and let transport chunk it

* fix: reinstate docker compose

* chore: remove unused transfer-twmil route for caller

* chore: update pipecat submodule

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
Sabiha Khan 2026-02-16 14:33:33 +05:30 committed by GitHub
parent 5d14d17ceb
commit c711920165
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 1965 additions and 128 deletions

File diff suppressed because one or more lines are too long

View file

@ -259,7 +259,9 @@ export type CreateToolRequest = {
type?: 'http_api';
} & HttpApiToolDefinition) | ({
type?: 'end_call';
} & EndCallToolDefinition);
} & EndCallToolDefinition) | ({
type?: 'transfer_call';
} & TransferCallToolDefinition);
};
export type CreateWorkflowRequest = {
@ -857,6 +859,57 @@ export type ToolResponse = {
created_by?: CreatedByResponse | null;
};
/**
* Configuration for Transfer Call tools.
*/
export type TransferCallConfig = {
/**
* Phone number to transfer the call to (E.164 format, e.g., +1234567890)
*/
destination: string;
/**
* Type of message to play before transfer
*/
messageType?: 'none' | 'custom';
/**
* Custom message to play before transferring the call
*/
customMessage?: string | null;
/**
* Maximum time in seconds to wait for destination to answer (5-120 seconds)
*/
timeout?: number;
};
/**
* Request model for initiating a call transfer.
*/
export type TransferCallRequest = {
destination: string;
organization_id: number;
transfer_id: string;
conference_name: string;
timeout?: number | null;
};
/**
* Tool definition for Transfer Call tools.
*/
export type TransferCallToolDefinition = {
/**
* Schema version
*/
schema_version?: number;
/**
* Tool type
*/
type: 'transfer_call';
/**
* Transfer Call configuration
*/
config: TransferCallConfig;
};
/**
* Request model for triggering a call via API
*/
@ -945,7 +998,9 @@ export type UpdateToolRequest = {
type?: 'http_api';
} & HttpApiToolDefinition) | ({
type?: 'end_call';
} & EndCallToolDefinition)) | null;
} & EndCallToolDefinition) | ({
type?: 'transfer_call';
} & TransferCallToolDefinition)) | null;
status?: string | null;
};
@ -1527,6 +1582,62 @@ export type HandleCloudonixCdrApiV1TelephonyCloudonixCdrPostResponses = {
200: unknown;
};
export type InitiateCallTransferApiV1TelephonyCallTransferPostData = {
body: TransferCallRequest;
path?: never;
query?: never;
url: '/api/v1/telephony/call-transfer';
};
export type InitiateCallTransferApiV1TelephonyCallTransferPostErrors = {
/**
* Not found
*/
404: unknown;
/**
* Validation Error
*/
422: HttpValidationError;
};
export type InitiateCallTransferApiV1TelephonyCallTransferPostError = InitiateCallTransferApiV1TelephonyCallTransferPostErrors[keyof InitiateCallTransferApiV1TelephonyCallTransferPostErrors];
export type InitiateCallTransferApiV1TelephonyCallTransferPostResponses = {
/**
* Successful Response
*/
200: unknown;
};
export type CompleteTransferFunctionCallApiV1TelephonyTransferResultTransferIdPostData = {
body?: never;
path: {
transfer_id: string;
};
query?: never;
url: '/api/v1/telephony/transfer-result/{transfer_id}';
};
export type CompleteTransferFunctionCallApiV1TelephonyTransferResultTransferIdPostErrors = {
/**
* Not found
*/
404: unknown;
/**
* Validation Error
*/
422: HttpValidationError;
};
export type CompleteTransferFunctionCallApiV1TelephonyTransferResultTransferIdPostError = CompleteTransferFunctionCallApiV1TelephonyTransferResultTransferIdPostErrors[keyof CompleteTransferFunctionCallApiV1TelephonyTransferResultTransferIdPostErrors];
export type CompleteTransferFunctionCallApiV1TelephonyTransferResultTransferIdPostResponses = {
/**
* Successful Response
*/
200: unknown;
};
export type ImpersonateApiV1SuperuserImpersonatePostData = {
body: ImpersonateRequest;
headers?: {