wbxcallprov/src/constants.js
jmcqueen 93b060bc8b Modernize bot to Node.js 22 with modular architecture and remote SIW agent
- Refactor monolithic index.js (2646 lines) into src/{webex,integrations,
  cards,flows,commands,services} modules; replace node-fetch/form-data
  with native fetch/FormData; move all secrets to .env via dotenv
- Add dockerized remote SIW agent (docker/remote-agent/) with cross-arch
  buildx packaging (arm64 Mac -> linux/amd64), idempotent install.sh
  deploy bundle, and docker-free ZIP inspector for arch verification
- Bot hosts a WebSocket server; agent proxies SIW requests with a
  per-request insecure:true flag, replacing the process-wide
  NODE_TLS_REJECT_UNAUTHORIZED bypass
- Add ESLint flat config + Prettier, rewrite Dockerfile as non-root
  multi-stage node:22-alpine build, README covering setup / deploy /
  remote agent workflow
- Fix parseStoreArg to read trigger.prompt correctly (was indexing past
  the framework's post-match slice); register /help as regex (string
  matcher only compares the first token); switch catch-all to /.+/
  (previous /.*/gim was stateful due to the g flag); remove
  /fixDisplayNames command and its flow/card

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 14:48:51 -04:00

115 lines
5.8 KiB
JavaScript

// Organization-scoped identifiers pulled out of the legacy index.js.
// These are not secrets (they are Webex resource IDs and SIP details),
// but they are org-specific, so keeping them in one file makes future
// tenant/environment changes a single-file diff.
export const WEBEX_API_BASE = 'https://webexapis.com/v1';
export const ROUTE_GROUPS = {
US: {
id: 'Y2lzY29zcGFyazovL3VzL1JPVVRFX0dST1VQLzViMjc1ZmYzLTI0NTUtNDYwOC1iMzI4LTZlMThhOGViMDk1Mg',
name: 'Stores',
},
CA: {
id: 'Y2lzY29zcGFyazovL3VzL1JPVVRFX0dST1VQLzNlZjY5NmVlLThhYzUtNGI3Ni05M2YxLWQ1N2I0NTdiMmRjMA',
name: 'Stores Canada',
},
};
export const MUSIC_ON_HOLD = {
announcementId:
'Y2lzY29zcGFyazovL3VzL0FOTk9VTkNFTUVOVC9mNDExYTY2Yy1jMmRhLTQ3ODgtOTNhYi04OTU1NzBhYjM3N2Q',
fileName: 'MusicOnHold.wav',
};
// Webex license identifiers (subscription-specific).
export const LICENSES = {
// License to add when granting Webex Calling to a store user (BroadCloud).
STORE_CALLING:
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkJDU1REXzAwNDQyMWYyLWQ4NzUtNGNhYi04NjBmLWZlYWVmMzA0ZTExOA',
// License granted to store users during clean-up.
STORE_MEETINGS_ADD:
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkVFXzVhMjg5MDRmLWFmOGUtNDY3ZC1iMTY2LTQ1NWU5YjZjYTIwZF9hZW9zdG9yZXMud2ViZXguY29t',
// Licenses to remove during clean-up (obsolete trial/preview/free tiers).
LEGACY_TO_REMOVE: [
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkZUQ19hMjQ3MzgyOC1hOTgwLTQ3MmYtODE5ZC02YjljY2UwOGU5MmI',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkNGX2VlNWI4YWU3LTExM2EtNGYyNC05ZjQyLTdhNWM0M2ZlNzllZg',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkZUTV9mNWZkZTM1Zi00NzA0LTQ2MGEtODEwZi00YzVkMzUyNDFlNjk',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOk1TXzZiMzYxZmI5LTc5NmQtNGY0Yy1hNGI1LWIwODEzM2JmZmZlNw',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkZNU185ZWNhNzgxNC0zMzEzLTQ2NGYtOTY0Mi0wMjM5ODc1YmM5Zjg',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOldYU0ZSRUVfYWExOWZjNTctZTFmOS00YTkwLTk2MjctYzM2ZjAwZGM5N2YxX2FlbzJnby10ZXN0LndlYmV4LmNvbQ',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkVFXzIwNTM3OGM0LTA2NmYtNDM1ZC04MGZkLTc5MDdiMjJkMDBlMF9hZW8yZ28tcHJldmlldy53ZWJleC5jb20',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOldYU0ZSRUVfN2UxZjFhNDAtOTVjOC00YzkyLWI5MDEtMTA4MmZjNmQ2YWEwX2FlbzJnby53ZWJleC5jb20',
'Y2lzY29zcGFyazovL3VzL0xJQ0VOU0UvZGI5Y2RjMzEtOGY4ZS00MGI0LTkxNmMtOGQ5ZTljOTJlNzBkOkVFX2FjZTJlZjAyLTY2YzEtNDc0OC05YjhmLTRhOTdiNDIwMzdlM19hZW8yZ28ud2ViZXguY29t',
],
};
// Webex meeting sites to enroll every store user in.
export const MEETING_SITES = [
{ siteUrl: 'aeo2go.webex.com', accountType: 'attendee', operation: 'add' },
{ siteUrl: 'aeostores.webex.com', operation: 'add' },
];
export const DEFAULT_DEFAULT_MEETING_SITE = 'aeostores.webex.com';
// Caller-ID / voicemail defaults for a newly built location.
export const CALLER_ID = {
externalCallerIdName: 'American Eagle Outfitters',
locationFallbackNumber: '+15153186064',
customExternalCallerIdName: 'American Eagle',
};
export const VOICE_PORTAL_PASSCODE = '147369';
// Store brand -> greeting audio file (relative to project root).
export const GREETINGS = {
'American Eagle Outfitters': { file: 'greetings/AEGreeting.wav', label: 'AE Greeting' },
Aerie: { file: 'greetings/AerieGreeting.wav', label: 'Aerie Greeting' },
Offline: { file: 'greetings/OfflineGreeting.wav', label: 'Offline Greeting' },
Unsubscribed: { file: 'greetings/UnsubscribedGreeting.wav', label: 'Unsubscribed Greeting' },
};
// Timezone remapping. Webex Calling doesn't accept some IANA zones that Google returns,
// so we translate them to the nearest supported equivalent.
export const TIMEZONE_ALIASES = {
'America/Toronto': 'America/Montreal',
'America/Indiana/Indianapolis': 'America/New_York',
'America/Boise': 'America/Denver',
'America/Detroit': 'America/New_York',
'America/Matamoros': 'America/Chicago',
};
// Standard set of outgoing calling permissions applied to every store location.
export const OUTGOING_CALLING_PERMISSIONS = [
{ callType: 'INTERNAL_CALL', action: 'ALLOW', transferEnabled: true },
{ callType: 'LOCAL', action: 'ALLOW', transferEnabled: false },
{ callType: 'TOLL_FREE', action: 'ALLOW', transferEnabled: false },
{ callType: 'TOLL', action: 'ALLOW', transferEnabled: false },
{ callType: 'NATIONAL', action: 'ALLOW', transferEnabled: false },
{ callType: 'INTERNATIONAL', action: 'BLOCK', transferEnabled: false },
{ callType: 'OPERATOR_ASSISTED', action: 'BLOCK', transferEnabled: false },
{ callType: 'CHARGEABLE_DIRECTORY_ASSISTED', action: 'BLOCK', transferEnabled: false },
{ callType: 'SPECIAL_SERVICES_I', action: 'BLOCK', transferEnabled: false },
{ callType: 'SPECIAL_SERVICES_II', action: 'BLOCK', transferEnabled: false },
{ callType: 'PREMIUM_SERVICES_I', action: 'BLOCK', transferEnabled: false },
{ callType: 'PREMIUM_SERVICES_II', action: 'BLOCK', transferEnabled: false },
{ callType: 'CASUAL', action: 'BLOCK', transferEnabled: false },
{ callType: 'URL_DIALING', action: 'ALLOW', transferEnabled: true },
{ callType: 'UNKNOWN', action: 'ALLOW', transferEnabled: true },
];
export default {
WEBEX_API_BASE,
ROUTE_GROUPS,
MUSIC_ON_HOLD,
LICENSES,
MEETING_SITES,
DEFAULT_DEFAULT_MEETING_SITE,
CALLER_ID,
VOICE_PORTAL_PASSCODE,
GREETINGS,
TIMEZONE_ALIASES,
OUTGOING_CALLING_PERMISSIONS,
};