- 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>
115 lines
5.8 KiB
JavaScript
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,
|
|
};
|