diff --git a/.changeset/silent-ducks-deny.md b/.changeset/silent-ducks-deny.md new file mode 100644 index 00000000..0bd67d95 --- /dev/null +++ b/.changeset/silent-ducks-deny.md @@ -0,0 +1,5 @@ +--- +'livekit-server-sdk': patch +--- + +updated SIP APIs to include new API options diff --git a/packages/livekit-server-sdk/package.json b/packages/livekit-server-sdk/package.json index ee4ecf6d..dfdd9bb0 100644 --- a/packages/livekit-server-sdk/package.json +++ b/packages/livekit-server-sdk/package.json @@ -42,7 +42,7 @@ "test:edge": "vitest --environment edge-runtime run" }, "dependencies": { - "@livekit/protocol": "^1.29.1", + "@livekit/protocol": "^1.30.0", "camelcase-keys": "^9.0.0", "jose": "^5.1.2" }, diff --git a/packages/livekit-server-sdk/src/SipClient.ts b/packages/livekit-server-sdk/src/SipClient.ts index db35c7dc..c7230824 100644 --- a/packages/livekit-server-sdk/src/SipClient.ts +++ b/packages/livekit-server-sdk/src/SipClient.ts @@ -2,6 +2,7 @@ // // SPDX-License-Identifier: Apache-2.0 import { Duration } from '@bufbuild/protobuf'; +import type { RoomConfiguration, SIPHeaderOptions } from '@livekit/protocol'; import { CreateSIPDispatchRuleRequest, CreateSIPInboundTrunkRequest, @@ -51,20 +52,37 @@ export interface CreateSipTrunkOptions { } export interface CreateSipInboundTrunkOptions { metadata?: string; + /** @deprecated - use `allowedAddresses` instead */ allowed_addresses?: string[]; + allowedAddresses?: string[]; + /** @deprecated - use `allowedNumbers` instead */ allowed_numbers?: string[]; + allowedNumbers?: string[]; + /** @deprecated - use `authUsername` instead */ auth_username?: string; + authUsername?: string; + /** @deprecated - use `authPassword` instead */ auth_password?: string; + authPassword?: string; headers?: { [key: string]: string }; headersToAttributes?: { [key: string]: string }; + // Map SIP response headers from INVITE to sip.h.* participant attributes automatically. + includeHeaders?: SIPHeaderOptions; + krispEnabled?: boolean; } export interface CreateSipOutboundTrunkOptions { metadata?: string; transport: SIPTransport; + /** @deprecated - use `authUsername` instead */ auth_username?: string; + authUsername?: string; + /** @deprecated - use `authPassword` instead */ auth_password?: string; + authPassword?: string; headers?: { [key: string]: string }; headersToAttributes?: { [key: string]: string }; + // Map SIP response headers from INVITE to sip.h.* participant attributes automatically. + includeHeaders?: SIPHeaderOptions; } export interface SipDispatchRuleDirect { @@ -84,16 +102,24 @@ export interface CreateSipDispatchRuleOptions { metadata?: string; trunkIds?: string[]; hidePhoneNumber?: boolean; + attributes?: { [key: string]: string }; + roomPreset?: string; + roomConfig?: RoomConfiguration; } export interface CreateSipParticipantOptions { participantIdentity?: string; participantName?: string; participantMetadata?: string; + participantAttributes?: { [key: string]: string }; dtmf?: string; /** @deprecated - use `playDialtone` instead */ playRingtone?: boolean; // Deprecated, use playDialtone instead playDialtone?: boolean; + // These headers are sent as-is and may help identify this call as coming from LiveKit for the other SIP endpoint. + headers?: { [key: string]: string }; + // Map SIP response headers from INVITE to sip.h.* participant attributes automatically. + includeHeaders?: SIPHeaderOptions; hidePhoneNumber?: boolean; ringingTimeout?: number; // Duration in seconds maxCallDuration?: number; // Duration in seconds @@ -102,6 +128,7 @@ export interface CreateSipParticipantOptions { export interface TransferSipParticipantOptions { playDialtone?: boolean; + headers?: { [key: string]: string }; } /** @@ -180,35 +207,22 @@ export class SipClient extends ServiceBase { numbers: string[], opts?: CreateSipInboundTrunkOptions, ): Promise { - let allowedAddresses: string[] | undefined; - let allowedNumbers: string[] | undefined; - let authUsername: string = ''; - let authPassword: string = ''; - let metadata: string = ''; - let headers: { [key: string]: string } = {}; - let headersToAttributes: { [key: string]: string } = {}; - - if (opts !== undefined) { - allowedAddresses = opts.allowed_addresses; - allowedNumbers = opts.allowed_numbers; - authUsername = opts.auth_username || ''; - authPassword = opts.auth_password || ''; - metadata = opts.metadata || ''; - headers = opts.headers || {}; - headersToAttributes = opts.headersToAttributes || {}; + if (opts === undefined) { + opts = {}; } - const req = new CreateSIPInboundTrunkRequest({ trunk: new SIPInboundTrunkInfo({ name: name, numbers: numbers, - metadata: metadata, - allowedAddresses: allowedAddresses, - allowedNumbers: allowedNumbers, - authUsername: authUsername, - authPassword: authPassword, - headers: headers, - headersToAttributes: headersToAttributes, + metadata: opts?.metadata, + allowedAddresses: opts.allowedAddresses ?? opts.allowed_addresses, + allowedNumbers: opts.allowedNumbers ?? opts.allowed_numbers, + authUsername: opts.authUsername ?? opts.auth_username, + authPassword: opts.authPassword ?? opts.auth_password, + headers: opts.headers, + headersToAttributes: opts.headersToAttributes, + includeHeaders: opts.includeHeaders, + krispEnabled: opts.krispEnabled, }), }).toJson(); @@ -233,20 +247,10 @@ export class SipClient extends ServiceBase { numbers: string[], opts?: CreateSipOutboundTrunkOptions, ): Promise { - let authUsername: string = ''; - let authPassword: string = ''; - let transport: SIPTransport = SIPTransport.SIP_TRANSPORT_AUTO; - let metadata: string = ''; - let headers: { [key: string]: string } = {}; - let headersToAttributes: { [key: string]: string } = {}; - - if (opts !== undefined) { - authUsername = opts.auth_username || ''; - authPassword = opts.auth_password || ''; - transport = opts.transport || SIPTransport.SIP_TRANSPORT_AUTO; - metadata = opts.metadata || ''; - headers = opts.headers || {}; - headersToAttributes = opts.headersToAttributes || {}; + if (opts === undefined) { + opts = { + transport: SIPTransport.SIP_TRANSPORT_AUTO, + }; } const req = new CreateSIPOutboundTrunkRequest({ @@ -254,12 +258,13 @@ export class SipClient extends ServiceBase { name: name, address: address, numbers: numbers, - metadata: metadata, - transport: transport, - authUsername: authUsername, - authPassword: authPassword, - headers: headers, - headersToAttributes: headersToAttributes, + metadata: opts.metadata, + transport: opts.transport, + authUsername: opts.authUsername ?? opts.auth_username, + authPassword: opts.authPassword ?? opts.auth_password, + headers: opts.headers, + headersToAttributes: opts.headersToAttributes, + includeHeaders: opts.includeHeaders, }), }).toJson(); @@ -329,18 +334,10 @@ export class SipClient extends ServiceBase { rule: SipDispatchRuleDirect | SipDispatchRuleIndividual, opts?: CreateSipDispatchRuleOptions, ): Promise { - let trunkIds: string[] | undefined; - let hidePhoneNumber: boolean = false; - let name: string = ''; - let metadata: string = ''; - let ruleProto: SIPDispatchRule | undefined = undefined; - - if (opts !== undefined) { - trunkIds = opts.trunkIds; - hidePhoneNumber = opts.hidePhoneNumber || false; - name = opts.name || ''; - metadata = opts.metadata || ''; + if (opts === undefined) { + opts = {}; } + let ruleProto: SIPDispatchRule | undefined = undefined; if (rule.type == 'direct') { ruleProto = new SIPDispatchRule({ rule: { @@ -365,10 +362,13 @@ export class SipClient extends ServiceBase { const req = new CreateSIPDispatchRuleRequest({ rule: ruleProto, - trunkIds: trunkIds, - hidePhoneNumber: hidePhoneNumber, - name: name, - metadata: metadata, + trunkIds: opts.trunkIds, + hidePhoneNumber: opts.hidePhoneNumber, + name: opts.name, + metadata: opts.metadata, + attributes: opts.attributes, + roomPreset: opts.roomPreset, + roomConfig: opts.roomConfig, }).toJson(); const data = await this.rpc.request( @@ -416,48 +416,29 @@ export class SipClient extends ServiceBase { roomName: string, opts?: CreateSipParticipantOptions, ): Promise { - let participantIdentity: string = ''; - let participantName: string = ''; - let participantMetadata: string = ''; - let dtmf: string = ''; - let playRingtone: boolean = false; - let playDialtone: boolean = false; - let hidePhoneNumber: boolean = false; - let ringingTimeout: number | undefined = undefined; - let maxCallDuration: number | undefined = undefined; - let enableKrisp: boolean | undefined = undefined; - - if (opts !== undefined) { - participantIdentity = opts.participantIdentity || ''; - participantName = opts.participantName || ''; - participantMetadata = opts.participantMetadata || ''; - dtmf = opts.dtmf || ''; - playRingtone = opts.playRingtone || false; - playDialtone = opts.playDialtone || playRingtone; // Enable PlayDialtone if either PlayDialtone or playRingtone is set - hidePhoneNumber = opts.hidePhoneNumber || false; - ringingTimeout = opts.ringingTimeout || undefined; - maxCallDuration = opts.maxCallDuration || undefined; - enableKrisp = opts.enableKrisp || undefined; + if (opts === undefined) { + opts = {}; } const req = new CreateSIPParticipantRequest({ sipTrunkId: sipTrunkId, sipCallTo: number, roomName: roomName, - participantIdentity: participantIdentity, - participantName: participantName, - participantMetadata: participantMetadata, - dtmf: dtmf, - playRingtone: playDialtone, - playDialtone: playDialtone, - hidePhoneNumber: hidePhoneNumber, - ringingTimeout: ringingTimeout - ? new Duration({ seconds: BigInt(ringingTimeout) }) + participantIdentity: opts.participantIdentity || 'sip-participant', + participantName: opts.participantName, + participantMetadata: opts.participantMetadata, + dtmf: opts.dtmf, + playDialtone: opts.playDialtone ?? opts.playRingtone, + headers: opts.headers, + hidePhoneNumber: opts.hidePhoneNumber, + includeHeaders: opts.includeHeaders, + ringingTimeout: opts.ringingTimeout + ? new Duration({ seconds: BigInt(opts.ringingTimeout) }) : undefined, - maxCallDuration: maxCallDuration - ? new Duration({ seconds: BigInt(maxCallDuration) }) + maxCallDuration: opts.maxCallDuration + ? new Duration({ seconds: BigInt(opts.maxCallDuration) }) : undefined, - enableKrisp: enableKrisp, + enableKrisp: opts.enableKrisp, }).toJson(); const data = await this.rpc.request( @@ -480,17 +461,16 @@ export class SipClient extends ServiceBase { transferTo: string, opts?: TransferSipParticipantOptions, ): Promise { - let playDialtone: boolean = false; - - if (opts !== undefined) { - playDialtone = opts.playDialtone || false; + if (opts === undefined) { + opts = {}; } const req = new TransferSIPParticipantRequest({ participantIdentity: participantIdentity, roomName: roomName, transferTo: transferTo, - playDialtone: playDialtone, + playDialtone: opts.playDialtone, + headers: opts.headers, }).toJson(); await this.rpc.request( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3459c017..098ef56a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,7 +43,7 @@ importers: version: 2.1.3(eslint@8.57.1) eslint-plugin-import: specifier: ^2.29.1 - version: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + version: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-n: specifier: ^17.9.0 version: 17.10.3(eslint@8.57.1) @@ -242,8 +242,8 @@ importers: packages/livekit-server-sdk: dependencies: '@livekit/protocol': - specifier: ^1.29.1 - version: 1.29.1 + specifier: ^1.30.0 + version: 1.30.0 camelcase-keys: specifier: ^9.0.0 version: 9.1.3 @@ -931,8 +931,8 @@ packages: '@livekit/protocol@1.28.0': resolution: {integrity: sha512-j7ifbZ1TVfrLDQEuyl4M5rOAS8mRNhpgGoSKE4z03gc012hUHThx227bD1M1BfFPTqNFHzpaGCu/HYE/l09dHw==} - '@livekit/protocol@1.29.1': - resolution: {integrity: sha512-OhxXTZlyM5f4ydnAq1p5azzzOtKWmIoCSVtyVj9rgE42zQI5JM1rR9pubVRZovouGSvEDSJx9yL4Js2IlIyM1Q==} + '@livekit/protocol@1.30.0': + resolution: {integrity: sha512-SDI9ShVKj8N3oOSinr8inaxD3FXgmgoJlqN35uU/Yx1sdoDeQbzAuBFox7bYjM+VhnZ1V22ivIDjAsKr00H+XQ==} '@livekit/typed-emitter@3.0.0': resolution: {integrity: sha512-9bl0k4MgBPZu3Qu3R3xy12rmbW17e3bE9yf4YY85gJIQ3ezLEj/uzpKHWBsLaDoL5Mozz8QCgggwIBudYQWeQg==} @@ -3967,7 +3967,7 @@ snapshots: dependencies: '@bufbuild/protobuf': 1.10.0 - '@livekit/protocol@1.29.1': + '@livekit/protocol@1.30.0': dependencies: '@bufbuild/protobuf': 1.10.0 @@ -4971,8 +4971,8 @@ snapshots: '@typescript-eslint/parser': 8.8.1(eslint@8.57.1)(typescript@5.6.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1) eslint-plugin-react: 7.37.1(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -4990,7 +4990,7 @@ snapshots: eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint-plugin-n@17.10.3(eslint@8.57.1))(eslint-plugin-promise@7.1.0(eslint@8.57.1))(eslint@8.57.1): dependencies: eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-n: 17.10.3(eslint@8.57.1) eslint-plugin-promise: 7.1.0(eslint@8.57.1) @@ -5007,33 +5007,33 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.8.1(eslint@8.57.1)(typescript@5.6.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -5044,7 +5044,7 @@ snapshots: eslint: 8.57.1 eslint-compat-utils: 0.5.1(eslint@8.57.1) - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -5055,7 +5055,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.8.1(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3