Add VoiceOps name mapping fields#3870
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds explicit name-mapping fields and an optional “split agent names from email” fallback for the VoiceOps Send Call Completed action, so customers can control customer/agent naming and fill missing agent names when upstream events only contain emails.
Changes:
- Introduces
customer_*andagent_*mapping fields plusassign_first_last_name_by_splitting_email. - Implements derivation of missing agent + agent-leg names from email local-part before validation/request.
- Updates generated payload types and expands Jest coverage + snapshots for the new behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/destination-actions/src/destinations/voiceops/sendCallCompleted/index.ts | Adds new mapping fields, email-splitting name derivation, and uses derived payload during perform. |
| packages/destination-actions/src/destinations/voiceops/sendCallCompleted/generated-types.ts | Updates Payload typings to include new fields and makes agent-leg names optional. |
| packages/destination-actions/src/destinations/voiceops/sendCallCompleted/tests/index.test.ts | Adds tests for name forwarding and email-derived names; updates prior test naming/expectations. |
| packages/destination-actions/src/destinations/voiceops/sendCallCompleted/tests/snapshots/snapshot.test.ts.snap | Updates action snapshot to reflect new fields. |
| packages/destination-actions/src/destinations/voiceops/tests/snapshots/snapshot.test.ts.snap | Updates destination snapshot to reflect new fields. |
| return { | ||
| first_name: titleCase(nameParts[0]), | ||
| last_name: nameParts.length > 1 ? nameParts.slice(1).map(titleCase).join(' ') : undefined | ||
| } |
| first_name: { | ||
| label: 'First Name', | ||
| description: 'The first name of the agent for this call leg.', | ||
| type: 'string', | ||
| required: true | ||
| type: 'string' | ||
| }, | ||
| last_name: { | ||
| label: 'Last Name', | ||
| description: 'The last name of the agent for this call leg.', | ||
| type: 'string', | ||
| required: true | ||
| type: 'string' | ||
| } |
798e726 to
5362ee8
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
packages/destination-actions/src/destinations/voiceops/sendCallCompleted/index.ts:84
- With the new
assign_first_last_name_by_splitting_emailfeature, these validation errors can become less actionable when names are omitted intentionally (expecting derivation) but derivation fails (e.g., missing/invalidagent_emailon a leg). Consider updating the error text to mention the derivation option and the requirement for a validagent_emailwhen names are not provided (e.g., 'Provide agentLegs.first_name or enable email splitting and supply agentLegs.agent_email').
for (const agentLeg of payload.agentLegs ?? []) {
if (!agentLeg.first_name?.trim()) {
throw new PayloadValidationError('agentLegs.first_name is required for every agent leg entry.')
}
if (!agentLeg.last_name?.trim()) {
throw new PayloadValidationError('agentLegs.last_name is required for every agent leg entry.')
}
}
| customer_first_name: { | ||
| label: 'Customer First Name', | ||
| description: 'The first name for the customer.', | ||
| type: 'string', | ||
| default: { | ||
| '@path': '$.properties.customer_first_name' | ||
| } | ||
| }, |
| agent_first_name: { | ||
| label: 'Agent First Name', | ||
| description: 'The first name for the primary handling agent.', | ||
| type: 'string', | ||
| default: { | ||
| '@path': '$.properties.first_name' | ||
| '@path': '$.properties.agent_first_name' | ||
| } | ||
| }, | ||
| last_name: { | ||
| label: 'Last Name', | ||
| agent_last_name: { | ||
| label: 'Agent Last Name', | ||
| description: 'The last name for the primary handling agent.', | ||
| type: 'string', | ||
| default: { | ||
| '@path': '$.properties.last_name' | ||
| '@path': '$.properties.agent_last_name' | ||
| } | ||
| }, |
| function splitNameFromEmail(email?: string): { first_name?: string; last_name?: string } { | ||
| const localPart = email?.split('@')[0]?.split('+')[0] | ||
| const nameParts = localPart?.split(/[^a-zA-Z0-9]+/).filter(Boolean) ?? [] | ||
|
|
||
| if (nameParts.length === 0) { | ||
| return {} | ||
| } |
| function titleCase(value: string): string { | ||
| return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase() | ||
| } |
| agent_first_name: { | ||
| label: 'Agent First Name', | ||
| description: 'The first name for the primary handling agent.', | ||
| type: 'string', | ||
| default: { | ||
| '@path': '$.properties.first_name' | ||
| '@path': '$.properties.agent_first_name' | ||
| } | ||
| }, | ||
| last_name: { | ||
| label: 'Last Name', | ||
| agent_last_name: { | ||
| label: 'Agent Last Name', | ||
| description: 'The last name for the primary handling agent.', | ||
| type: 'string', | ||
| default: { | ||
| '@path': '$.properties.last_name' | ||
| '@path': '$.properties.agent_last_name' | ||
| } | ||
| }, |
| if (agentLeg.last_name === undefined || agentLeg.last_name === null) { | ||
| throw new PayloadValidationError( | ||
| 'agentLegs.last_name is required for every agent leg entry. Provide first_name and last_name, or enable assign_first_last_name_by_splitting_email and provide an agent_email that can be split. Single-token email local-parts derive an empty last_name.' | ||
| ) | ||
| } |
| /** | ||
| * When enabled, missing agent first and last names are derived from agent email addresses by splitting the email local-part. | ||
| */ | ||
| assign_first_last_name_by_splitting_email?: boolean |
|
Video of test: bf1496384aac109e26b89d1ab0529d13.webm |
What changed
Adds explicit optional name mapping fields to the VoiceOps Send Call Completed action:
When email splitting is enabled, missing primary agent and agent-leg names are derived from the email local-part before the request is sent to VoiceOps. For example, ava-agent@voiceops.com derives Ava / Agent.
Why
VoiceOps customers need clearer mapping controls for customer and agent names, plus a fallback for deriving agent names from email addresses when names are not provided by the source event.
Compatibility
Validation
Note: the local pre-commit hook could not run because it invokes yarn directly and yarn is not on PATH in this shell; the equivalent build/test checks above were run manually.
Segment review note
Before marking this ready for review, attach an Action Tester video showing the new mapping fields and email-splitting behavior with a realistic Call Completed payload.