Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,28 @@ export const filterAvailableAgents = (agents: BuddyDetails[], logger?): BuddyDet
}
};

/**
* Filters buddy agents by a free-text query across name, dn and id.
*/
export const filterAgentsByQuery = (agents: BuddyDetails[], query: string): BuddyDetails[] => {
Copy link
Contributor Author

@adhmenon adhmenon Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added custom utils here so our presentational layer is not cluttered.
I've tried to optimise it as much as posisble with cursors's help.
Followed a similar logic to what I found in agent desktop.

const searchTerm = (query ?? '').trim().toLowerCase();
if (!searchTerm) return agents ?? [];
return (agents ?? []).filter((agent) =>
`${agent.agentName ?? ''}|${(agent as {dn?: string}).dn ?? ''}|${agent.agentId ?? ''}`
.toLowerCase()
.includes(searchTerm)
);
};

/**
* Returns agents to display for current category, applying search only for Agents tab, since other tabs support via the SDK
*/
export const getAgentsForDisplay = (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason these 2 methods exist separately is because for the other tabs we have paginated lists and hence search was done in SDK.
For buddy agents the list is provided via SDK and we simply need to perform a local search in our widgets.
This is needed as otherwise it was breaking. I don't feel comfortable moving this to SDK as it would mess up the flow of the other search as agents don't have pagination.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is alright for now but we can brainstorm and see how we can fit this in the SDK later.

selectedCategory: 'Agents' | string,
agents: BuddyDetails[],
query: string
): BuddyDetails[] => (selectedCategory === 'Agents' ? filterAgentsByQuery(agents, query) : agents || []);

/**
* Filters available queues
*/
Expand Down Expand Up @@ -655,3 +677,36 @@ export const debounce = <T extends (...args: unknown[]) => unknown>(
};
}
};

/**
* Helpers for Dial Number / Entry Point manual actions
*/
export const shouldAddConsultTransferAction = (
selectedCategory: string,
isEntryPointTabVisible: boolean,
query: string,
entryPoints: {id: string; name: string}[],
onDialNumberSelect: ((dialNumber: string) => void) | undefined,
onEntryPointSelect: ((entryPointId: string, entryPointName: string) => void) | undefined
): {visible: boolean; onClick?: () => void; title?: string} => {
const DN_REGEX = new RegExp('^[+1][0-9]{3,18}$|^[*#:][+1][0-9*#:]{3,18}$|^[0-9*#:]{3,18}$');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation here follows the same logic we have in agent desktop.
It only is valid for dial number or entrypoint as of now.


const isDial = selectedCategory === 'Dial Number';
const isEntry = selectedCategory === 'Entry Point' && isEntryPointTabVisible;
const valid = DN_REGEX.test(query || '');

if (isDial) {
return valid && onDialNumberSelect
? {visible: true, onClick: () => onDialNumberSelect(query), title: query}
: {visible: false};
}

if (isEntry) {
const match = query ? entryPoints?.find((e) => e.name === query || e.id === query) : null;
return valid && match && onEntryPointSelect
? {visible: true, onClick: () => onEntryPointSelect(match.id, match.name), title: match.name}
: {visible: false};
}

return {visible: false};
};
Loading
Loading