@botonic/core 0.57.0-rslib-esm.0 → 0.57.0-rslib-esm.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/lib/constants.js.map +1 -0
  2. package/lib/core-bot.js.map +1 -0
  3. package/lib/debug/index.js.map +1 -0
  4. package/lib/debug/inspector.js.map +1 -0
  5. package/lib/handoff.js.map +1 -0
  6. package/lib/hubtype-service.js.map +1 -0
  7. package/lib/index.js.map +1 -0
  8. package/lib/{esm/models → models}/ai-agents.d.ts +8 -1
  9. package/lib/{esm/models → models}/ai-agents.js +1 -0
  10. package/lib/models/ai-agents.js.map +1 -0
  11. package/lib/models/bot-config.js.map +1 -0
  12. package/lib/models/hubtype-analytics.js.map +1 -0
  13. package/lib/models/index.js.map +1 -0
  14. package/lib/models/legacy-types.js.map +1 -0
  15. package/lib/plugins.js.map +1 -0
  16. package/lib/pusher-utils.js.map +1 -0
  17. package/lib/routing/index.js.map +1 -0
  18. package/lib/routing/router-utils.js.map +1 -0
  19. package/lib/routing/router.js.map +1 -0
  20. package/lib/testing/index.js.map +1 -0
  21. package/lib/utils/bot-config.js.map +1 -0
  22. package/lib/utils/check-providers.js.map +1 -0
  23. package/lib/utils/functional.js.map +1 -0
  24. package/lib/utils/index.js.map +1 -0
  25. package/package.json +14 -14
  26. package/src/models/ai-agents.ts +9 -0
  27. package/lib/esm/constants.js.map +0 -1
  28. package/lib/esm/core-bot.js.map +0 -1
  29. package/lib/esm/debug/index.js.map +0 -1
  30. package/lib/esm/debug/inspector.js.map +0 -1
  31. package/lib/esm/handoff.js.map +0 -1
  32. package/lib/esm/hubtype-service.js.map +0 -1
  33. package/lib/esm/index.js.map +0 -1
  34. package/lib/esm/models/ai-agents.js.map +0 -1
  35. package/lib/esm/models/bot-config.js.map +0 -1
  36. package/lib/esm/models/hubtype-analytics.js.map +0 -1
  37. package/lib/esm/models/index.js.map +0 -1
  38. package/lib/esm/models/legacy-types.js.map +0 -1
  39. package/lib/esm/package.json +0 -3
  40. package/lib/esm/plugins.js.map +0 -1
  41. package/lib/esm/pusher-utils.js.map +0 -1
  42. package/lib/esm/routing/index.js.map +0 -1
  43. package/lib/esm/routing/router-utils.js.map +0 -1
  44. package/lib/esm/routing/router.js.map +0 -1
  45. package/lib/esm/testing/index.js.map +0 -1
  46. package/lib/esm/utils/bot-config.js.map +0 -1
  47. package/lib/esm/utils/check-providers.js.map +0 -1
  48. package/lib/esm/utils/functional.js.map +0 -1
  49. package/lib/esm/utils/index.js.map +0 -1
  50. /package/lib/{esm/constants.d.ts → constants.d.ts} +0 -0
  51. /package/lib/{esm/constants.js → constants.js} +0 -0
  52. /package/lib/{esm/core-bot.d.ts → core-bot.d.ts} +0 -0
  53. /package/lib/{esm/core-bot.js → core-bot.js} +0 -0
  54. /package/lib/{esm/debug → debug}/index.d.ts +0 -0
  55. /package/lib/{esm/debug → debug}/index.js +0 -0
  56. /package/lib/{esm/debug → debug}/inspector.d.ts +0 -0
  57. /package/lib/{esm/debug → debug}/inspector.js +0 -0
  58. /package/lib/{esm/handoff.d.ts → handoff.d.ts} +0 -0
  59. /package/lib/{esm/handoff.js → handoff.js} +0 -0
  60. /package/lib/{esm/hubtype-service.d.ts → hubtype-service.d.ts} +0 -0
  61. /package/lib/{esm/hubtype-service.js → hubtype-service.js} +0 -0
  62. /package/lib/{esm/index.d.ts → index.d.ts} +0 -0
  63. /package/lib/{esm/index.js → index.js} +0 -0
  64. /package/lib/{esm/models → models}/bot-config.d.ts +0 -0
  65. /package/lib/{esm/models → models}/bot-config.js +0 -0
  66. /package/lib/{esm/models → models}/hubtype-analytics.d.ts +0 -0
  67. /package/lib/{esm/models → models}/hubtype-analytics.js +0 -0
  68. /package/lib/{esm/models → models}/index.d.ts +0 -0
  69. /package/lib/{esm/models → models}/index.js +0 -0
  70. /package/lib/{esm/models → models}/legacy-types.d.ts +0 -0
  71. /package/lib/{esm/models → models}/legacy-types.js +0 -0
  72. /package/lib/{esm/plugins.d.ts → plugins.d.ts} +0 -0
  73. /package/lib/{esm/plugins.js → plugins.js} +0 -0
  74. /package/lib/{esm/pusher-utils.d.ts → pusher-utils.d.ts} +0 -0
  75. /package/lib/{esm/pusher-utils.js → pusher-utils.js} +0 -0
  76. /package/lib/{esm/routing → routing}/index.d.ts +0 -0
  77. /package/lib/{esm/routing → routing}/index.js +0 -0
  78. /package/lib/{esm/routing → routing}/router-utils.d.ts +0 -0
  79. /package/lib/{esm/routing → routing}/router-utils.js +0 -0
  80. /package/lib/{esm/routing → routing}/router.d.ts +0 -0
  81. /package/lib/{esm/routing → routing}/router.js +0 -0
  82. /package/lib/{esm/testing → testing}/index.d.ts +0 -0
  83. /package/lib/{esm/testing → testing}/index.js +0 -0
  84. /package/lib/{esm/utils → utils}/bot-config.d.ts +0 -0
  85. /package/lib/{esm/utils → utils}/bot-config.js +0 -0
  86. /package/lib/{esm/utils → utils}/check-providers.d.ts +0 -0
  87. /package/lib/{esm/utils → utils}/check-providers.js +0 -0
  88. /package/lib/{esm/utils → utils}/functional.d.ts +0 -0
  89. /package/lib/{esm/utils → utils}/functional.js +0 -0
  90. /package/lib/{esm/utils → utils}/index.d.ts +0 -0
  91. /package/lib/{esm/utils → utils}/index.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sources":["../src/constants.ts"],"sourcesContent":["export const NOT_FOUND_PATH = '404'\nexport const EMPTY_ACTION_PATH = ''\nexport const PATH_PAYLOAD_IDENTIFIER = '__PATH_PAYLOAD__'\nexport const PATH_PAYLOAD_REGEXP = new RegExp(\n `\\\\b^${PATH_PAYLOAD_IDENTIFIER}(.*)\\\\b`\n)\n"],"names":["NOT_FOUND_PATH","EMPTY_ACTION_PATH","PATH_PAYLOAD_IDENTIFIER","PATH_PAYLOAD_REGEXP","RegExp"],"mappings":"AAAO,MAAMA,cAAcA,GAAG,MAAK;AAC5B,MAAMC,iBAAiBA,GAAG,GAAE;AAC5B,MAAMC,uBAAuBA,GAAG,mBAAkB;AAClD,MAAMC,mBAAmBA,GAAG,IAAIC,OACrC,CAAC,IAAI,EAAEF,uBAAuBA,CAAC,OAAO,CAAC,EACxC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-bot.js","sources":["../src/core-bot.ts"],"sourcesContent":["import { Inspector } from './debug'\nimport {\n type BotContext,\n BotonicAction,\n type BotRequest,\n type BotResponse,\n type BotSecrets,\n type BotSettings,\n INPUT,\n type Input,\n type ProcessInputResult,\n type ResolvedPlugins,\n type Route,\n type Routes,\n type Session,\n} from './models'\nimport { runPlugins } from './plugins'\nimport { getComputedRoutes, Router } from './routing'\n\nexport interface CoreBotConfig {\n appId?: string\n defaultDelay?: number\n defaultRoutes?: Route[]\n defaultTyping?: number\n inspector?: Inspector\n plugins?: ResolvedPlugins\n renderer: any\n routes: Routes\n theme?: any\n}\n\nexport class CoreBot {\n appId?: string\n defaultDelay: number\n defaultRoutes: Route[]\n defaultTyping: number\n inspector: Inspector\n plugins: ResolvedPlugins\n renderer: any // TODO use a type like ({ request, actions }: RendererArgs) => Promise<any[]>\n rootElement: any\n router: Router | null\n routes: Routes\n theme?: any\n\n constructor({\n renderer,\n routes,\n theme,\n plugins,\n appId,\n defaultTyping = 0.6,\n defaultDelay = 0.4,\n defaultRoutes,\n inspector,\n }: CoreBotConfig) {\n this.renderer = renderer\n this.plugins = plugins || {}\n this.theme = theme || {}\n this.defaultTyping = defaultTyping\n this.defaultDelay = defaultDelay\n this.appId = appId || undefined\n this.rootElement = null\n this.inspector = inspector || new Inspector()\n this.routes = routes\n this.defaultRoutes = defaultRoutes || []\n this.router =\n this.routes instanceof Function\n ? null\n : new Router(\n [...this.routes, ...this.defaultRoutes],\n this.inspector.routeInspector\n )\n }\n\n setSystemLocale(locale: string, session: Session): void {\n session.user.system_locale = locale\n }\n\n setUserLocale(locale: string, session: Session): void {\n session.user.locale = locale\n }\n\n setUserCountry(country: string, session: Session): void {\n session.user.country = country\n }\n\n async input(request: BotRequest): Promise<BotResponse> {\n const botContext = this.getBotContext(request)\n\n const output = await this.runInput(botContext)\n\n if (\n botContext.session._botonic_action?.startsWith(BotonicAction.Redirect)\n ) {\n return await this.runRedirectAction(output, botContext)\n }\n\n return output\n }\n\n private getBotContext(request: BotRequest): BotContext {\n const { input, session, lastRoutePath } = request\n const settings = this.getSettings(request)\n const secrets = this.getSecrets(request)\n\n return {\n input,\n session,\n lastRoutePath,\n params: {},\n plugins: this.plugins,\n defaultTyping: this.defaultTyping,\n defaultDelay: this.defaultDelay,\n getUserCountry: () => session.user.country,\n getUserLocale: () => session.user.locale,\n getSystemLocale: () => session.user.system_locale,\n setUserCountry: (country: string) =>\n this.setUserCountry(country, session),\n setUserLocale: (locale: string) => this.setUserLocale(locale, session),\n setSystemLocale: (locale: string) =>\n this.setSystemLocale(locale, session),\n settings,\n secrets,\n }\n }\n\n private getSettings(request: BotRequest): BotSettings {\n if (!request.settings) {\n // This only happens in local development\n return {\n HUBTYPE_API_URL: '',\n STATIC_URL: '',\n LITELLM_API_URL: '',\n AZURE_OPENAI_API_BASE: '',\n AZURE_OPENAI_API_VERSION: '',\n CUSTOM_SHORT_URL_HOST: '',\n LANGUAGE_DETECTION_ENABLED: false,\n custom: {},\n }\n }\n\n return request.settings\n }\n\n private getSecrets(request: BotRequest): BotSecrets {\n if (!request.secrets) {\n // This only happens in local development\n return {\n HUBTYPE_ACCESS_TOKEN: '',\n LITELLM_API_KEY: '',\n AZURE_OPENAI_API_KEY: '',\n custom: {},\n }\n }\n\n return request.secrets\n }\n\n private async runInput(botContext: BotContext): Promise<BotResponse> {\n // After first updateSession, user country locale and system_locale are always defined\n this.updateSession(botContext.session)\n\n if (botContext.input.type === INPUT.CHAT_EVENT) {\n return {\n input: botContext.input,\n session: botContext.session,\n lastRoutePath: botContext.lastRoutePath,\n settings: botContext.settings,\n secrets: botContext.secrets,\n response: [],\n }\n }\n\n await this.runPrePlugins(botContext)\n\n const output = await this.getOutput(botContext)\n botContext = this.updateRequestFromOutput(botContext, output)\n const response = await this.renderer({\n request: botContext,\n actions: [output.fallbackAction, output.action, output.emptyAction],\n })\n\n await this.runPostPlugins(botContext, response)\n\n botContext.session.is_first_interaction = false\n\n return {\n input: botContext.input,\n session: botContext.session,\n lastRoutePath: botContext.lastRoutePath,\n settings: botContext.settings,\n secrets: botContext.secrets,\n response,\n }\n }\n\n private updateSession(session: Session) {\n // set new user fields (country, locale, system_locale) from old fields in extra_data\n if (!session.user.country) {\n const country = session.user.extra_data?.country\n this.setUserCountry(country, session)\n }\n\n if (!session.user.locale) {\n const language = session.user.extra_data?.language\n this.setUserLocale(language, session)\n }\n\n if (!session.user.system_locale) {\n const locale = session.user.locale\n if (locale) {\n this.setSystemLocale(locale, session)\n }\n }\n }\n\n private async runPrePlugins(botContext: BotContext) {\n if (this.plugins) {\n await runPlugins({ botContext, mode: 'pre' })\n }\n }\n\n private async getOutput(botContext: BotContext): Promise<ProcessInputResult> {\n await this.setRouter(botContext)\n\n const output = (this.router as Router).processInput(\n botContext.input,\n botContext.session,\n botContext.lastRoutePath\n )\n return output\n }\n\n private async setRouter(botContext: BotContext) {\n if (this.routes instanceof Function) {\n this.router = new Router(\n [\n ...(await getComputedRoutes(this.routes, botContext)),\n ...this.defaultRoutes,\n ],\n this.inspector.routeInspector\n )\n }\n }\n\n private updateRequestFromOutput(\n botContext: BotContext,\n output: ProcessInputResult\n ): BotContext {\n return {\n ...botContext,\n params: output.params || {},\n lastRoutePath: output.lastRoutePath,\n }\n }\n\n private async runPostPlugins(botContext: BotContext, response: any) {\n if (this.plugins) {\n await runPlugins({\n botContext,\n mode: 'post',\n response,\n })\n }\n }\n\n private async runRedirectAction(\n previousResponse: BotResponse,\n botContext: BotContext,\n numOfRedirects: number = 0\n ) {\n if (numOfRedirects > 10) {\n throw new Error('Maximum BotAction recursive calls reached (10)')\n }\n\n const nextPayload = botContext.session._botonic_action?.split(\n `${BotonicAction.Redirect}:`\n )[1]\n\n const inputWithBotActionPayload: Input = {\n ...botContext.input,\n payload: nextPayload,\n type: INPUT.POSTBACK,\n data: undefined,\n text: undefined,\n }\n\n botContext.session._botonic_action = undefined\n botContext.input = inputWithBotActionPayload\n\n const followUp = await this.runInput(botContext)\n\n const response: BotResponse = {\n input: followUp.input,\n response: previousResponse.response.concat(followUp.response),\n session: botContext.session,\n lastRoutePath: followUp.lastRoutePath,\n settings: followUp.settings,\n secrets: followUp.secrets,\n }\n\n // Recursive call to handle multiple bot actions in a row\n if (response.session._botonic_action?.startsWith(BotonicAction.Redirect)) {\n return await this.runRedirectAction(\n response,\n botContext,\n numOfRedirects + 1\n )\n }\n\n return response\n }\n}\n"],"names":["Inspector","BotonicAction","INPUT","runPlugins","getComputedRoutes","Router","CoreBot","locale","session","country","request","botContext","output","input","lastRoutePath","settings","secrets","response","language","Function","previousResponse","numOfRedirects","Error","nextPayload","inputWithBotActionPayload","undefined","followUp","renderer","routes","theme","plugins","appId","defaultTyping","defaultDelay","defaultRoutes","inspector"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug/index.js","sources":["../../src/debug/index.ts"],"sourcesContent":["export * from './inspector'\n"],"names":[],"mappings":";AAA2B"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug/inspector.js","sources":["../../src/debug/inspector.ts"],"sourcesContent":["import type { Route, RouteMatcher } from '../models'\nexport class RouteInspector {\n routeMatched(\n _route: Route,\n _routeKey: string,\n _routeValue: RouteMatcher,\n _input: any\n ): void {}\n routeNotMatched(\n _route: Route,\n _routeKey: string,\n _routeValue: RouteMatcher,\n _input: any\n ): void {}\n}\n\nexport class FocusRouteInspector extends RouteInspector {\n focusRoutePaths: string[] | null\n focusOnMatches: boolean\n constructor() {\n super()\n this.focusRoutePaths = null\n this.focusOnMatches = false\n }\n\n focusOnlyOnRoutes(focusRoutePaths: string[]): this {\n this.focusRoutePaths = focusRoutePaths\n return this\n }\n\n focusOnlyOnMatches(): this {\n this.focusOnMatches = true\n return this\n }\n\n _isOnFocus(route: Route): boolean {\n if (this.focusRoutePaths === null) {\n return true\n }\n return this.focusRoutePaths.includes(route.path as string)\n }\n}\n\nexport class LogRouteInspector extends FocusRouteInspector {\n override routeMatched(\n route: Route,\n routeKey: string,\n routeValue: RouteMatcher,\n inputValue: string\n ): void {\n if (!this._isOnFocus(route)) {\n return\n }\n this._log(\n `Route ${this._routeName(route)} selected ` +\n `because Input.${routeKey} (${inputValue}) matched '${routeValue}'`\n )\n }\n\n override routeNotMatched(\n route: Route,\n routeKey: string,\n routeValue: RouteMatcher,\n inputValue: string\n ): void {\n if (!this._isOnFocus(route) || this.focusOnMatches) {\n return\n }\n this._log(\n `Route ${this._routeName(route)} not selected ` +\n `because Input.${routeKey} (${inputValue}) did not match '${routeValue}'`\n )\n }\n\n _routeName(obj: Route): string {\n let name = obj.path || '<<no path defined>>'\n if (obj.action) {\n name = `'${name}' (to action '${obj.action.name}')`\n }\n if (obj.redirect) {\n name = `'${name}' (with redirect to '${obj.redirect}')`\n }\n return name as string\n }\n\n _log(message: string, ...optionalParams: string[]): void {\n console.log(message, ...optionalParams)\n }\n}\n\nexport class Inspector {\n routeInspector: RouteInspector\n constructor(routeInspector: RouteInspector | undefined = undefined) {\n this.routeInspector = routeInspector || new RouteInspector()\n }\n\n getRouteInspector(): RouteInspector {\n return this.routeInspector\n }\n}\n"],"names":["RouteInspector","_route","_routeKey","_routeValue","_input","FocusRouteInspector","focusRoutePaths","route","LogRouteInspector","routeKey","routeValue","inputValue","obj","name","message","optionalParams","console","Inspector","routeInspector","undefined"],"mappings":";;;;;;;;;;;AACO,MAAMA,cAAcA;IACzB,aACEC,MAAa,EACbC,SAAiB,EACjBC,WAAyB,EACzBC,MAAW,EACL,CAAC;IACT,gBACEH,MAAa,EACbC,SAAiB,EACjBC,WAAyB,EACzBC,MAAW,EACL,CAAC;AACX;AAEO,MAAMC,mBAAmBA,SAASL,cAAcA;IASrD,kBAAkBM,eAAyB,EAAQ;QACjD,IAAI,CAAC,eAAe,GAAGA;QACvB,OAAO,IAAI;IACb;IAEA,qBAA2B;QACzB,IAAI,CAAC,cAAc,GAAG;QACtB,OAAO,IAAI;IACb;IAEA,WAAWC,KAAY,EAAW;QAChC,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM;YACjC,OAAO;QACT;QACA,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAACA,MAAM,IAAI;IACjD;IArBA,aAAc;QACZ,KAAK,IAHP,mDACA;QAGE,IAAI,CAAC,eAAe,GAAG;QACvB,IAAI,CAAC,cAAc,GAAG;IACxB;AAkBF;AAEO,MAAMC,iBAAiBA,SAASH,mBAAmBA;IAC/C,aACPE,KAAY,EACZE,QAAgB,EAChBC,UAAwB,EACxBC,UAAkB,EACZ;QACN,IAAI,CAAC,IAAI,CAAC,UAAU,CAACJ,QAAQ;YAC3B;QACF;QACA,IAAI,CAAC,IAAI,CACP,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAACA,OAAO,UAAU,CAAC,GACzC,CAAC,cAAc,EAAEE,SAAS,EAAE,EAAEE,WAAW,WAAW,EAAED,WAAW,CAAC,CAAC;IAEzE;IAES,gBACPH,KAAY,EACZE,QAAgB,EAChBC,UAAwB,EACxBC,UAAkB,EACZ;QACN,IAAI,CAAC,IAAI,CAAC,UAAU,CAACJ,UAAU,IAAI,CAAC,cAAc,EAAE;YAClD;QACF;QACA,IAAI,CAAC,IAAI,CACP,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAACA,OAAO,cAAc,CAAC,GAC7C,CAAC,cAAc,EAAEE,SAAS,EAAE,EAAEE,WAAW,iBAAiB,EAAED,WAAW,CAAC,CAAC;IAE/E;IAEA,WAAWE,GAAU,EAAU;QAC7B,IAAIC,OAAOD,IAAI,IAAI,IAAI;QACvB,IAAIA,IAAI,MAAM,EAAE;YACdC,OAAO,CAAC,CAAC,EAAEA,KAAK,cAAc,EAAED,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD;QACA,IAAIA,IAAI,QAAQ,EAAE;YAChBC,OAAO,CAAC,CAAC,EAAEA,KAAK,qBAAqB,EAAED,IAAI,QAAQ,CAAC,EAAE,CAAC;QACzD;QACA,OAAOC;IACT;IAEA,KAAKC,OAAe,EAAE,GAAGC,cAAwB,EAAQ;QACvDC,QAAQ,GAAG,CAACF,YAAYC;IAC1B;AACF;AAEO,MAAME,SAASA;IAMpB,oBAAoC;QAClC,OAAO,IAAI,CAAC,cAAc;IAC5B;IANA,YAAYC,iBAA6CC,SAAS,CAAE;QADpE;QAEE,IAAI,CAAC,cAAc,GAAGD,kBAAkB,IAAIlB,cAAcA;IAC5D;AAKF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff.js","sources":["../src/handoff.ts"],"sourcesContent":["import axios from 'axios'\n\nimport { PATH_PAYLOAD_IDENTIFIER } from './constants'\nimport {\n BotonicAction,\n type BotonicActionType,\n EVENT_FORMAT_VERSION,\n type Session,\n} from './models'\n\nconst HUBTYPE_API_URL = 'https://api.hubtype.com'\n\nexport interface HubtypeAgentsInfo {\n attending_count: number\n email: string\n idle_count: number\n last_message_sent: string\n status: string\n}\n\nexport interface BackendContext {\n timeoutMs: number\n}\n\nexport interface VacationRange {\n end_date: number // timestamp\n id: number\n start_date: number // timestamp\n}\n\nexport type HandoffExtraData = {\n language?: string\n url?: string\n location?: string\n}\n\nexport interface BotEventData {\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n}\n\nexport interface FormattedBotEventData {\n format_version: number\n flow_id: string\n flow_name: string\n flow_node_id: string\n flow_node_content_id: string\n}\n\nexport enum HelpdeskEvent {\n StatusChanged = 'status_changed',\n AgentMessageCreated = 'agent_message_created',\n QueuePositionChanged = 'queue_position_changed',\n}\n\nfunction contextDefaults(context: any): BackendContext {\n return {\n timeoutMs: context.timeoutMs || 10000,\n }\n}\n\nexport async function getOpenQueues(\n session: Session,\n context = {}\n): Promise<{ queues: string[] }> {\n //be aware of https://github.com/axios/axios/issues/1543\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const endpointUrl = `${baseUrl}/v1/queues/get_open_queues/`\n context = contextDefaults(context)\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: endpointUrl,\n data: { bot_id: session.bot.id },\n timeout: (context as BackendContext).timeoutMs,\n })\n return resp.data\n}\n\nexport class HandOffBuilder {\n _session: Session\n _queue: string\n _onFinish: string\n _email: string\n _agentId: string\n _forceAssignIfNotAvailable: boolean\n _autoAssignOnWaiting: boolean\n _note: string\n _caseInfo: string\n _autoIdleMessage: string\n _shadowing: boolean\n _extraData: HandoffExtraData\n _bot_event: FormattedBotEventData\n _subscribeHelpdeskEvents: HelpdeskEvent[]\n\n constructor(session: Session) {\n this._session = session\n }\n\n withQueue(queueNameOrId: string): this {\n this._queue = queueNameOrId\n return this\n }\n\n withOnFinishPayload(payload: string): this {\n this._onFinish = payload\n return this\n }\n\n withOnFinishPath(path: string): this {\n this._onFinish = `${PATH_PAYLOAD_IDENTIFIER}${path}`\n return this\n }\n\n withAgentEmail(email: string): this {\n this._email = email\n return this\n }\n\n withAgentId(agentId: string): this {\n this._agentId = agentId\n return this\n }\n\n withForceAssignIfNotAvailable(forceAssign: boolean): this {\n this._forceAssignIfNotAvailable = forceAssign\n return this\n }\n\n withAutoAssignOnWaiting(autoAssignOnWaiting: boolean): this {\n this._autoAssignOnWaiting = autoAssignOnWaiting\n return this\n }\n\n withNote(note: string): this {\n this._note = note\n return this\n }\n\n withCaseInfo(caseInfo: string): this {\n this._caseInfo = caseInfo\n return this\n }\n\n withAutoIdleMessage(message: string): this {\n this._autoIdleMessage = message\n return this\n }\n\n withShadowing(shadowing = true): this {\n this._shadowing = shadowing\n return this\n }\n\n withExtraData(extraData: HandoffExtraData): this {\n this._extraData = extraData\n return this\n }\n\n withBotEvent(botEvent: BotEventData): this {\n this._bot_event = {\n format_version: EVENT_FORMAT_VERSION,\n flow_id: botEvent.flowId,\n flow_name: botEvent.flowName,\n flow_node_id: botEvent.flowNodeId,\n flow_node_content_id: botEvent.flowNodeContentId,\n }\n return this\n }\n\n withSubscribeHelpdeskEvents(events: HelpdeskEvent[]): this {\n this._subscribeHelpdeskEvents = events\n return this\n }\n\n async handOff(): Promise<void> {\n return _humanHandOff(\n this._session,\n this._queue,\n this._onFinish,\n this._email,\n this._agentId,\n this._forceAssignIfNotAvailable,\n this._autoAssignOnWaiting,\n this._caseInfo,\n this._note,\n this._autoIdleMessage,\n this._shadowing,\n this._extraData,\n this._bot_event,\n this._subscribeHelpdeskEvents\n )\n }\n}\n\n/**\n * @deprecated use {@link HandOffBuilder} class instead\n */\nexport async function humanHandOff(session, queueNameOrId = '', onFinish) {\n const builder = new HandOffBuilder(session)\n if (queueNameOrId) {\n builder.withQueue(queueNameOrId)\n }\n if (onFinish) {\n if (onFinish.path) {\n builder.withOnFinishPath(onFinish.path)\n } else if (onFinish.payload) {\n builder.withOnFinishPayload(onFinish.payload)\n } else {\n throw new Error('onFinish requires payload or path field')\n }\n }\n return builder.handOff()\n}\n\nexport interface HubtypeHandoffParams {\n queue?: string\n agent_email?: string\n agent_id?: string\n force_assign_if_not_available?: boolean\n auto_assign_on_waiting?: boolean\n case_info?: string\n note?: string\n auto_idle_message?: string\n shadowing?: boolean\n on_finish?: string\n case_extra_data?: HandoffExtraData\n bot_event?: FormattedBotEventData\n subscribe_helpdesk_events?: HelpdeskEvent[]\n}\nasync function _humanHandOff(\n session: Session,\n queueNameOrId = '',\n onFinish: string,\n agentEmail = '',\n agentId = '',\n forceAssignIfNotAvailable = true,\n autoAssignOnWaiting = false,\n caseInfo = '',\n note = '',\n autoIdleMessage = '',\n shadowing = false,\n extraData: HandoffExtraData | undefined = undefined,\n botEvent: FormattedBotEventData,\n subscribeHelpdeskEvents: HelpdeskEvent[] = []\n) {\n const params: HubtypeHandoffParams = {}\n\n params.force_assign_if_not_available = forceAssignIfNotAvailable\n\n if (queueNameOrId) {\n params.queue = queueNameOrId\n }\n if (agentEmail) {\n params.agent_email = agentEmail\n }\n if (agentId) {\n params.agent_id = agentId\n }\n if (autoAssignOnWaiting) {\n params.auto_assign_on_waiting = autoAssignOnWaiting\n }\n if (caseInfo) {\n params.case_info = caseInfo\n }\n if (note) {\n params.note = note\n }\n if (autoIdleMessage) {\n params.auto_idle_message = autoIdleMessage\n }\n if (shadowing) {\n params.shadowing = shadowing\n }\n if (onFinish) {\n params.on_finish = onFinish\n }\n if (extraData) {\n params.case_extra_data = extraData\n }\n if (botEvent) {\n params.bot_event = botEvent\n }\n if (subscribeHelpdeskEvents.length > 0) {\n params.subscribe_helpdesk_events = subscribeHelpdeskEvents\n }\n session._botonic_action = `${BotonicAction.CreateCase}:${JSON.stringify(params)}`\n}\n\nexport async function storeCaseRating(\n session: Session,\n rating: number,\n context: any = {}\n): Promise<{ status: string }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const chatId = session.user.id\n context = contextDefaults(context)\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: `${baseUrl}/v1/chats/${chatId}/store_case_rating/`,\n data: { chat_id: chatId, rating },\n timeout: (context as BackendContext).timeoutMs,\n })\n return resp.data\n}\n\nexport async function getAvailableAgentsByQueue(\n session: Session,\n queueId: string\n): Promise<{ agents: string[] }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: `${baseUrl}/v1/queues/${queueId}/get_available_agents/`,\n })\n return resp.data\n}\n\nexport async function getAvailableAgents(\n session: Session\n): Promise<{ agents: HubtypeAgentsInfo[] }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const botId = session.bot.id\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: `${baseUrl}/v1/bots/${botId}/get_agents/`,\n })\n return resp.data\n}\n\nexport async function getAgentVacationRanges(\n session: Session,\n { agentId, agentEmail }: { agentId?: string; agentEmail?: string }\n): Promise<{ vacation_ranges: VacationRange[] }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const botId = session.bot.id\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'get',\n url: `${baseUrl}/v1/bots/${botId}/get_agent_vacation_ranges/`,\n params: { agent_id: agentId, agent_email: agentEmail },\n })\n return resp.data\n}\n\nexport function cancelHandoff(\n session: Session,\n typification: string | null = null\n): void {\n let action: BotonicActionType = BotonicAction.DiscardCase\n if (typification) {\n action = `${action}:${JSON.stringify({ typification })}`\n }\n session._botonic_action = action\n}\n\nexport function deleteUser(session: Session): void {\n session._botonic_action = BotonicAction.DeleteUser\n}\n"],"names":["axios","PATH_PAYLOAD_IDENTIFIER","BotonicAction","EVENT_FORMAT_VERSION","HUBTYPE_API_URL","HelpdeskEvent","contextDefaults","context","getOpenQueues","session","baseUrl","endpointUrl","resp","HandOffBuilder","queueNameOrId","payload","path","email","agentId","forceAssign","autoAssignOnWaiting","note","caseInfo","message","shadowing","extraData","botEvent","events","_humanHandOff","humanHandOff","onFinish","builder","Error","agentEmail","forceAssignIfNotAvailable","autoIdleMessage","undefined","subscribeHelpdeskEvents","params","JSON","storeCaseRating","rating","chatId","getAvailableAgentsByQueue","queueId","getAvailableAgents","botId","getAgentVacationRanges","cancelHandoff","typification","action","deleteUser"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hubtype-service.js","sources":["../src/hubtype-service.ts"],"sourcesContent":["import axios, { type AxiosResponse } from 'axios'\nimport Pusher, { type AuthOptions, type Channel, type Runtime } from 'pusher-js'\nimport type Channels from 'pusher-js/types/src/core/channels/channels'\n\nimport type { Input, SessionUser } from './models'\nimport { decompressData } from './pusher-utils'\n\ninterface UnsentInput {\n id: string\n ack: number\n unsentInput: Input\n}\n\ninterface BotonicHeaders {\n 'X-BOTONIC-USER-ID': string\n 'X-BOTONIC-LAST-MESSAGE-ID': string\n 'X-BOTONIC-LAST-MESSAGE-UPDATE-DATE': string\n}\n\nexport interface ServerConfig {\n activityTimeout?: number\n pongTimeout?: number\n}\n\ninterface HubtypeServiceArgs {\n appId: string\n user: SessionUser\n lastMessageId?: string\n lastMessageUpdateDate?: string\n onEvent: any\n unsentInputs: () => UnsentInput[]\n server?: ServerConfig\n}\n\nconst WEBCHAT_PUSHER_KEY =\n process.env.WEBCHAT_PUSHER_KEY || '434ca667c8e6cb3f641c' // pragma: allowlist secret\n\nconst HUBTYPE_API_URL = process.env.HUBTYPE_API_URL || 'https://api.hubtype.com'\n\nconst ACTIVITY_TIMEOUT = 20 * 1000 // https://pusher.com/docs/channels/using_channels/connection#activitytimeout-integer-\nconst PONG_TIMEOUT = 5 * 1000 // https://pusher.com/docs/channels/using_channels/connection#pongtimeout-integer-\n\n/**\n * Calls Hubtype APIs from Webchat\n */\nexport class HubtypeService {\n public appId: string\n public user: SessionUser\n public lastMessageId?: string\n public lastMessageUpdateDate?: string\n public onEvent: (event: any) => void\n public unsentInputs: () => UnsentInput[]\n // Pusher 5's CJS default is a namespace under NodeNext. Its named Runtime\n // interface exposes the same constructor without that interop ambiguity.\n public pusher: InstanceType<Parameters<Runtime['setup']>[0]> | null\n public channel: Channel\n public server?: ServerConfig\n public PUSHER_CONNECT_TIMEOUT_MS = 10000\n\n constructor({\n appId,\n user,\n lastMessageId,\n lastMessageUpdateDate,\n onEvent,\n unsentInputs,\n server,\n }: HubtypeServiceArgs) {\n this.appId = appId\n this.user = user || {}\n this.lastMessageId = lastMessageId\n this.lastMessageUpdateDate = lastMessageUpdateDate\n this.onEvent = onEvent\n this.unsentInputs = unsentInputs\n this.server = server\n\n if (this.user.id && (lastMessageId || lastMessageUpdateDate)) {\n // It's safe not awaiting Promise because:\n // * it will never be called from AWS lambda\n // * though init() is called again from postMesage, it does nothing if Pusher already created\n this.init()\n }\n }\n\n init(\n user?: SessionUser,\n lastMessageId?: string,\n lastMessageUpdateDate?: string\n ): Promise<void> {\n if (user) {\n this.user = user\n }\n\n if (lastMessageId) {\n this.lastMessageId = lastMessageId\n }\n\n if (lastMessageUpdateDate) {\n this.lastMessageUpdateDate = lastMessageUpdateDate\n }\n\n return this._initPusher()\n }\n\n _initPusher(): Promise<void> {\n if (this.pusher) {\n return Promise.resolve()\n }\n if (!this.user.id || !this.appId) {\n // TODO recover user & appId somehow\n return Promise.reject('No User or appId. Clear cache and reload')\n }\n this.pusher = new Pusher(WEBCHAT_PUSHER_KEY, {\n cluster: 'eu',\n authEndpoint: `${HUBTYPE_API_URL}/v1/provider_accounts/webhooks/webchat/${this.appId}/auth/`,\n forceTLS: true,\n auth: {\n headers: this.constructHeaders(),\n } as AuthOptions,\n ...this.resolveServerConfig(),\n })\n this.channel = this.pusher.subscribe(this.pusherChannel)\n const connectionPromise = new Promise<void>((resolve, reject) => {\n const cleanAndReject = msg => {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n clearTimeout(connectTimeout)\n this.destroyPusher()\n reject(msg)\n }\n const connectTimeout = setTimeout(\n () => cleanAndReject('Connection Timeout'),\n this.PUSHER_CONNECT_TIMEOUT_MS\n )\n this.channel.bind('pusher:subscription_succeeded', () => {\n // Once subscribed, we know that authentication has been done: https://pusher.com/docs/channels/server_api/authenticating-users\n this.onConnectionRegained()\n clearTimeout(connectTimeout)\n resolve()\n })\n this.channel.bind('botonic_response', data => this.onPusherEvent(data))\n this.channel.bind('botonic_response_compressed', compressedData => {\n try {\n const data = JSON.parse(decompressData(compressedData))\n this.onPusherEvent(data)\n } catch (e) {\n console.error('Error: Unable to decompress data', e)\n }\n })\n this.channel.bind('update_message_info', data => this.onPusherEvent(data))\n\n this.pusher?.connection.bind('error', event => {\n if (event.type === 'WebSocketError') {\n this.handleConnectionChange(false)\n } else {\n const errorMsg = event.error?.data\n ? event.error.data.code || event.error.data.message\n : 'Connection error'\n cleanAndReject(`Pusher error (${errorMsg})`)\n }\n })\n })\n this.pusher.connection.bind('state_change', states => {\n if (states.current === 'connecting') {\n this.updateAuthHeaders()\n }\n if (states.current === 'connected') {\n this.handleConnectionChange(true)\n }\n if (states.current === 'unavailable') {\n this.handleConnectionChange(false)\n }\n })\n\n return connectionPromise\n }\n\n constructHeaders(): BotonicHeaders {\n const headers = {}\n if (this.user?.id) {\n headers['X-BOTONIC-USER-ID'] = this.user.id\n }\n\n if (this.lastMessageId) {\n headers['X-BOTONIC-LAST-MESSAGE-ID'] = this.lastMessageId\n }\n\n if (this.lastMessageUpdateDate) {\n headers['X-BOTONIC-LAST-MESSAGE-UPDATE-DATE'] = this.lastMessageUpdateDate\n }\n\n return headers as BotonicHeaders\n }\n\n resolveServerConfig(): ServerConfig {\n if (!this.server) {\n return { activityTimeout: ACTIVITY_TIMEOUT, pongTimeout: PONG_TIMEOUT }\n }\n return {\n activityTimeout: this.server.activityTimeout || ACTIVITY_TIMEOUT,\n pongTimeout: this.server.pongTimeout || PONG_TIMEOUT,\n }\n }\n\n updateAuthHeaders(): void {\n if (this.pusher) {\n this.pusher.config.auth.headers = {\n ...this.pusher.config.auth.headers,\n ...this.constructHeaders(),\n }\n }\n }\n\n handleConnectionChange(online: boolean): void {\n this.onPusherEvent({ action: 'connectionChange', online })\n }\n\n onPusherEvent(event: any): void {\n if (this.onEvent && typeof this.onEvent === 'function') {\n this.onEvent(event)\n }\n }\n\n get pusherChannel(): string {\n return `private-encrypted-${this.appId}-${this.user.id}`\n }\n\n handleSentInput(message: any): void {\n this.onEvent({\n action: 'update_message_info',\n message: { id: message.id, ack: 1 },\n })\n }\n\n handleUnsentInput(message: any): void {\n this.onEvent({\n action: 'update_message_info',\n message: { id: message.id, ack: 0, unsentInput: message },\n })\n }\n\n async postMessage(user: SessionUser, message: any): Promise<void> {\n try {\n await this.init(user)\n await axios.post(\n `${HUBTYPE_API_URL}/v1/provider_accounts/webhooks/webchat/${this.appId}/`,\n {\n sender: this.user,\n message: message,\n },\n {\n validateStatus: status => status === 200,\n }\n )\n this.handleSentInput(message)\n } catch (_e) {\n this.handleUnsentInput(message)\n }\n return Promise.resolve()\n }\n\n static async getWebchatVisibility(\n appId: string\n ): Promise<AxiosResponse<any>> {\n return axios.get(\n `${HUBTYPE_API_URL}/v1/provider_accounts/${appId}/visibility/`\n )\n }\n\n destroyPusher(): void {\n if (!this.pusher) {\n return\n }\n\n this.pusher.disconnect()\n this.pusher.unsubscribe(this.pusherChannel)\n this.pusher.unbind_all()\n this.pusher.channels = {} as Channels\n this.pusher = null\n }\n\n async onConnectionRegained(): Promise<void> {\n await this.resendUnsentInputs()\n }\n\n async resendUnsentInputs(): Promise<void> {\n for (const message of this.unsentInputs()) {\n message.unsentInput &&\n (await this.postMessage(this.user, message.unsentInput))\n }\n }\n}\n"],"names":["axios","Pusher","decompressData","WEBCHAT_PUSHER_KEY","process","HUBTYPE_API_URL","ACTIVITY_TIMEOUT","PONG_TIMEOUT","HubtypeService","user","lastMessageId","lastMessageUpdateDate","Promise","connectionPromise","resolve","reject","cleanAndReject","msg","clearTimeout","connectTimeout","setTimeout","data","compressedData","JSON","e","console","event","errorMsg","states","headers","online","message","status","_e","appId","onEvent","unsentInputs","server"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["export * from './constants'\nexport * from './core-bot'\nexport * from './debug'\nexport * from './handoff'\nexport * from './hubtype-service'\nexport * from './models'\nexport * from './plugins'\nexport * from './routing'\nexport * from './utils'\n"],"names":[],"mappings":";;;;;;;;;AAA2B;AACD;AACH;AACE;AACQ;AACT;AACC;AACA;AACF"}
@@ -4,6 +4,7 @@ export declare enum OutputMessageType {
4
4
  TextWithButtons = "textWithButtons",
5
5
  BotExecutor = "botExecutor",
6
6
  Carousel = "carousel",
7
+ RequestContactInfo = "requestContactInfo",
7
8
  Exit = "exit"
8
9
  }
9
10
  export interface BaseMessage<T extends string = OutputMessageType> {
@@ -52,10 +53,16 @@ export interface CarouselMessage extends BaseMessage {
52
53
  elements: CarouselElement[];
53
54
  };
54
55
  }
56
+ export interface RequestContactInfoMessage extends BaseMessage {
57
+ type: OutputMessageType.RequestContactInfo;
58
+ content: {
59
+ text: string;
60
+ };
61
+ }
55
62
  export interface ExitMessage extends BaseMessage {
56
63
  type: OutputMessageType.Exit;
57
64
  }
58
- export type OutputMessage<Extra extends BaseMessage<string> = never> = TextMessage | TextWithButtonsMessage | BotExecutorMessage | CarouselMessage | ExitMessage | Extra;
65
+ export type OutputMessage<Extra extends BaseMessage<string> = never> = TextMessage | TextWithButtonsMessage | BotExecutorMessage | CarouselMessage | RequestContactInfoMessage | ExitMessage | Extra;
59
66
  export type AgenticOutputMessage<Extra extends BaseMessage<string> = never> = Exclude<OutputMessage<Extra>, ExitMessage>;
60
67
  export interface ToolExecution {
61
68
  toolName: string;
@@ -3,6 +3,7 @@ var ai_agents_OutputMessageType = /*#__PURE__*/ function(OutputMessageType) {
3
3
  OutputMessageType["TextWithButtons"] = "textWithButtons";
4
4
  OutputMessageType["BotExecutor"] = "botExecutor";
5
5
  OutputMessageType["Carousel"] = "carousel";
6
+ OutputMessageType["RequestContactInfo"] = "requestContactInfo";
6
7
  OutputMessageType["Exit"] = "exit";
7
8
  return OutputMessageType;
8
9
  }({});
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models/ai-agents.js","sources":["../../src/models/ai-agents.ts"],"sourcesContent":["import type { z } from 'zod'\n\nexport enum OutputMessageType {\n Text = 'text',\n TextWithButtons = 'textWithButtons',\n BotExecutor = 'botExecutor',\n Carousel = 'carousel',\n RequestContactInfo = 'requestContactInfo',\n Exit = 'exit',\n}\n\nexport interface BaseMessage<T extends string = OutputMessageType> {\n type: T\n}\n\nexport interface Button {\n text: string\n payload?: string\n url?: string\n target?: string\n}\nexport interface ButtonWithPayload {\n text: string\n payload: string\n}\n\nexport interface TextMessage extends BaseMessage {\n type: OutputMessageType.Text\n content: {\n text: string\n }\n}\n\nexport interface TextWithButtonsMessage extends BaseMessage {\n type: OutputMessageType.TextWithButtons\n content: {\n text: string\n buttons: Button[]\n }\n}\n\nexport interface BotExecutorMessage extends BaseMessage {\n type: OutputMessageType.BotExecutor\n content: {\n text: string\n buttons: ButtonWithPayload[]\n }\n}\n\ninterface CarouselElement {\n title: string\n subtitle: string\n image: string\n button: Button\n}\n\nexport interface CarouselMessage extends BaseMessage {\n type: OutputMessageType.Carousel\n content: {\n text?: string\n elements: CarouselElement[]\n }\n}\n\nexport interface RequestContactInfoMessage extends BaseMessage {\n type: OutputMessageType.RequestContactInfo\n content: {\n text: string\n }\n}\n\nexport interface ExitMessage extends BaseMessage {\n type: OutputMessageType.Exit\n}\n\nexport type OutputMessage<Extra extends BaseMessage<string> = never> =\n | TextMessage\n | TextWithButtonsMessage\n | BotExecutorMessage\n | CarouselMessage\n | RequestContactInfoMessage\n | ExitMessage\n | Extra\n\nexport type AgenticOutputMessage<Extra extends BaseMessage<string> = never> =\n Exclude<OutputMessage<Extra>, ExitMessage>\n\nexport interface ToolExecution {\n toolName: string\n toolArguments: Record<string, any>\n toolResults?: string\n knowledgebaseSourcesIds?: string[]\n knowledgebaseChunksIds?: string[]\n}\n\nexport interface AvailableSpecialist {\n name: string\n description: string\n}\n\nexport interface RunResult<Extra extends BaseMessage<string> = never> {\n messages: AgenticOutputMessage<Extra>[]\n toolsExecuted: ToolExecution[]\n memoryLength: number\n exit: boolean\n error: boolean\n inputGuardrailsTriggered: string[]\n outputGuardrailsTriggered: string[]\n startingAgentName: string\n lastAgentName: string\n availableSpecialists: AvailableSpecialist[]\n isTransferredToSpecialist: boolean\n}\n\nexport type InferenceResponse<Extra extends BaseMessage<string> = never> =\n RunResult<Extra>\n\nexport interface GuardrailRule {\n name: string\n description: string\n}\nexport enum VerbosityLevel {\n Low = 'low',\n Medium = 'medium',\n High = 'high',\n}\n\nexport enum ReasoningEffort {\n None = 'none',\n Low = 'low',\n Medium = 'medium',\n High = 'high',\n}\n\nexport interface HubtypeAssistantMessage {\n role: 'assistant'\n content: string\n}\n\nexport interface HubtypeUserMessage {\n role: 'user'\n content: string\n}\n\nexport enum AiAgentType {\n Specialist = 'specialist',\n Router = 'router',\n}\n\nexport type AiAgentArgs = AiAgentSpecialistArgs | AIAgentRouterArgs\n\nexport type AiAgentBaseArgs = {\n type: AiAgentType\n name: string\n instructions: string\n model: string\n verbosity: VerbosityLevel\n reasoningEffort?: ReasoningEffort\n disableForceRetrieveKnowledge?: boolean // If true, the agent will not force the retrieve knowledge tool to be used.\n inputGuardrailRules?: GuardrailRule[]\n previousHubtypeMessages?: HubtypeAssistantMessage[]\n outputMessagesSchemas?: z.ZodObject<any>[]\n forceToolNameOverride?: string\n}\n\nexport interface AiAgentSpecialistArgs extends AiAgentBaseArgs {\n type: AiAgentType.Specialist\n activeTools: { name: string }[]\n sourceIds: string[]\n}\n\ninterface AIAgentRoute extends AiAgentSpecialistArgs {\n description: string\n}\n\nexport interface AIAgentRouterArgs extends AiAgentBaseArgs {\n type: AiAgentType.Router\n specialists: AIAgentRoute[]\n}\n"],"names":["OutputMessageType","VerbosityLevel","ReasoningEffort","AiAgentType"],"mappings":"AAEO,IAAKA,2BAAiBA,0BAAjBA;;;;;;;WAAAA;MAOX;AAgHM,IAAKC,wBAAcA,0BAAdA;;;;WAAAA;MAIX;AAEM,IAAKC,yBAAeA,0BAAfA;;;;;WAAAA;MAKX;AAYM,IAAKC,qBAAWA,0BAAXA;;;WAAAA;MAGX"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models/bot-config.js","sources":["../../src/models/bot-config.ts"],"sourcesContent":["import type { core } from 'zod'\n\n// This types are used in the bot-config.ts file to load the bot config when deploy a bot.\nexport interface BotConfigJSON {\n tools: ToolConfigJSON[]\n payloads: string[]\n webviews: WebviewConfigJSON[]\n variables?: VariableConfigJSON[]\n}\n\nexport interface ToolConfigJSON {\n name: string\n schema?: core.JSONSchema.JSONSchema\n description: string\n}\n\nexport interface WebviewConfigJSON {\n name: string\n}\n\nexport enum VariableType {\n String = 'string',\n Number = 'number',\n Boolean = 'boolean',\n}\n\nexport interface VariableConfigJSON {\n key_path: string\n type: VariableType\n}\n"],"names":["VariableType"],"mappings":"AAoBO,IAAKA,uBAAYA,0BAAZA;;;;WAAAA;MAIX"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models/hubtype-analytics.js","sources":["../../src/models/hubtype-analytics.ts"],"sourcesContent":["import type { AvailableSpecialist, ToolExecution } from './ai-agents'\n\nexport const EVENT_FORMAT_VERSION = 5\n\nexport enum EventAction {\n AiAgent = 'ai_agent',\n FeedbackCase = 'feedback_case',\n FeedbackMessage = 'feedback_message',\n FeedbackConversation = 'feedback_conversation',\n FeedbackWebview = 'feedback_webview',\n FlowNode = 'flow_node',\n ConditionalCountry = 'conditional_country',\n ConditionalQueueStatus = 'conditional_queue_status',\n ConditionalCustom = 'conditional_custom',\n ConditionalChannel = 'conditional_channel',\n BotAction = 'bot_action',\n WebviewActionTriggered = 'webview_action_triggered',\n HandoffOption = 'handoff_option',\n HandoffSuccess = 'handoff_success',\n HandoffFail = 'handoff_fail',\n Keyword = 'nlu_keyword',\n IntentSmart = 'nlu_intent_smart',\n Fallback = 'fallback',\n WebviewStep = 'webview_step',\n WebviewEnd = 'webview_end',\n Custom = 'custom',\n RedirectFlow = 'redirect_flow',\n CaptureUserInput = 'capture_user_input',\n AiAgentRouter = 'ai_agent_router',\n}\n\nexport interface HtBaseEventProps {\n action: EventAction\n}\n\nexport interface HtBaseEventAllFlowProps extends HtBaseEventProps {\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n flowNodeIsMeaningful: boolean\n}\n\nexport interface EventFeedback extends HtBaseEventProps {\n action:\n | EventAction.FeedbackCase\n | EventAction.FeedbackConversation\n | EventAction.FeedbackMessage\n | EventAction.FeedbackWebview\n feedbackTargetId: string\n feedbackGroupId: string\n possibleOptions: string[]\n possibleValues?: number[]\n option: string\n value?: number\n comment?: string\n}\n\nexport interface EventFlow extends HtBaseEventProps {\n action: EventAction.FlowNode\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n flowNodeIsMeaningful?: boolean\n}\n\nexport interface EventBotAction extends HtBaseEventAllFlowProps {\n action: EventAction.BotAction\n payload: string\n}\n\nexport interface EventConditionalCountry extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalCountry\n country: string\n}\n\nexport interface EventConditionalQueueStatus extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalQueueStatus\n queueId: string\n queueName: string\n isQueueOpen: boolean\n isAvailableAgent: boolean\n}\n\nexport interface EventConditionalCustom extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalCustom\n conditionalVariable: string\n variableFormat: string\n operator: string\n}\n\nexport interface EventConditionalChannel extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalChannel\n channel: string\n}\n\nexport interface EventHandoff extends HtBaseEventProps {\n action: EventAction.HandoffSuccess | EventAction.HandoffFail\n flowThreadId?: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n queueId: string\n queueName: string\n caseId?: string\n isQueueOpen?: boolean\n isAvailableAgent?: boolean\n isThresholdReached?: boolean\n}\n\nexport interface EventHandoffOption extends HtBaseEventProps {\n action: EventAction.HandoffOption\n flowThreadId?: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n queueId?: string\n queueName?: string\n}\n\nexport interface EventKeyword extends HtBaseEventProps {\n action: EventAction.Keyword\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n nluKeywordName: string\n nluKeywordIsRegex?: boolean\n nluKeywordMessageId: string\n userInput: string\n}\n\nexport interface EventIntentSmart extends HtBaseEventProps {\n action: EventAction.IntentSmart\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n nluIntentSmartTitle: string\n nluIntentSmartNumUsed: number\n nluIntentSmartMessageId: string\n userInput: string\n}\n\nexport interface EventWebviewActionTriggered extends HtBaseEventAllFlowProps {\n action: EventAction.WebviewActionTriggered\n webviewTargetId: string\n webviewName: string\n webviewParams?: Record<string, string>\n}\n\nexport interface EventAiAgent extends HtBaseEventAllFlowProps {\n action: EventAction.AiAgent\n toolsExecuted: ToolExecution[]\n inputMessageId: string\n memoryLength: number\n inputGuardrailsTriggered: string[]\n outputGuardrailsTriggered: string[]\n exit: boolean\n error: boolean\n}\n\nexport interface EventAiAgentRouter extends HtBaseEventAllFlowProps {\n action: EventAction.AiAgentRouter\n inputMessageId: string\n memoryLength: number\n inputGuardrailsTriggered: string[]\n outputGuardrailsTriggered: string[]\n exit: boolean\n error: boolean\n startingAgentName: string\n lastAgentName: string\n availableSpecialists: AvailableSpecialist[]\n isTransferredToSpecialist: boolean\n}\n\nexport interface EventRedirectFlow extends HtBaseEventAllFlowProps {\n action: EventAction.RedirectFlow\n flowTargetId: string\n flowTargetName: string\n}\n\nexport interface EventCaptureUserInput extends HtBaseEventAllFlowProps {\n action: EventAction.CaptureUserInput\n fieldName: string\n userInput: string\n captureSuccess: boolean\n messageId: string\n}\n\nexport interface EventFallback extends HtBaseEventProps {\n action: EventAction.Fallback\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n userInput: string\n fallbackOut: number\n fallbackMessageId: string\n}\n\nexport interface EventWebviewStep extends HtBaseEventProps {\n action: EventAction.WebviewStep\n flowThreadId?: string\n webviewThreadId: string\n webviewName: string\n webviewStepName: string\n webviewStepNumber: number\n}\n\nexport interface EventWebviewEnd extends HtBaseEventProps {\n action: EventAction.WebviewEnd\n flowThreadId?: string\n webviewThreadId: string\n webviewName: string\n webviewStepName?: string\n webviewStepNumber?: number\n webviewEndFailType?: WebviewEndFailType\n webviewEndFailMessage?: string\n}\n\nexport enum WebviewEndFailType {\n CanceledByUser = 'canceled_by_user',\n ApiError = 'api_error',\n NeedsEscalation = 'needs_escalation',\n}\n\nexport interface EventCustom extends HtBaseEventProps {\n action: EventAction.Custom\n customFields?: Record<string, any>\n customSensitiveFields?: Record<string, any>\n}\n"],"names":["EVENT_FORMAT_VERSION","EventAction","WebviewEndFailType"],"mappings":"AAEO,MAAMA,oBAAoBA,GAAG,EAAC;AAE9B,IAAKC,6BAAWA,0BAAXA;;;;;;;;;;;;;;;;;;;;;;;;;WAAAA;MAyBX;AAuMM,IAAKC,oCAAkBA,0BAAlBA;;;;WAAAA;MAIX"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models/index.js","sources":["../../src/models/index.ts"],"sourcesContent":["export * from './ai-agents'\nexport * from './bot-config'\nexport * from './hubtype-analytics'\nexport * from './legacy-types'\n"],"names":[],"mappings":";;;;AAA2B;AACC;AACO;AACL"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models/legacy-types.js","sources":["../../src/models/legacy-types.ts"],"sourcesContent":["// TODO: This file contains all the legacy types we had in index.ts. After some refactors, we should be able to get rid of many of them.\n\nexport enum CASE_STATUS {\n WAITING = 'status_waiting',\n ATTENDING = 'status_attending',\n IDLE = 'status_idle',\n RESOLVED = 'status_resolved',\n}\n\nexport type CaseStatusType =\n | CASE_STATUS.ATTENDING\n | CASE_STATUS.IDLE\n | CASE_STATUS.RESOLVED\n | CASE_STATUS.WAITING\n\nexport enum CASE_RESOLUTION {\n OK = 'result_ok',\n NOK = 'result_nok',\n NOT_SOLVED = 'result_not_solved',\n BANNED = 'result_banned',\n}\n\nexport type CaseResolution =\n | CASE_RESOLUTION.BANNED\n | CASE_RESOLUTION.NOK\n | CASE_RESOLUTION.NOT_SOLVED\n | CASE_RESOLUTION.OK\n\nexport enum PROVIDER {\n APPLE = 'apple',\n DEV = 'dev',\n FACEBOOK = 'facebook',\n GENERIC = 'generic',\n INSTAGRAM = 'instagram',\n INTERCOM = 'intercom',\n SMOOCH = 'smooch',\n TELEGRAM = 'telegram',\n TWITTER = 'twitter',\n WEBCHAT = 'webchat',\n WECHAT = 'wechat',\n WHATSAPP = 'whatsapp',\n}\n\nexport type ProviderType =\n | PROVIDER.DEV\n | PROVIDER.FACEBOOK\n | PROVIDER.GENERIC\n | PROVIDER.INSTAGRAM\n | PROVIDER.INTERCOM\n | PROVIDER.SMOOCH\n | PROVIDER.TELEGRAM\n | PROVIDER.TWITTER\n | PROVIDER.WEBCHAT\n | PROVIDER.WECHAT\n | PROVIDER.WHATSAPP\n\nexport enum INPUT {\n TEXT = 'text',\n POSTBACK = 'postback',\n AUDIO = 'audio',\n IMAGE = 'image',\n VIDEO = 'video',\n DOCUMENT = 'document',\n LOCATION = 'location',\n CONTACT = 'contact',\n BUTTON_MESSAGE = 'buttonmessage',\n CAROUSEL = 'carousel',\n CUSTOM = 'custom',\n WEBCHAT_SETTINGS = 'webchatsettings',\n WHATSAPP_TEMPLATE = 'whatsapptemplate',\n RAW = 'raw',\n CHAT_EVENT = 'chatevent',\n WHATSAPP_BUTTON_LIST = 'whatsapp-button-list',\n WHATSAPP_CTA_URL_BUTTON = 'whatsapp-cta-url-button',\n WHATSAPP_REQUEST_CONTACT_INFO = 'whatsapp-request-contact-info',\n WHATSAPP_CATALOG = 'whatsapp-catalog',\n WHATSAPP_PRODUCT = 'whatsapp-product',\n WHATSAPP_PRODUCT_LIST = 'whatsapp-product-list',\n WHATSAPP_PRODUCT_CAROUSEL = 'whatsapp-product-carousel',\n WHATSAPP_MEDIA_CAROUSEL = 'whatsapp-media-carousel',\n WHATSAPP_ORDER = 'whatsapp_order',\n EVENT_AGENT_MESSAGE_CREATED = 'case_event_agent_message_created',\n EVENT_QUEUE_POSITION_CHANGED = 'case_event_queue_position_changed',\n EVENT_CASE_STATUS_CHANGED = 'case_event_status_changed',\n SYSTEM_DEBUG_TRACE = 'system_debug_trace',\n}\n\ninterface PluginConstructor<T> {\n new (arg: T): Plugin\n}\n\nexport interface PluginConfig<T> {\n id: string\n options?: T\n resolve: { default: PluginConstructor<T> }\n}\n\nexport type ResolvedPlugins = Record<string, Plugin>\n\nexport type InputType =\n | INPUT.AUDIO\n | INPUT.BUTTON_MESSAGE\n | INPUT.CAROUSEL\n | INPUT.CONTACT\n | INPUT.CUSTOM\n | INPUT.DOCUMENT\n | INPUT.IMAGE\n | INPUT.LOCATION\n | INPUT.POSTBACK\n | INPUT.TEXT\n | INPUT.VIDEO\n | INPUT.CHAT_EVENT\n | INPUT.WEBCHAT_SETTINGS\n | INPUT.WHATSAPP_TEMPLATE\n | INPUT.WHATSAPP_BUTTON_LIST\n | INPUT.WHATSAPP_CTA_URL_BUTTON\n | INPUT.WHATSAPP_REQUEST_CONTACT_INFO\n | INPUT.WHATSAPP_CATALOG\n | INPUT.WHATSAPP_PRODUCT\n | INPUT.WHATSAPP_PRODUCT_LIST\n | INPUT.WHATSAPP_PRODUCT_CAROUSEL\n | INPUT.WHATSAPP_MEDIA_CAROUSEL\n | INPUT.WHATSAPP_ORDER\n | INPUT.EVENT_AGENT_MESSAGE_CREATED\n | INPUT.EVENT_QUEUE_POSITION_CHANGED\n | INPUT.EVENT_CASE_STATUS_CHANGED\n\n/** Generated by Translation plugins: GoogleTranslation **/\nexport interface Translations {\n [languageCode: string]: string\n}\n\nexport enum NluType {\n Keyword = 'keyword',\n SmartIntent = 'smart-intent',\n}\n\nexport interface Input {\n text?: string\n src?: string\n data?: string\n path?: string\n payload?: string\n referral?: string\n type: InputType\n context?: {\n campaign?: Campaign\n campaigns_v2?: CampaignV2[]\n salesforce?: {\n access_token: string\n }\n }\n transcript?: string\n message_id: string\n bot_interaction_id: string\n catalog_id?: string\n product_items?: ProductItem[]\n nluResolution?: {\n type: NluType\n matchedValue: string\n payload?: string\n }\n origin?: string\n}\n\nexport interface CaseEventQueuePositionChangedInput {\n type: INPUT.EVENT_QUEUE_POSITION_CHANGED\n case_id: string\n prev_queue_position: number | null\n prev_queue_position_notified_at: string | null\n current_queue_position: number\n current_queue_position_notified_at: string\n total_queue_waiting_cases_number: number\n}\n\nexport enum CaseStatus {\n Waiting = 'status_waiting',\n Attending = 'status_attending',\n Idle = 'status_idle',\n Resolved = 'status_resolved',\n}\n\nexport interface CaseEventStatusChangedInput {\n type: INPUT.EVENT_CASE_STATUS_CHANGED\n case_id: string\n prev_status: CaseStatus | null\n next_status: CaseStatus\n}\n\nexport interface CaseEventAgentMessageCreatedInput {\n type: INPUT.EVENT_AGENT_MESSAGE_CREATED\n agent_id?: string\n agent_name?: string\n message?: {\n type: string\n data: string\n }\n}\n\ninterface ProductItem {\n product_retailer_id: string\n quantity: number\n item_price: number\n currency: string\n}\n\nexport interface Campaign {\n id: string\n name: string\n status: string\n start_date: string\n end_date: string\n bot_path: string\n template_name: string\n}\n\nexport interface CampaignV2 {\n id: string\n name: string\n agent_context?: string\n end_date?: string\n}\n\nexport interface ContactInfo {\n name: string\n type: string\n value: string\n description?: string\n}\n\nexport interface SessionUser<TExtraData = any> {\n id: string\n // login\n username?: string\n // person name\n name?: string\n // whatsapp, telegram,...\n provider: ProviderType\n // The provider's user id\n extra_data?: TExtraData\n contact_info?: ContactInfo[]\n imp_id?: string\n provider_id?: string\n locale: string\n country: string\n system_locale: string\n system_locale_updated?: boolean\n}\n\nexport interface HubtypeCaseContactReason {\n id: string\n name: string\n project_id: string\n}\n\nexport interface SessionBot {\n id: string\n name?: string\n}\n\nexport interface Session<TExtraData = any> {\n bot: SessionBot\n __retries: number\n _access_token: string\n _hubtype_api: string\n is_first_interaction: boolean\n is_test_integration: boolean\n last_session?: any\n organization_id: string\n organization: string\n user: SessionUser<TExtraData>\n // after handoff\n _botonic_action?: BotonicActionType\n _hubtype_case_resolution?: CaseResolution\n _hubtype_case_id?: string\n _hubtype_case_typification?: string\n _hubtype_case_contact_reasons?: HubtypeCaseContactReason[]\n _shadowing?: boolean\n external?: any\n zendesk_ticket_id?: string\n flow_thread_id?: string\n __campaign?: {\n id: string\n path: string\n active: boolean\n }\n capture_user_input?: {\n node_id: string\n }\n}\n\nexport type InputMatcher = (input: Input) => boolean\nexport type ParamsMatcher =\n | { [key: string]: string }\n | ((params: { [key: string]: string }) => boolean)\nexport type SessionMatcher<TExtraData = any> = (\n session: Session<TExtraData>\n) => boolean\nexport type RequestMatcher<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> = (request: BotContext<TPlugins, TExtraData>) => boolean\nexport type StringMatcher = RegExp | string | ((data: string) => boolean)\n\nexport type RouteMatcher =\n | InputMatcher\n | ParamsMatcher\n | RequestMatcher\n | SessionMatcher\n | StringMatcher\n\nexport interface Route<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> {\n action?: any\n childRoutes?: Route[]\n lastRoutePath?: string\n ignoreRetry?: boolean\n path: RoutePath\n redirect?: string\n retry?: number\n\n // matchers\n input?: InputMatcher\n params?: ParamsMatcher\n payload?: StringMatcher\n request?: RequestMatcher<TPlugins, TExtraData>\n session?: SessionMatcher<TExtraData>\n text?: StringMatcher\n data?: StringMatcher\n type?: StringMatcher\n}\n\nexport type Routes<R = Route> = R[] | ((request: BotContext) => R[])\n\nexport interface BotRequest<TExtraData = any> {\n input: Input\n lastRoutePath: RoutePath\n session: Session<TExtraData>\n settings: BotSettings\n secrets: BotSecrets\n}\n\nexport interface BotSettings {\n HUBTYPE_API_URL: string\n STATIC_URL: string\n LITELLM_API_URL: string\n AZURE_OPENAI_API_BASE: string\n AZURE_OPENAI_API_VERSION: string\n LANGUAGE_DETECTION_ENABLED?: boolean\n CUSTOM_SHORT_URL_HOST: string | null\n custom: Record<string, any>\n}\n\nexport interface BotSecrets {\n HUBTYPE_ACCESS_TOKEN: string\n LITELLM_API_KEY: string\n AZURE_OPENAI_API_KEY: string\n custom: Record<string, any>\n}\n\nexport interface BotContext<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> extends BotRequest<TExtraData> {\n getUserCountry: () => string\n getUserLocale: () => string\n getSystemLocale: () => string\n setUserCountry: (country: string) => void\n setUserLocale: (locale: string) => void\n setSystemLocale: (locale: string) => void\n defaultDelay: number\n defaultTyping: number\n params: Record<string, string>\n plugins: TPlugins\n}\n\n/** The response of the bot for the triggered actions, which can be\n * the one matched by the routes, the default action and the retry actions.\n * See Response at @botonic/react's index.d.ts for the React type\n * */\nexport interface BotResponse extends BotRequest {\n response: any\n}\n\nexport type PluginPreRequest<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> = BotContext<TPlugins, TExtraData>\n\nexport type PluginPostRequest<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> = BotContext<TPlugins, TExtraData> & {\n response: string | null\n}\n\nexport interface Plugin {\n post?(request: PluginPostRequest): void | Promise<void>\n pre?(request: PluginPreRequest): void | Promise<void>\n}\n\nexport interface Params {\n [key: string]: any\n}\n\nexport type Nullable<T> = T | null\n\nexport type Action = Nullable<() => any>\nexport type RoutePath = Nullable<string>\n\nexport interface ProcessInputResult {\n action: Action\n emptyAction: Action\n fallbackAction: Action\n lastRoutePath: RoutePath\n params: Params\n}\n\nexport type MatchedValue = boolean | RegExpExecArray | null\n\nexport type RoutingState = {\n currentRoute: Nullable<Route>\n matchedRoute: Nullable<Route>\n params: Params\n isFlowBroken: boolean\n}\n\nexport interface RouteParams {\n route: Nullable<Route>\n params: Params\n}\nexport interface PathParams {\n path: RoutePath\n params: Params\n}\n\nexport type MatchingProp =\n | 'text'\n | 'payload'\n | 'type'\n | 'input'\n | 'session'\n | 'request'\n\nexport type Matcher = string | RegExp | ((args) => boolean)\n\nexport type BotonicActionType =\n | `${BotonicAction.CreateCase}${BotonicActionSeparator}${string}`\n | `${BotonicAction.Redirect}${BotonicActionSeparator}${string}`\n | `${BotonicAction.DiscardCase}${BotonicActionSeparator}${string}`\n | `${BotonicAction.DiscardCase}`\n | `${BotonicAction.DeleteUser}`\n\ntype BotonicActionSeparator = ':'\n\nexport enum BotonicAction {\n Redirect = 'redirect_action',\n CreateCase = 'create_case',\n DeleteUser = 'delete_user',\n DiscardCase = 'discard_case',\n}\n"],"names":["CASE_STATUS","CASE_RESOLUTION","PROVIDER","INPUT","NluType","CaseStatus","BotonicAction"],"mappings":"AAAA,wIAAwI;AAEjI,IAAKA,wBAAWA,0BAAXA;;;;;WAAAA;MAKX;AAQM,IAAKC,4BAAeA,0BAAfA;;;;;WAAAA;MAKX;AAQM,IAAKC,qBAAQA,0BAARA;;;;;;;;;;;;;WAAAA;MAaX;AAeM,IAAKC,kBAAKA,0BAALA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAAAA;MA6BX;AA+CM,IAAKC,oBAAOA,0BAAPA;;;WAAAA;MAGX;AAwCM,IAAKC,uBAAUA,0BAAVA;;;;;WAAAA;MAKX;AAqRM,IAAKC,0BAAaA,0BAAbA;;;;;WAAAA;MAKX"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.js","sources":["../src/plugins.ts"],"sourcesContent":["import type { BotContext, Plugin } from './models'\n\ninterface RunPluginArgs {\n botContext: BotContext\n mode: PluginMode\n response?: string | null\n}\n\ntype PluginMode = 'pre' | 'post'\n\nexport async function runPlugins({\n botContext,\n mode,\n response = null,\n}: RunPluginArgs): Promise<void> {\n const plugins = botContext.plugins\n for (const key in plugins) {\n const plugin: Plugin = plugins[key]\n try {\n if (mode === 'pre' && typeof plugin.pre === 'function') {\n await plugin.pre(botContext)\n }\n if (mode === 'post' && typeof plugin.post === 'function') {\n await plugin.post({\n ...botContext,\n response,\n })\n }\n } catch (e) {\n console.log(e)\n }\n }\n}\n"],"names":["runPlugins","botContext","mode","response","plugins","key","plugin","e","console"],"mappings":"AAUO,eAAeA,UAAUA,CAAC,EAC/BC,UAAU,EACVC,IAAI,EACJC,WAAW,IAAI,EACD;IACd,MAAMC,UAAUH,WAAW,OAAO;IAClC,IAAK,MAAMI,OAAOD,QAAS;QACzB,MAAME,SAAiBF,OAAO,CAACC,IAAI;QACnC,IAAI;YACF,IAAIH,SAAS,SAAS,OAAOI,OAAO,GAAG,KAAK,YAAY;gBACtD,MAAMA,OAAO,GAAG,CAACL;YACnB;YACA,IAAIC,SAAS,UAAU,OAAOI,OAAO,IAAI,KAAK,YAAY;gBACxD,MAAMA,OAAO,IAAI,CAAC;oBAChB,GAAGL,UAAU;oBACbE;gBACF;YACF;QACF,EAAE,OAAOI,GAAG;YACVC,QAAQ,GAAG,CAACD;QACd;IACF;AACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pusher-utils.js","sources":["../src/pusher-utils.ts"],"sourcesContent":["import { inflate } from 'pako'\n\n/**\n *\n * @param compressedData a string representing gzipped data previously encoded to base64 for very large contents\n * @returns a string representing the information of a very large content\n * Ref: https://stackoverflow.com/questions/4875020/javascript-decompress-inflate-unzip-ungzip-strings (check jsfiddle proposal)\n */\nexport function decompressData(compressedData: string): string {\n const strData = atob(compressedData) // Decode base64 (convert ascii to binary)\n const charData = strData.split('').map(x => x.charCodeAt(0)) // Convert binary string to character-number array\n const binData = new Uint8Array(charData) // Turn number array into byte-array\n const data = inflate(binData)\n return new TextDecoder('utf-8').decode(data)\n}\n"],"names":["inflate","decompressData","compressedData","strData","atob","charData","x","binData","Uint8Array","data","TextDecoder"],"mappings":";;;AAA8B;AAE9B;;;;;CAKC,GACM,SAASC,cAAcA,CAACC,cAAsB;IACnD,MAAMC,UAAUC,KAAKF,gBAAgB,0CAA0C;;IAC/E,MAAMG,WAAWF,QAAQ,KAAK,CAAC,IAAI,GAAG,CAACG,CAAAA,IAAKA,EAAE,UAAU,CAAC,IAAI,kDAAkD;;IAC/G,MAAMC,UAAU,IAAIC,WAAWH,UAAU,oCAAoC;;IAC7E,MAAMI,OAAOT,OAAOA,CAACO;IACrB,OAAO,IAAIG,YAAY,SAAS,MAAM,CAACD;AACzC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing/index.js","sources":["../../src/routing/index.ts"],"sourcesContent":["export * from './router'\nexport * from './router-utils'\n"],"names":[],"mappings":";;AAAwB;AACM"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing/router-utils.js","sources":["../../src/routing/router-utils.ts"],"sourcesContent":["import {\n EMPTY_ACTION_PATH,\n NOT_FOUND_PATH,\n PATH_PAYLOAD_IDENTIFIER,\n PATH_PAYLOAD_REGEXP,\n} from '../constants'\nimport type {\n Action,\n BotContext,\n Input,\n Params,\n PathParams,\n Route,\n Routes,\n} from '../models'\n\nexport class NoMatchingRouteError extends Error {\n input: Input\n constructor(input: Input) {\n super(\n `No route found for input '${JSON.stringify(\n input\n )}' and no ${NOT_FOUND_PATH} route defined`\n )\n this.input = input\n }\n}\n\nexport function isPathPayload(payload?: string): boolean {\n if (!payload) {\n return false\n }\n const isPathPayload = PATH_PAYLOAD_REGEXP.exec(payload)\n return Boolean(isPathPayload)\n}\n\nexport function getPathParamsFromPathPayload(payload?: string): PathParams {\n const defaultPathParams = {\n path: null,\n params: {},\n }\n if (!payload) {\n return defaultPathParams\n }\n if (!isPathPayload(payload)) {\n return defaultPathParams\n }\n try {\n const pathWithParams = payload.split(PATH_PAYLOAD_IDENTIFIER)[1]\n if (!pathWithParams) {\n throw `${PATH_PAYLOAD_IDENTIFIER} is empty`\n }\n const [path, params] = pathWithParams.split('?')\n return { path: path ?? null, params: pathParamsToParams(params) }\n } catch (e) {\n console.error('Error getting path and params from input.payload:', e)\n return defaultPathParams\n }\n}\n\nexport function pathParamsToParams(pathParams?: string): Params {\n if (!pathParams) {\n return {}\n }\n try {\n const params = {}\n const searchParams = new URLSearchParams(pathParams)\n for (const [key, value] of searchParams) {\n params[key] = value\n }\n return params\n } catch (_e) {\n return {}\n }\n}\n\nexport function getEmptyAction(childRoutes?: Route[]): Action {\n if (!childRoutes) {\n return null\n }\n const emptyActionRoute = childRoutes.find(r => r.path === EMPTY_ACTION_PATH)\n if (!emptyActionRoute) {\n return null\n }\n return emptyActionRoute.action\n}\n\nexport function getNotFoundAction(input: Input, routes: Route[]): Action {\n const notFoundActionRoute = routes.find(r => r.path === NOT_FOUND_PATH)\n if (!notFoundActionRoute) {\n throw new NoMatchingRouteError(input)\n }\n return notFoundActionRoute.action\n}\n\nexport async function getComputedRoutes(\n routes: Routes,\n botContext: BotContext\n): Promise<Route[]> {\n if (routes instanceof Function) {\n return await getComputedRoutes(await routes(botContext), botContext)\n }\n for (const [key, route] of Object.entries(routes) as any) {\n if (route.childRoutes && route.childRoutes instanceof Function) {\n routes[key].childRoutes = await getComputedRoutes(\n await route.childRoutes(botContext),\n botContext\n )\n } else {\n routes[key] = route\n }\n }\n return routes\n}\n"],"names":["EMPTY_ACTION_PATH","NOT_FOUND_PATH","PATH_PAYLOAD_IDENTIFIER","PATH_PAYLOAD_REGEXP","NoMatchingRouteError","Error","input","JSON","isPathPayload","payload","Boolean","getPathParamsFromPathPayload","defaultPathParams","pathWithParams","path","params","pathParamsToParams","e","console","pathParams","searchParams","URLSearchParams","key","value","_e","getEmptyAction","childRoutes","emptyActionRoute","r","getNotFoundAction","routes","notFoundActionRoute","getComputedRoutes","botContext","Function","route","Object"],"mappings":";;;;;;;;;;;;;;AAKqB;AAWd,MAAMI,oBAAoBA,SAASC;IAExC,YAAYC,KAAY,CAAE;QACxB,KAAK,CACH,CAAC,0BAA0B,EAAEC,KAAK,SAAS,CACzCD,OACA,SAAS,EAAEL,cAAcA,CAAC,cAAc,CAAC,GAL/C;QAOE,IAAI,CAAC,KAAK,GAAGK;IACf;AACF;AAEO,SAASE,0BAAaA,CAACC,OAAgB;IAC5C,IAAI,CAACA,SAAS;QACZ,OAAO;IACT;IACA,MAAMD,gBAAgBL,wBAAwB,CAACM;IAC/C,OAAOC,QAAQF;AACjB;AAEO,SAASG,4BAA4BA,CAACF,OAAgB;IAC3D,MAAMG,oBAAoB;QACxB,MAAM;QACN,QAAQ,CAAC;IACX;IACA,IAAI,CAACH,SAAS;QACZ,OAAOG;IACT;IACA,IAAI,CAACJ,0BAAaA,CAACC,UAAU;QAC3B,OAAOG;IACT;IACA,IAAI;QACF,MAAMC,iBAAiBJ,QAAQ,KAAK,CAACP,uBAAuBA,CAAC,CAAC,EAAE;QAChE,IAAI,CAACW,gBAAgB;YACnB,MAAM,GAAGX,uBAAuBA,CAAC,SAAS,CAAC;QAC7C;QACA,MAAM,CAACY,MAAMC,OAAO,GAAGF,eAAe,KAAK,CAAC;QAC5C,OAAO;YAAE,MAAMC,QAAQ;YAAM,QAAQE,kBAAkBA,CAACD;QAAQ;IAClE,EAAE,OAAOE,GAAG;QACVC,QAAQ,KAAK,CAAC,qDAAqDD;QACnE,OAAOL;IACT;AACF;AAEO,SAASI,kBAAkBA,CAACG,UAAmB;IACpD,IAAI,CAACA,YAAY;QACf,OAAO,CAAC;IACV;IACA,IAAI;QACF,MAAMJ,SAAS,CAAC;QAChB,MAAMK,eAAe,IAAIC,gBAAgBF;QACzC,KAAK,MAAM,CAACG,KAAKC,MAAM,IAAIH,aAAc;YACvCL,MAAM,CAACO,IAAI,GAAGC;QAChB;QACA,OAAOR;IACT,EAAE,OAAOS,IAAI;QACX,OAAO,CAAC;IACV;AACF;AAEO,SAASC,cAAcA,CAACC,WAAqB;IAClD,IAAI,CAACA,aAAa;QAChB,OAAO;IACT;IACA,MAAMC,mBAAmBD,YAAY,IAAI,CAACE,CAAAA,IAAKA,EAAE,IAAI,KAAK5B,iBAAiBA;IAC3E,IAAI,CAAC2B,kBAAkB;QACrB,OAAO;IACT;IACA,OAAOA,iBAAiB,MAAM;AAChC;AAEO,SAASE,iBAAiBA,CAACvB,KAAY,EAAEwB,MAAe;IAC7D,MAAMC,sBAAsBD,OAAO,IAAI,CAACF,CAAAA,IAAKA,EAAE,IAAI,KAAK3B,cAAcA;IACtE,IAAI,CAAC8B,qBAAqB;QACxB,MAAM,IAAI3B,oBAAoBA,CAACE;IACjC;IACA,OAAOyB,oBAAoB,MAAM;AACnC;AAEO,eAAeC,iBAAiBA,CACrCF,MAAc,EACdG,UAAsB;IAEtB,IAAIH,kBAAkBI,UAAU;QAC9B,OAAO,MAAMF,iBAAiBA,CAAC,MAAMF,OAAOG,aAAaA;IAC3D;IACA,KAAK,MAAM,CAACX,KAAKa,MAAM,IAAIC,OAAO,OAAO,CAACN,QAAgB;QACxD,IAAIK,MAAM,WAAW,IAAIA,MAAM,WAAW,YAAYD,UAAU;YAC9DJ,MAAM,CAACR,IAAI,CAAC,WAAW,GAAG,MAAMU,iBAAiBA,CAC/C,MAAMG,MAAM,WAAW,CAACF,aACxBA;QAEJ,OAAO;YACLH,MAAM,CAACR,IAAI,GAAGa;QAChB;IACF;IACA,OAAOL;AACT"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing/router.js","sources":["../../src/routing/router.ts"],"sourcesContent":["import { NOT_FOUND_PATH } from '../constants'\nimport { RouteInspector } from '../debug/inspector'\nimport type {\n Input,\n MatchedValue,\n Matcher,\n MatchingProp,\n Nullable,\n ProcessInputResult,\n Route,\n RouteParams,\n RoutePath,\n RoutingState,\n Session,\n} from '../models'\nimport { cloneObject } from '../utils'\nimport {\n getEmptyAction,\n getNotFoundAction,\n getPathParamsFromPathPayload,\n isPathPayload,\n} from './router-utils'\n\nexport class Router {\n routes: Route[]\n routeInspector: RouteInspector\n\n constructor(\n routes: Route[],\n routeInspector: RouteInspector | undefined = undefined\n ) {\n this.routes = routes\n this.routeInspector = routeInspector || new RouteInspector()\n }\n\n /**\n * Processes an input and return a representation of the new bot state.\n * The algorithm is splitted in two main parts:\n * 1. Getting the current routing state.\n * 2. Given a routing state, resolve the different possible scenarios and return the new bot state.\n * The new bot state can return three type of actions:\n * - action: an action directly resolved from a matching route\n * - emptyAction: optional action that can exists or not only within childRoutes\n * - fallbackAction: any other action that acts as a fallback (404, )\n */\n\n // eslint-disable-next-line complexity\n processInput(\n input: Input,\n session: Session,\n lastRoutePath: RoutePath = null\n ): ProcessInputResult {\n session.__retries = session?.__retries ?? 0\n\n // 1. Getting the current routing state.\n const { currentRoute, matchedRoute, params, isFlowBroken } =\n this.getRoutingState(input, session, lastRoutePath)\n\n const currentRoutePath = currentRoute?.path ?? null\n const matchedRoutePath = matchedRoute?.path ?? null\n\n // 2. Given a routing state, resolve the different possible scenarios and return the new bot state.\n\n /**\n * Redirect Scenario:\n * We have matched a redirect route with a given redirection path, so we try to obtain the redirectionRoute with getRouteByPath.\n * Independently of whether the redirectionRoute is found or not, the intent is to trigger a redirection which by definition breaks the flow, so retries are set to 0.\n * It has preference over ignoring retries.\n */\n if (matchedRoute?.redirect) {\n session.__retries = 0\n const redirectionRoute = this.getRouteByPath(matchedRoute.redirect)\n if (redirectionRoute) {\n return {\n action: redirectionRoute.action,\n emptyAction: getEmptyAction(redirectionRoute.childRoutes),\n fallbackAction: null,\n lastRoutePath: matchedRoute.redirect,\n params,\n }\n }\n return {\n action: null,\n emptyAction: null,\n fallbackAction: getNotFoundAction(input, this.routes),\n lastRoutePath: null,\n params,\n }\n }\n\n /**\n * Ignore Retry Scenario:\n * We have matched a route with an ignore retry, so we return directly the new bot state. The intent is to break the flow, so retries are set to 0.\n */\n if (matchedRoute?.ignoreRetry) {\n session.__retries = 0\n return {\n action: matchedRoute.action,\n emptyAction: getEmptyAction(matchedRoute.childRoutes),\n fallbackAction: null,\n lastRoutePath: matchedRoutePath,\n params,\n }\n }\n\n /**\n * Retry Scenario:\n * We were in a route which had retries enabled, so we check if the number of retries is exceeded.\n * If we have not surpassed the limit of retries and we haven't matched an ignoreRetry route, update them, and then return the new bot state.\n */\n if (\n isFlowBroken &&\n currentRoute &&\n currentRoute.retry &&\n session.__retries < currentRoute.retry\n ) {\n session.__retries = session.__retries !== 0 ? session.__retries + 1 : 1\n if (matchedRoute && matchedRoutePath !== NOT_FOUND_PATH) {\n return {\n action: currentRoute.action,\n emptyAction: getEmptyAction(matchedRoute.childRoutes),\n fallbackAction: matchedRoute.action,\n lastRoutePath: currentRoutePath,\n params,\n }\n }\n return {\n action: currentRoute.action ?? null,\n emptyAction: getEmptyAction(currentRoute.childRoutes),\n fallbackAction: getNotFoundAction(input, this.routes),\n lastRoutePath: currentRoutePath,\n params,\n }\n }\n\n /**\n * Default Scenario:\n * We have matched a route or not, but we don't need to execute retries logic, so retries stay to 0.\n */\n session.__retries = 0\n\n /**\n * Matching Route Scenario:\n * We have matched a route, so we return the new bot state.\n */\n if (matchedRoute && matchedRoutePath !== NOT_FOUND_PATH) {\n return {\n action: matchedRoute.action ?? null,\n emptyAction: getEmptyAction(matchedRoute.childRoutes),\n fallbackAction: null,\n lastRoutePath: matchedRoutePath,\n params,\n }\n }\n\n /**\n * 404 Scenario (No Route Found):\n * We have not matched any route, so we return the new bot state.\n */\n return {\n action: null,\n emptyAction: null,\n fallbackAction: getNotFoundAction(input, this.routes),\n params,\n lastRoutePath: currentRoutePath,\n }\n }\n\n /**\n * Find the route that matches the given input, if it match with some of the entries, return the whole Route of the entry with optional params captured if matcher was a regex.\n * IMPORTANT: It returns a cloned route instead of the route itself to avoid modifying original routes and introduce side effects\n * */\n getRoute(\n input: Input | Partial<Input>,\n routes: Route[],\n session: Session,\n lastRoutePath: RoutePath\n ): RouteParams | null {\n let params = {}\n const route = routes.find(r =>\n Object.entries(r)\n .filter(\n ([key, _]) =>\n key !== 'action' && key !== 'childRoutes' && key !== 'path'\n )\n .some(([key, value]) => {\n const match = this.matchRoute(\n r,\n key as MatchingProp,\n value as Matcher,\n input as Input,\n session,\n lastRoutePath\n )\n try {\n if (match !== null && typeof match !== 'boolean' && match.groups) {\n // Strip '[Object: null prototype]' from groups result: https://stackoverflow.com/a/62945609/6237608\n params = { ...match.groups }\n }\n } catch (_e) {}\n return Boolean(match)\n })\n )\n if (route) {\n return { route: cloneObject(route), params }\n }\n return null\n }\n\n /**\n * Find the route that matches the given path. Path can include concatenations, e.g: 'Flow1/Subflow1.1'.\n * IMPORTANT: It returns a cloned route instead of the route itself to avoid modifying original routes and introduce side effects\n * */\n getRouteByPath(\n path: RoutePath,\n routeList: Route[] = this.routes\n ): Nullable<Route> {\n if (!path) {\n return null\n }\n const [currentPath, ...childPath] = path.split('/')\n for (const route of routeList) {\n // iterate over all routeList\n if (route.path === currentPath) {\n if (route.childRoutes?.length && childPath.length > 0) {\n // evaluate childroute over next actions\n const computedRoute = this.getRouteByPath(\n childPath.join('/'),\n route.childRoutes\n )\n // IMPORTANT: Returning a new object to avoid modifying dev routes and introduce side effects\n if (computedRoute) {\n return cloneObject(computedRoute)\n }\n } else if (childPath.length === 0) {\n return cloneObject(route) // last action and found route\n }\n }\n }\n return null\n }\n\n /**\n * Returns the matched value for a specific route.\n * Matching Props: ('text' | 'payload' | 'intent' | 'type' | 'input' | 'session' | 'request' ...)\n * Matchers: (string: exact match | regex: regular expression match | function: return true)\n * input: user input object, e.g.: {type: 'text', data: 'Hi'}\n * */\n matchRoute(\n route: Route,\n prop: MatchingProp,\n matcher: Matcher,\n input: Input,\n session: Session,\n lastRoutePath: RoutePath\n ): MatchedValue {\n let value: any = null\n if (Object.keys(input).indexOf(prop) > -1) {\n value = input[prop]\n } else if (prop === 'text') {\n value = input.data\n } else if (prop === 'input') {\n value = input\n } else if (prop === 'session') {\n value = session\n } else if (prop === 'request') {\n value = { input, session, lastRoutePath }\n }\n const matched = this.matchValue(matcher, value)\n if (matched) {\n this.routeInspector.routeMatched(route, prop, matcher, value)\n } else {\n this.routeInspector.routeNotMatched(route, prop, matcher, value)\n }\n return matched\n }\n\n /**\n * Runs the matcher against the given value.\n * If there is a match, it will return a truthy value (true, RegExp result), o.w., it will return a falsy value.\n * */\n matchValue(matcher: Matcher, value: any): MatchedValue {\n if (typeof matcher === 'string') {\n return value === matcher\n }\n if (matcher instanceof RegExp) {\n if (value === undefined || value === null) {\n return false\n }\n return matcher.exec(value)\n }\n if (typeof matcher === 'function') {\n return matcher(value)\n }\n return false\n }\n\n /**\n * It resolves the current state of navigation. Two scenarios:\n * 1. Given a path payload input (__PATH_PAYLOAD__somePath?someParam=someValue), we can resolve the routing state directly from it (using getRouteByPath).\n * 2. Given any other type of input, we resolve the routing state with normal resolution (using getRoute).\n * */\n getRoutingState(\n input: Input,\n session: Session,\n lastRoutePath: RoutePath\n ): RoutingState {\n const currentRoute = this.getRouteByPath(lastRoutePath)\n if (currentRoute && lastRoutePath) {\n currentRoute.path = lastRoutePath\n }\n if (typeof input.payload === 'string' && isPathPayload(input.payload)) {\n return this.getRoutingStateFromPathPayload(currentRoute, input.payload)\n }\n return this.getRoutingStateFromInput(currentRoute, input, session)\n }\n\n /**\n * Given a non path payload input, try to run it against the routes, update matching routes information in consequence and dictamine if the flow has been broken.\n * */\n getRoutingStateFromInput(\n currentRoute: Nullable<Route>,\n input: Input,\n session: Session\n ): RoutingState {\n // get route depending of current ChildRoutes\n if (currentRoute?.childRoutes) {\n const routeParams = this.getRoute(\n input,\n currentRoute.childRoutes,\n session,\n currentRoute.path\n )\n if (routeParams) {\n return {\n currentRoute,\n matchedRoute: {\n ...routeParams.route,\n path:\n routeParams.route && currentRoute.path\n ? `${currentRoute.path}/${routeParams.route.path}`\n : currentRoute.path,\n },\n params: routeParams.params,\n isFlowBroken: false,\n }\n }\n }\n /**\n * we couldn't find a route in the state of the currentRoute childRoutes,\n * so let's find in the general routes\n */\n const routeParams = this.getRoute(\n input,\n this.routes,\n session,\n currentRoute?.path ?? null\n )\n const isFlowBroken = Boolean(currentRoute?.path)\n if (routeParams?.route) {\n return {\n currentRoute,\n matchedRoute: {\n ...routeParams.route,\n path: routeParams.route?.path ?? null,\n },\n params: routeParams.params,\n isFlowBroken,\n }\n }\n return {\n currentRoute,\n matchedRoute: null,\n params: {},\n isFlowBroken,\n }\n }\n\n /**\n * Given a path payload input, try to run the path against the routes, update matching routes information in consequence and dictamine if the flow has been broken.\n * */\n getRoutingStateFromPathPayload(\n currentRoute: Nullable<Route>,\n pathPayload: string\n ): RoutingState {\n const { path, params } = getPathParamsFromPathPayload(pathPayload)\n /**\n * shorthand function to update the matching information given a path\n */\n const getRoutingStateFromPath = (seekPath: string): RoutingState => {\n const matchedRoute = this.getRouteByPath(seekPath)\n if (!matchedRoute) {\n return {\n currentRoute,\n matchedRoute: null,\n params: {},\n isFlowBroken: true,\n }\n }\n return {\n currentRoute,\n matchedRoute: { ...matchedRoute, path: seekPath },\n params,\n isFlowBroken: false,\n }\n }\n /**\n * Given a valid path: 'Flow1/Subflow1' we are in one of the two scenarios below.\n */\n // 1. Received __PATH_PAYLOAD__Subflow2, so we need to first try to concatenate it with Flow1 (lastRoutePath)\n if (currentRoute?.path) {\n const routingState = getRoutingStateFromPath(\n `${currentRoute.path}/${path}`\n )\n if (routingState.matchedRoute) {\n return routingState\n }\n }\n // 2. Received __PATH_PAYLOAD__Flow1/Subflow1, so we can resolve it directly\n return getRoutingStateFromPath(path as string)\n }\n}\n"],"names":["NOT_FOUND_PATH","RouteInspector","cloneObject","getEmptyAction","getNotFoundAction","getPathParamsFromPathPayload","isPathPayload","Router","input","session","lastRoutePath","currentRoute","matchedRoute","params","isFlowBroken","currentRoutePath","matchedRoutePath","redirectionRoute","routes","route","r","Object","key","_","value","match","_e","Boolean","path","routeList","currentPath","childPath","computedRoute","prop","matcher","matched","RegExp","undefined","routeParams","pathPayload","getRoutingStateFromPath","seekPath","routingState","routeInspector"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing/index.js","sources":["../../src/testing/index.ts"],"sourcesContent":["import {\n type BotContext,\n type BotRequest,\n type BotSecrets,\n type BotSettings,\n type ContactInfo,\n INPUT,\n type Input,\n PROVIDER,\n type ProviderType,\n type ResolvedPlugins,\n type Session,\n type SessionUser,\n} from '../models'\n\n// ---------------------------------------------------------------------------\n// Default values\n// ---------------------------------------------------------------------------\n\nexport const TEST_DEFAULTS = {\n HUBTYPE_API_URL: 'https://api.hubtype.com',\n STATIC_URL: 'https://static.hubtype.com',\n LITELLM_API_URL: 'https://api.litellm.com',\n AZURE_OPENAI_API_BASE: 'https://api.openai.com',\n AZURE_OPENAI_API_VERSION: '2026-02-01',\n LANGUAGE_DETECTION_ENABLED: true,\n HUBTYPE_ACCESS_TOKEN: 'testAccessToken', // pragma: allowlist secret\n LITELLM_API_KEY: 'testLiteLLMAPIKey', // pragma: allowlist secret\n AZURE_OPENAI_API_KEY: 'testAzureOpenAIAPIKey', // pragma: allowlist secret\n ACCESS_TOKEN: 'fake_access_token',\n HUBTYPE_API_HOST: 'https://api.hubtype.com',\n FLOW_THREAD_ID: 'testFlowThreadId',\n BOT_ID: 'testBotId',\n USER_ID: 'testUserId',\n ORG_ID: 'testOrgId',\n ORG_NAME: 'testOrg',\n PROVIDER: PROVIDER.WEBCHAT as ProviderType,\n LOCALE: 'en',\n COUNTRY: 'US',\n BOT_INTERACTION_ID: 'testInteractionId',\n MESSAGE_ID: 'testMessageId',\n LAST_ROUTE_PATH: '',\n}\n\n// ---------------------------------------------------------------------------\n// Leaf factories\n// ---------------------------------------------------------------------------\n\nexport function createTestSettings(\n overrides?: Partial<BotSettings>\n): BotSettings {\n return {\n HUBTYPE_API_URL: TEST_DEFAULTS.HUBTYPE_API_URL,\n STATIC_URL: TEST_DEFAULTS.STATIC_URL,\n LITELLM_API_URL: TEST_DEFAULTS.LITELLM_API_URL,\n AZURE_OPENAI_API_BASE: TEST_DEFAULTS.AZURE_OPENAI_API_BASE,\n AZURE_OPENAI_API_VERSION: TEST_DEFAULTS.AZURE_OPENAI_API_VERSION,\n LANGUAGE_DETECTION_ENABLED: TEST_DEFAULTS.LANGUAGE_DETECTION_ENABLED,\n CUSTOM_SHORT_URL_HOST: null,\n custom: {},\n ...overrides,\n }\n}\n\nexport function createTestSecrets(overrides?: Partial<BotSecrets>): BotSecrets {\n return {\n HUBTYPE_ACCESS_TOKEN: TEST_DEFAULTS.HUBTYPE_ACCESS_TOKEN,\n LITELLM_API_KEY: TEST_DEFAULTS.LITELLM_API_KEY,\n AZURE_OPENAI_API_KEY: TEST_DEFAULTS.AZURE_OPENAI_API_KEY,\n custom: {},\n ...overrides,\n }\n}\n\nexport interface TestUserOptions {\n id?: string\n provider?: ProviderType\n locale?: string\n country?: string\n systemLocale?: string\n contactInfo?: ContactInfo[]\n extraData?: Record<string, any>\n}\n\nexport function createTestSessionUser(\n options?: TestUserOptions\n): SessionUser<Record<string, any>> {\n const locale = options?.locale ?? TEST_DEFAULTS.LOCALE\n const country = options?.country ?? TEST_DEFAULTS.COUNTRY\n return {\n id: options?.id ?? TEST_DEFAULTS.USER_ID,\n provider: options?.provider ?? TEST_DEFAULTS.PROVIDER,\n locale,\n country,\n system_locale: options?.systemLocale ?? locale,\n contact_info: options?.contactInfo ?? [],\n extra_data: options?.extraData ?? {},\n }\n}\n\nexport interface TestSessionOptions {\n user?: TestUserOptions\n botId?: string\n organization?: string\n organizationId?: string\n isFirstInteraction?: boolean\n isTestIntegration?: boolean\n accessToken?: string\n hubtypeApi?: string\n flowThreadId?: string\n retries?: number\n shadowing?: boolean\n hubtypeCaseId?: string\n captureUserInputNodeId?: string\n}\n\nexport function createTestSession(\n options?: TestSessionOptions\n): Session<Record<string, any>> {\n return {\n bot: { id: options?.botId ?? TEST_DEFAULTS.BOT_ID },\n user: createTestSessionUser(options?.user),\n organization: options?.organization ?? TEST_DEFAULTS.ORG_NAME,\n organization_id: options?.organizationId ?? TEST_DEFAULTS.ORG_ID,\n is_first_interaction: options?.isFirstInteraction ?? false,\n is_test_integration: options?.isTestIntegration ?? false,\n _access_token: options?.accessToken ?? TEST_DEFAULTS.ACCESS_TOKEN,\n _hubtype_api: options?.hubtypeApi ?? TEST_DEFAULTS.HUBTYPE_API_HOST,\n flow_thread_id: options?.flowThreadId ?? TEST_DEFAULTS.FLOW_THREAD_ID,\n __retries: options?.retries ?? 0,\n _shadowing: options?.shadowing,\n _hubtype_case_id: options?.hubtypeCaseId,\n capture_user_input: options?.captureUserInputNodeId\n ? { node_id: options.captureUserInputNodeId }\n : undefined,\n }\n}\n\nexport interface TestInputOptions {\n type?: Input['type']\n data?: string\n text?: string\n payload?: string\n src?: string\n botInteractionId?: string\n messageId?: string\n context?: Input['context']\n transcript?: string\n}\n\nexport function createTestInput(options?: TestInputOptions): Input {\n return {\n type: options?.type ?? INPUT.TEXT,\n data: options?.data,\n text: options?.text ?? options?.data,\n payload: options?.payload,\n src: options?.src,\n transcript: options?.transcript,\n context: options?.context,\n bot_interaction_id:\n options?.botInteractionId ?? TEST_DEFAULTS.BOT_INTERACTION_ID,\n message_id: options?.messageId ?? TEST_DEFAULTS.MESSAGE_ID,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Composite factories\n// ---------------------------------------------------------------------------\n\nexport interface TestBotRequestOptions {\n input?: TestInputOptions | Input\n session?: TestSessionOptions | Session\n lastRoutePath?: string\n settings?: Partial<BotSettings> | BotSettings\n secrets?: Partial<BotSecrets> | BotSecrets\n}\n\nfunction isFullInput(v: TestInputOptions | Input): v is Input {\n return 'bot_interaction_id' in v && 'message_id' in v\n}\n\nfunction isFullSession(v: TestSessionOptions | Session): v is Session {\n return 'bot' in v && '__retries' in v\n}\n\nfunction isFullSettings(\n v: Partial<BotSettings> | BotSettings\n): v is BotSettings {\n return (\n 'HUBTYPE_API_URL' in v &&\n 'STATIC_URL' in v &&\n 'LITELLM_API_URL' in v &&\n 'AZURE_OPENAI_API_BASE' in v &&\n 'AZURE_OPENAI_API_VERSION' in v &&\n 'LANGUAGE_DETECTION_ENABLED' in v &&\n 'CUSTOM_SHORT_URL_HOST' in v &&\n 'custom' in v\n )\n}\n\nfunction isFullSecrets(v: Partial<BotSecrets> | BotSecrets): v is BotSecrets {\n return (\n 'HUBTYPE_ACCESS_TOKEN' in v &&\n 'LITELLM_API_KEY' in v &&\n 'AZURE_OPENAI_API_KEY' in v &&\n 'custom' in v\n )\n}\n\nexport function createTestBotRequest(\n options?: TestBotRequestOptions\n): BotRequest {\n const input =\n options?.input == null\n ? createTestInput()\n : isFullInput(options.input)\n ? options.input\n : createTestInput(options.input)\n\n const session =\n options?.session == null\n ? createTestSession()\n : isFullSession(options.session)\n ? options.session\n : createTestSession(options.session)\n\n const settings =\n options?.settings == null\n ? createTestSettings()\n : isFullSettings(options.settings)\n ? options.settings\n : createTestSettings(options.settings)\n\n const secrets =\n options?.secrets == null\n ? createTestSecrets()\n : isFullSecrets(options.secrets)\n ? options.secrets\n : createTestSecrets(options.secrets)\n\n return {\n input,\n session,\n lastRoutePath: options?.lastRoutePath ?? TEST_DEFAULTS.LAST_ROUTE_PATH,\n settings,\n secrets,\n }\n}\n\nexport interface TestBotContextOptions<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n> extends TestBotRequestOptions {\n plugins?: TPlugins\n params?: Record<string, string>\n defaultDelay?: number\n defaultTyping?: number\n}\n\nexport function createTestBotContext<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n>(options?: TestBotContextOptions<TPlugins>): BotContext<TPlugins> {\n const request = createTestBotRequest(options)\n\n const sessionForLocale =\n options?.session == null\n ? createTestSession()\n : isFullSession(options.session)\n ? options.session\n : createTestSession(options.session)\n\n const locale = sessionForLocale.user.locale\n const country = sessionForLocale.user.country\n const systemLocale = sessionForLocale.user.system_locale\n\n return {\n ...request,\n plugins: options?.plugins ?? ({} as TPlugins),\n params: options?.params ?? {},\n defaultDelay: options?.defaultDelay ?? 0,\n defaultTyping: options?.defaultTyping ?? 0,\n getUserLocale: () => locale,\n getUserCountry: () => country,\n getSystemLocale: () => systemLocale,\n setUserLocale: () => undefined,\n setUserCountry: () => undefined,\n setSystemLocale: () => undefined,\n }\n}\n\n/**\n * Alias for `createTestBotContext` typed as `PluginPreRequest`.\n * PluginPreRequest === BotContext in @botonic/core.\n */\nexport const createTestPluginPreRequest = createTestBotContext\n\nexport interface TestPluginPostRequestOptions<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n> extends TestBotContextOptions<TPlugins> {\n response?: string | null\n}\n\nexport function createTestPluginPostRequest<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n>(\n options?: TestPluginPostRequestOptions<TPlugins>\n): BotContext<TPlugins> & { response: string | null } {\n return {\n ...createTestBotContext(options),\n response: options?.response ?? null,\n }\n}\n"],"names":["INPUT","PROVIDER","TEST_DEFAULTS","createTestSettings","overrides","createTestSecrets","createTestSessionUser","options","locale","country","createTestSession","undefined","createTestInput","isFullInput","v","isFullSession","isFullSettings","isFullSecrets","createTestBotRequest","input","session","settings","secrets","createTestBotContext","request","sessionForLocale","systemLocale","createTestPluginPreRequest","createTestPluginPostRequest"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/bot-config.js","sources":["../../src/utils/bot-config.ts"],"sourcesContent":["import { type ZodType, z } from 'zod'\nimport { type VariableConfigJSON, VariableType } from '../models/index'\n\nconst SESSION_USER_EXTRA_DATA_PREFIX = 'session.user.extra_data'\n\nexport const BASE_SESSION_VARIABLES: VariableConfigJSON[] = [\n { key_path: 'input.data', type: VariableType.String },\n { key_path: 'input.type', type: VariableType.String },\n {\n key_path: 'session.is_first_interaction',\n type: VariableType.Boolean,\n },\n {\n key_path: 'session.is_test_integration',\n type: VariableType.Boolean,\n },\n { key_path: 'session._shadowing', type: VariableType.Boolean },\n { key_path: 'session.user.locale', type: VariableType.String },\n {\n key_path: 'session.user.country',\n type: VariableType.String,\n },\n { key_path: 'session.user.system_locale', type: VariableType.String },\n { key_path: 'session.user.username', type: VariableType.String },\n {\n key_path: 'session.user.unformatted_phone_number',\n type: VariableType.String,\n },\n]\n\nexport function getSessionVariables(\n extraDataSchema?: ZodType\n): VariableConfigJSON[] {\n const variables = [...BASE_SESSION_VARIABLES]\n\n if (extraDataSchema) {\n variables.push(...getSessionVariablesFromZodSchema(extraDataSchema))\n }\n\n return variables\n}\n\nfunction getSessionVariablesFromZodSchema(\n schema: ZodType\n): VariableConfigJSON[] {\n const jsonSchema = z.toJSONSchema(schema) as JsonSchemaNode\n\n if (!jsonSchema.properties) {\n return []\n }\n\n return Object.entries(jsonSchema.properties).flatMap(\n ([key, propertySchema]) =>\n getSessionVariablesFromJsonSchema(\n propertySchema,\n `${SESSION_USER_EXTRA_DATA_PREFIX}.${key}`\n )\n )\n}\n\nfunction getSessionVariablesFromJsonSchema(\n schema: JsonSchemaNode,\n keyPath: string\n): VariableConfigJSON[] {\n const type = getJsonSchemaType(schema)\n\n // TODO:Arrays are not supported yet. Review in the future, how to handle them\n // in the frontend feature-flow-builder and in the plugin-flow-builder.\n if (type === 'array') {\n return []\n }\n\n if (type === 'object' && schema.properties) {\n return Object.entries(schema.properties).flatMap(([key, propertySchema]) =>\n getSessionVariablesFromJsonSchema(propertySchema, `${keyPath}.${key}`)\n )\n }\n\n const variableType = getVariableTypeFromJsonSchema(schema)\n if (!variableType) {\n return []\n }\n\n return [{ key_path: keyPath, type: variableType }]\n}\n\nfunction getJsonSchemaType(schema: JsonSchemaNode): string | undefined {\n const resolved = resolveJsonSchemaNode(schema)\n const { type } = resolved\n\n if (Array.isArray(type)) {\n return type.find(candidate => candidate !== 'null')\n }\n\n return type\n}\n\nfunction getVariableTypeFromJsonSchema(\n schema: JsonSchemaNode\n): VariableType | undefined {\n const resolved = resolveJsonSchemaNode(schema)\n const type = getJsonSchemaType(resolved)\n\n // enum is transformed to string. Review in the future, how to handle them\n if (type === 'string' || resolved.enum !== undefined) {\n return VariableType.String\n }\n\n if (type === 'number' || type === 'integer') {\n return VariableType.Number\n }\n\n if (type === 'boolean') {\n return VariableType.Boolean\n }\n\n return undefined\n}\n\ntype JsonSchemaNode = {\n type?: string | string[]\n enum?: unknown[]\n properties?: Record<string, JsonSchemaNode>\n anyOf?: JsonSchemaNode[]\n}\n\nfunction resolveJsonSchemaNode(schema: JsonSchemaNode): JsonSchemaNode {\n if (schema.anyOf?.length) {\n const nonNullSchema = schema.anyOf.find(\n candidate => candidate.type !== 'null'\n )\n if (nonNullSchema) {\n return resolveJsonSchemaNode(nonNullSchema)\n }\n }\n\n return schema\n}\n"],"names":["z","VariableType","SESSION_USER_EXTRA_DATA_PREFIX","BASE_SESSION_VARIABLES","getSessionVariables","extraDataSchema","variables","getSessionVariablesFromZodSchema","schema","jsonSchema","Object","key","propertySchema","getSessionVariablesFromJsonSchema","keyPath","type","getJsonSchemaType","variableType","getVariableTypeFromJsonSchema","resolved","resolveJsonSchemaNode","Array","candidate","undefined","nonNullSchema"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/check-providers.js","sources":["../../src/utils/check-providers.ts"],"sourcesContent":["import { PROVIDER, type Session } from '../models/legacy-types'\n\n// To check Provider in session\nexport function isDev(session: Session) {\n return session.user.provider === PROVIDER.DEV\n}\n\nexport function isWebchat(session: Session) {\n // When the provider is DEV should we return true because it is a webchat?\n return session.user.provider === PROVIDER.WEBCHAT\n}\n\nexport function isWhatsapp(session: Session) {\n return session.user.provider === PROVIDER.WHATSAPP\n}\n\nexport function isTelegram(session: Session) {\n return session.user.provider === PROVIDER.TELEGRAM\n}\n\nexport function isFacebook(session: Session) {\n return session.user.provider === PROVIDER.FACEBOOK\n}\n\nexport function isInstagram(session: Session) {\n return session.user.provider === PROVIDER.INSTAGRAM\n}\n\nexport function isTwitter(session: Session) {\n return session.user.provider === PROVIDER.TWITTER\n}\n"],"names":["PROVIDER","isDev","session","isWebchat","isWhatsapp","isTelegram","isFacebook","isInstagram","isTwitter"],"mappings":";;;AAA+D;AAE/D,+BAA+B;AACxB,SAASC,KAAKA,CAACC,OAAgB;IACpC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,YAAY;AAC/C;AAEO,SAASG,SAASA,CAACD,OAAgB;IACxC,0EAA0E;IAC1E,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,gBAAgB;AACnD;AAEO,SAASI,UAAUA,CAACF,OAAgB;IACzC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,iBAAiB;AACpD;AAEO,SAASK,UAAUA,CAACH,OAAgB;IACzC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,iBAAiB;AACpD;AAEO,SAASM,UAAUA,CAACJ,OAAgB;IACzC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,iBAAiB;AACpD;AAEO,SAASO,WAAWA,CAACL,OAAgB;IAC1C,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,kBAAkB;AACrD;AAEO,SAASQ,SAASA,CAACN,OAAgB;IACxC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,gBAAgB;AACnD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/functional.js","sources":["../../src/utils/functional.ts"],"sourcesContent":["export const isNode = (): boolean => {\n // @ts-expect-error\n return typeof IS_NODE !== 'undefined'\n ? // @ts-ignore\n IS_NODE\n : typeof process !== 'undefined' &&\n process.versions !== null &&\n process.versions.node !== null\n}\n\nexport const isBrowser = (): boolean => {\n // @ts-expect-error\n return typeof IS_BROWSER !== 'undefined'\n ? // @ts-ignore\n IS_BROWSER\n : typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n !window.process?.versions?.node // In Jest window.process?.versions?.node is defined\n}\n\nexport const isMobile = (mobileBreakpoint = 460): boolean => {\n if (isBrowser()) {\n const w = Math.max(\n document.documentElement.clientWidth,\n window.innerWidth || 0\n )\n if (w < mobileBreakpoint) {\n return true\n }\n }\n return false\n}\n\nexport function isFunction(o: any): boolean {\n return typeof o === 'function'\n}\n\nexport function cloneObject(object: any): any {\n if (!object) {\n return {}\n }\n return { ...object }\n}\n\nexport const params2queryString = (params: { [key: string]: string }): string =>\n Object.entries(params)\n .map(([k, v]: any) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&')\n\n// Joins path segments. Preserves initial \"/\" and resolves \"..\" and \".\"\n// Does not support using \"..\" to go above/outside the root.\n// This means that join(\"foo\", \"../../bar\") will not resolve to \"../bar\"\nexport const join = (...segments: string[]): string => {\n // Split the inputs into a list of path commands.\n let parts: string[] = []\n for (let i = 0, l = segments.length; i < l; i++) {\n parts = parts.concat(segments[i].split('/'))\n }\n // Interpret the path commands to get the new resolved path.\n const newParts: string[] = []\n for (let i = 0, l = parts.length; i < l; i++) {\n const part = parts[i]\n // Remove leading and trailing slashes\n // Also remove \".\" segments\n if (!part || part === '.') {\n continue\n }\n // Interpret \"..\" to pop the last segment\n if (part === '..') {\n newParts.pop()\n }\n // Push new path segments.\n else {\n newParts.push(part)\n }\n }\n // Preserve the initial slash if there was one.\n if (parts[0] === '') {\n newParts.unshift('')\n }\n // Turn back into a single string path.\n return newParts.join('/') || (newParts.length ? '/' : '.')\n}\n\n// A simple function to get the dirname of a path\n// Trailing slashes are ignored. Leading slash is preserved.\nexport const dirname = (path: string): string => join(path, '..')\n"],"names":["isNode","IS_NODE","process","isBrowser","IS_BROWSER","window","isMobile","mobileBreakpoint","w","Math","document","isFunction","o","cloneObject","object","params2queryString","params","Object","k","v","encodeURIComponent","join","segments","parts","i","l","newParts","part","dirname","path"],"mappings":"AAAO,MAAMA,MAAMA,GAAG;IACpB,mBAAmB;IACnB,OAAO,OAAOC,YAAY,cAEtBA,UACA,OAAOC,YAAY,eACjBA,QAAQ,QAAQ,KAAK,QACrBA,QAAQ,QAAQ,CAAC,IAAI,KAAK;AAClC,EAAC;AAEM,MAAMC,SAASA,GAAG;IACvB,mBAAmB;IACnB,OAAO,OAAOC,eAAe,cAEzBA,aACA,OAAOC,WAAW,eAChB,OAAOA,OAAO,QAAQ,KAAK,eAC3B,CAACA,OAAO,OAAO,EAAE,UAAU,KAAK,oDAAoD;;AAC5F,EAAC;AAEM,MAAMC,QAAQA,GAAG,CAACC,mBAAmB,GAAG;IAC7C,IAAIJ,SAASA,IAAI;QACf,MAAMK,IAAIC,KAAK,GAAG,CAChBC,SAAS,eAAe,CAAC,WAAW,EACpCL,OAAO,UAAU,IAAI;QAEvB,IAAIG,IAAID,kBAAkB;YACxB,OAAO;QACT;IACF;IACA,OAAO;AACT,EAAC;AAEM,SAASI,UAAUA,CAACC,CAAM;IAC/B,OAAO,OAAOA,MAAM;AACtB;AAEO,SAASC,WAAWA,CAACC,MAAW;IACrC,IAAI,CAACA,QAAQ;QACX,OAAO,CAAC;IACV;IACA,OAAO;QAAE,GAAGA,MAAM;IAAC;AACrB;AAEO,MAAMC,kBAAkBA,GAAG,CAACC,SACjCC,OAAO,OAAO,CAACD,QACZ,GAAG,CAAC,CAAC,CAACE,GAAGC,EAAO,GAAK,GAAGC,mBAAmBF,GAAG,CAAC,EAAEE,mBAAmBD,IAAI,EACxE,IAAI,CAAC,KAAI;AAEd,wEAAwE;AACxE,4DAA4D;AAC5D,wEAAwE;AACjE,MAAME,IAAIA,GAAG,CAAC,GAAGC;IACtB,iDAAiD;IACjD,IAAIC,QAAkB,EAAE;IACxB,IAAK,IAAIC,IAAI,GAAGC,IAAIH,SAAS,MAAM,EAAEE,IAAIC,GAAGD,IAAK;QAC/CD,QAAQA,MAAM,MAAM,CAACD,QAAQ,CAACE,EAAE,CAAC,KAAK,CAAC;IACzC;IACA,4DAA4D;IAC5D,MAAME,WAAqB,EAAE;IAC7B,IAAK,IAAIF,IAAI,GAAGC,IAAIF,MAAM,MAAM,EAAEC,IAAIC,GAAGD,IAAK;QAC5C,MAAMG,OAAOJ,KAAK,CAACC,EAAE;QACrB,sCAAsC;QACtC,2BAA2B;QAC3B,IAAI,CAACG,QAAQA,SAAS,KAAK;YACzB;QACF;QACA,yCAAyC;QACzC,IAAIA,SAAS,MAAM;YACjBD,SAAS,GAAG;QACd,OAEK;YACHA,SAAS,IAAI,CAACC;QAChB;IACF;IACA,+CAA+C;IAC/C,IAAIJ,KAAK,CAAC,EAAE,KAAK,IAAI;QACnBG,SAAS,OAAO,CAAC;IACnB;IACA,uCAAuC;IACvC,OAAOA,SAAS,IAAI,CAAC,QAASA,CAAAA,SAAS,MAAM,GAAG,MAAM,GAAE;AAC1D,EAAC;AAED,iDAAiD;AACjD,4DAA4D;AACrD,MAAME,OAAOA,GAAG,CAACC,OAAyBR,IAAIA,CAACQ,MAAM,MAAK"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/index.js","sources":["../../src/utils/index.ts"],"sourcesContent":["export * from './bot-config'\nexport * from './check-providers'\nexport * from './functional'\n"],"names":[],"mappings":";;;AAA4B;AACK;AACL"}
package/package.json CHANGED
@@ -1,28 +1,29 @@
1
1
  {
2
+ "type": "module",
2
3
  "name": "@botonic/core",
3
- "version": "0.57.0-rslib-esm.0",
4
+ "version": "0.57.0-rslib-esm.2",
4
5
  "license": "MIT",
5
6
  "description": "Build Chatbots using React",
6
- "main": "./lib/esm/index.js",
7
- "module": "./lib/esm/index.js",
7
+ "main": "./lib/index.js",
8
+ "module": "./lib/index.js",
8
9
  "exports": {
9
10
  ".": {
10
- "types": "./lib/esm/index.d.ts",
11
- "default": "./lib/esm/index.js"
11
+ "types": "./lib/index.d.ts",
12
+ "default": "./lib/index.js"
12
13
  },
13
14
  "./testing": {
14
- "types": "./lib/esm/testing/index.d.ts",
15
- "default": "./lib/esm/testing/index.js"
15
+ "types": "./lib/testing/index.d.ts",
16
+ "default": "./lib/testing/index.js"
16
17
  }
17
18
  },
18
19
  "scripts": {
19
- "test": "../../node_modules/.bin/jest --coverage",
20
+ "test": "vitest run --coverage",
20
21
  "prepublishOnly": "npm run build && npm run test && npm run lint",
21
22
  "lint": "biome check --write src/",
22
23
  "lint:check": "biome check src/",
23
24
  "format": "biome format --write src/",
24
- "build": "node ../../scripts/build/clean.mjs && rslib build --no-env",
25
- "build:watch": "node ../../scripts/build/clean.mjs && rslib build --watch --no-env",
25
+ "build": "rslib build --no-env",
26
+ "build:watch": "rslib build --watch --no-env",
26
27
  "cloc": "../../scripts/qa/cloc-package.sh ."
27
28
  },
28
29
  "repository": {
@@ -42,7 +43,7 @@
42
43
  "typesVersions": {
43
44
  "*": {
44
45
  "testing": [
45
- "./lib/esm/testing/index.d.ts"
46
+ "./lib/testing/index.d.ts"
46
47
  ]
47
48
  }
48
49
  },
@@ -55,8 +56,7 @@
55
56
  "zod": "^4.4.3"
56
57
  },
57
58
  "devDependencies": {
58
- "@types/pako": "^1.0.2",
59
- "babel-plugin-add-module-exports": "^1.0.2"
59
+ "@types/pako": "^1.0.2"
60
60
  },
61
61
  "homepage": "https://github.com/hubtype/botonic#readme",
62
62
  "engines": {
@@ -71,5 +71,5 @@
71
71
  "javascript"
72
72
  ],
73
73
  "sideEffects": false,
74
- "types": "./lib/esm/index.d.ts"
74
+ "types": "./lib/index.d.ts"
75
75
  }
@@ -5,6 +5,7 @@ export enum OutputMessageType {
5
5
  TextWithButtons = 'textWithButtons',
6
6
  BotExecutor = 'botExecutor',
7
7
  Carousel = 'carousel',
8
+ RequestContactInfo = 'requestContactInfo',
8
9
  Exit = 'exit',
9
10
  }
10
11
 
@@ -61,6 +62,13 @@ export interface CarouselMessage extends BaseMessage {
61
62
  }
62
63
  }
63
64
 
65
+ export interface RequestContactInfoMessage extends BaseMessage {
66
+ type: OutputMessageType.RequestContactInfo
67
+ content: {
68
+ text: string
69
+ }
70
+ }
71
+
64
72
  export interface ExitMessage extends BaseMessage {
65
73
  type: OutputMessageType.Exit
66
74
  }
@@ -70,6 +78,7 @@ export type OutputMessage<Extra extends BaseMessage<string> = never> =
70
78
  | TextWithButtonsMessage
71
79
  | BotExecutorMessage
72
80
  | CarouselMessage
81
+ | RequestContactInfoMessage
73
82
  | ExitMessage
74
83
  | Extra
75
84
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sources":["../../src/constants.ts"],"sourcesContent":["export const NOT_FOUND_PATH = '404'\nexport const EMPTY_ACTION_PATH = ''\nexport const PATH_PAYLOAD_IDENTIFIER = '__PATH_PAYLOAD__'\nexport const PATH_PAYLOAD_REGEXP = new RegExp(\n `\\\\b^${PATH_PAYLOAD_IDENTIFIER}(.*)\\\\b`\n)\n"],"names":["NOT_FOUND_PATH","EMPTY_ACTION_PATH","PATH_PAYLOAD_IDENTIFIER","PATH_PAYLOAD_REGEXP","RegExp"],"mappings":"AAAO,MAAMA,cAAcA,GAAG,MAAK;AAC5B,MAAMC,iBAAiBA,GAAG,GAAE;AAC5B,MAAMC,uBAAuBA,GAAG,mBAAkB;AAClD,MAAMC,mBAAmBA,GAAG,IAAIC,OACrC,CAAC,IAAI,EAAEF,uBAAuBA,CAAC,OAAO,CAAC,EACxC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-bot.js","sources":["../../src/core-bot.ts"],"sourcesContent":["import { Inspector } from './debug'\nimport {\n type BotContext,\n BotonicAction,\n type BotRequest,\n type BotResponse,\n type BotSecrets,\n type BotSettings,\n INPUT,\n type Input,\n type ProcessInputResult,\n type ResolvedPlugins,\n type Route,\n type Routes,\n type Session,\n} from './models'\nimport { runPlugins } from './plugins'\nimport { getComputedRoutes, Router } from './routing'\n\nexport interface CoreBotConfig {\n appId?: string\n defaultDelay?: number\n defaultRoutes?: Route[]\n defaultTyping?: number\n inspector?: Inspector\n plugins?: ResolvedPlugins\n renderer: any\n routes: Routes\n theme?: any\n}\n\nexport class CoreBot {\n appId?: string\n defaultDelay: number\n defaultRoutes: Route[]\n defaultTyping: number\n inspector: Inspector\n plugins: ResolvedPlugins\n renderer: any // TODO use a type like ({ request, actions }: RendererArgs) => Promise<any[]>\n rootElement: any\n router: Router | null\n routes: Routes\n theme?: any\n\n constructor({\n renderer,\n routes,\n theme,\n plugins,\n appId,\n defaultTyping = 0.6,\n defaultDelay = 0.4,\n defaultRoutes,\n inspector,\n }: CoreBotConfig) {\n this.renderer = renderer\n this.plugins = plugins || {}\n this.theme = theme || {}\n this.defaultTyping = defaultTyping\n this.defaultDelay = defaultDelay\n this.appId = appId || undefined\n this.rootElement = null\n this.inspector = inspector || new Inspector()\n this.routes = routes\n this.defaultRoutes = defaultRoutes || []\n this.router =\n this.routes instanceof Function\n ? null\n : new Router(\n [...this.routes, ...this.defaultRoutes],\n this.inspector.routeInspector\n )\n }\n\n setSystemLocale(locale: string, session: Session): void {\n session.user.system_locale = locale\n }\n\n setUserLocale(locale: string, session: Session): void {\n session.user.locale = locale\n }\n\n setUserCountry(country: string, session: Session): void {\n session.user.country = country\n }\n\n async input(request: BotRequest): Promise<BotResponse> {\n const botContext = this.getBotContext(request)\n\n const output = await this.runInput(botContext)\n\n if (\n botContext.session._botonic_action?.startsWith(BotonicAction.Redirect)\n ) {\n return await this.runRedirectAction(output, botContext)\n }\n\n return output\n }\n\n private getBotContext(request: BotRequest): BotContext {\n const { input, session, lastRoutePath } = request\n const settings = this.getSettings(request)\n const secrets = this.getSecrets(request)\n\n return {\n input,\n session,\n lastRoutePath,\n params: {},\n plugins: this.plugins,\n defaultTyping: this.defaultTyping,\n defaultDelay: this.defaultDelay,\n getUserCountry: () => session.user.country,\n getUserLocale: () => session.user.locale,\n getSystemLocale: () => session.user.system_locale,\n setUserCountry: (country: string) =>\n this.setUserCountry(country, session),\n setUserLocale: (locale: string) => this.setUserLocale(locale, session),\n setSystemLocale: (locale: string) =>\n this.setSystemLocale(locale, session),\n settings,\n secrets,\n }\n }\n\n private getSettings(request: BotRequest): BotSettings {\n if (!request.settings) {\n // This only happens in local development\n return {\n HUBTYPE_API_URL: '',\n STATIC_URL: '',\n LITELLM_API_URL: '',\n AZURE_OPENAI_API_BASE: '',\n AZURE_OPENAI_API_VERSION: '',\n CUSTOM_SHORT_URL_HOST: '',\n LANGUAGE_DETECTION_ENABLED: false,\n custom: {},\n }\n }\n\n return request.settings\n }\n\n private getSecrets(request: BotRequest): BotSecrets {\n if (!request.secrets) {\n // This only happens in local development\n return {\n HUBTYPE_ACCESS_TOKEN: '',\n LITELLM_API_KEY: '',\n AZURE_OPENAI_API_KEY: '',\n custom: {},\n }\n }\n\n return request.secrets\n }\n\n private async runInput(botContext: BotContext): Promise<BotResponse> {\n // After first updateSession, user country locale and system_locale are always defined\n this.updateSession(botContext.session)\n\n if (botContext.input.type === INPUT.CHAT_EVENT) {\n return {\n input: botContext.input,\n session: botContext.session,\n lastRoutePath: botContext.lastRoutePath,\n settings: botContext.settings,\n secrets: botContext.secrets,\n response: [],\n }\n }\n\n await this.runPrePlugins(botContext)\n\n const output = await this.getOutput(botContext)\n botContext = this.updateRequestFromOutput(botContext, output)\n const response = await this.renderer({\n request: botContext,\n actions: [output.fallbackAction, output.action, output.emptyAction],\n })\n\n await this.runPostPlugins(botContext, response)\n\n botContext.session.is_first_interaction = false\n\n return {\n input: botContext.input,\n session: botContext.session,\n lastRoutePath: botContext.lastRoutePath,\n settings: botContext.settings,\n secrets: botContext.secrets,\n response,\n }\n }\n\n private updateSession(session: Session) {\n // set new user fields (country, locale, system_locale) from old fields in extra_data\n if (!session.user.country) {\n const country = session.user.extra_data?.country\n this.setUserCountry(country, session)\n }\n\n if (!session.user.locale) {\n const language = session.user.extra_data?.language\n this.setUserLocale(language, session)\n }\n\n if (!session.user.system_locale) {\n const locale = session.user.locale\n if (locale) {\n this.setSystemLocale(locale, session)\n }\n }\n }\n\n private async runPrePlugins(botContext: BotContext) {\n if (this.plugins) {\n await runPlugins({ botContext, mode: 'pre' })\n }\n }\n\n private async getOutput(botContext: BotContext): Promise<ProcessInputResult> {\n await this.setRouter(botContext)\n\n const output = (this.router as Router).processInput(\n botContext.input,\n botContext.session,\n botContext.lastRoutePath\n )\n return output\n }\n\n private async setRouter(botContext: BotContext) {\n if (this.routes instanceof Function) {\n this.router = new Router(\n [\n ...(await getComputedRoutes(this.routes, botContext)),\n ...this.defaultRoutes,\n ],\n this.inspector.routeInspector\n )\n }\n }\n\n private updateRequestFromOutput(\n botContext: BotContext,\n output: ProcessInputResult\n ): BotContext {\n return {\n ...botContext,\n params: output.params || {},\n lastRoutePath: output.lastRoutePath,\n }\n }\n\n private async runPostPlugins(botContext: BotContext, response: any) {\n if (this.plugins) {\n await runPlugins({\n botContext,\n mode: 'post',\n response,\n })\n }\n }\n\n private async runRedirectAction(\n previousResponse: BotResponse,\n botContext: BotContext,\n numOfRedirects: number = 0\n ) {\n if (numOfRedirects > 10) {\n throw new Error('Maximum BotAction recursive calls reached (10)')\n }\n\n const nextPayload = botContext.session._botonic_action?.split(\n `${BotonicAction.Redirect}:`\n )[1]\n\n const inputWithBotActionPayload: Input = {\n ...botContext.input,\n payload: nextPayload,\n type: INPUT.POSTBACK,\n data: undefined,\n text: undefined,\n }\n\n botContext.session._botonic_action = undefined\n botContext.input = inputWithBotActionPayload\n\n const followUp = await this.runInput(botContext)\n\n const response: BotResponse = {\n input: followUp.input,\n response: previousResponse.response.concat(followUp.response),\n session: botContext.session,\n lastRoutePath: followUp.lastRoutePath,\n settings: followUp.settings,\n secrets: followUp.secrets,\n }\n\n // Recursive call to handle multiple bot actions in a row\n if (response.session._botonic_action?.startsWith(BotonicAction.Redirect)) {\n return await this.runRedirectAction(\n response,\n botContext,\n numOfRedirects + 1\n )\n }\n\n return response\n }\n}\n"],"names":["Inspector","BotonicAction","INPUT","runPlugins","getComputedRoutes","Router","CoreBot","locale","session","country","request","botContext","output","input","lastRoutePath","settings","secrets","response","language","Function","previousResponse","numOfRedirects","Error","nextPayload","inputWithBotActionPayload","undefined","followUp","renderer","routes","theme","plugins","appId","defaultTyping","defaultDelay","defaultRoutes","inspector"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"debug/index.js","sources":["../../../src/debug/index.ts"],"sourcesContent":["export * from './inspector'\n"],"names":[],"mappings":";AAA2B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"debug/inspector.js","sources":["../../../src/debug/inspector.ts"],"sourcesContent":["import type { Route, RouteMatcher } from '../models'\nexport class RouteInspector {\n routeMatched(\n _route: Route,\n _routeKey: string,\n _routeValue: RouteMatcher,\n _input: any\n ): void {}\n routeNotMatched(\n _route: Route,\n _routeKey: string,\n _routeValue: RouteMatcher,\n _input: any\n ): void {}\n}\n\nexport class FocusRouteInspector extends RouteInspector {\n focusRoutePaths: string[] | null\n focusOnMatches: boolean\n constructor() {\n super()\n this.focusRoutePaths = null\n this.focusOnMatches = false\n }\n\n focusOnlyOnRoutes(focusRoutePaths: string[]): this {\n this.focusRoutePaths = focusRoutePaths\n return this\n }\n\n focusOnlyOnMatches(): this {\n this.focusOnMatches = true\n return this\n }\n\n _isOnFocus(route: Route): boolean {\n if (this.focusRoutePaths === null) {\n return true\n }\n return this.focusRoutePaths.includes(route.path as string)\n }\n}\n\nexport class LogRouteInspector extends FocusRouteInspector {\n override routeMatched(\n route: Route,\n routeKey: string,\n routeValue: RouteMatcher,\n inputValue: string\n ): void {\n if (!this._isOnFocus(route)) {\n return\n }\n this._log(\n `Route ${this._routeName(route)} selected ` +\n `because Input.${routeKey} (${inputValue}) matched '${routeValue}'`\n )\n }\n\n override routeNotMatched(\n route: Route,\n routeKey: string,\n routeValue: RouteMatcher,\n inputValue: string\n ): void {\n if (!this._isOnFocus(route) || this.focusOnMatches) {\n return\n }\n this._log(\n `Route ${this._routeName(route)} not selected ` +\n `because Input.${routeKey} (${inputValue}) did not match '${routeValue}'`\n )\n }\n\n _routeName(obj: Route): string {\n let name = obj.path || '<<no path defined>>'\n if (obj.action) {\n name = `'${name}' (to action '${obj.action.name}')`\n }\n if (obj.redirect) {\n name = `'${name}' (with redirect to '${obj.redirect}')`\n }\n return name as string\n }\n\n _log(message: string, ...optionalParams: string[]): void {\n console.log(message, ...optionalParams)\n }\n}\n\nexport class Inspector {\n routeInspector: RouteInspector\n constructor(routeInspector: RouteInspector | undefined = undefined) {\n this.routeInspector = routeInspector || new RouteInspector()\n }\n\n getRouteInspector(): RouteInspector {\n return this.routeInspector\n }\n}\n"],"names":["RouteInspector","_route","_routeKey","_routeValue","_input","FocusRouteInspector","focusRoutePaths","route","LogRouteInspector","routeKey","routeValue","inputValue","obj","name","message","optionalParams","console","Inspector","routeInspector","undefined"],"mappings":";;;;;;;;;;;AACO,MAAMA,cAAcA;IACzB,aACEC,MAAa,EACbC,SAAiB,EACjBC,WAAyB,EACzBC,MAAW,EACL,CAAC;IACT,gBACEH,MAAa,EACbC,SAAiB,EACjBC,WAAyB,EACzBC,MAAW,EACL,CAAC;AACX;AAEO,MAAMC,mBAAmBA,SAASL,cAAcA;IASrD,kBAAkBM,eAAyB,EAAQ;QACjD,IAAI,CAAC,eAAe,GAAGA;QACvB,OAAO,IAAI;IACb;IAEA,qBAA2B;QACzB,IAAI,CAAC,cAAc,GAAG;QACtB,OAAO,IAAI;IACb;IAEA,WAAWC,KAAY,EAAW;QAChC,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM;YACjC,OAAO;QACT;QACA,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAACA,MAAM,IAAI;IACjD;IArBA,aAAc;QACZ,KAAK,IAHP,mDACA;QAGE,IAAI,CAAC,eAAe,GAAG;QACvB,IAAI,CAAC,cAAc,GAAG;IACxB;AAkBF;AAEO,MAAMC,iBAAiBA,SAASH,mBAAmBA;IAC/C,aACPE,KAAY,EACZE,QAAgB,EAChBC,UAAwB,EACxBC,UAAkB,EACZ;QACN,IAAI,CAAC,IAAI,CAAC,UAAU,CAACJ,QAAQ;YAC3B;QACF;QACA,IAAI,CAAC,IAAI,CACP,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAACA,OAAO,UAAU,CAAC,GACzC,CAAC,cAAc,EAAEE,SAAS,EAAE,EAAEE,WAAW,WAAW,EAAED,WAAW,CAAC,CAAC;IAEzE;IAES,gBACPH,KAAY,EACZE,QAAgB,EAChBC,UAAwB,EACxBC,UAAkB,EACZ;QACN,IAAI,CAAC,IAAI,CAAC,UAAU,CAACJ,UAAU,IAAI,CAAC,cAAc,EAAE;YAClD;QACF;QACA,IAAI,CAAC,IAAI,CACP,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAACA,OAAO,cAAc,CAAC,GAC7C,CAAC,cAAc,EAAEE,SAAS,EAAE,EAAEE,WAAW,iBAAiB,EAAED,WAAW,CAAC,CAAC;IAE/E;IAEA,WAAWE,GAAU,EAAU;QAC7B,IAAIC,OAAOD,IAAI,IAAI,IAAI;QACvB,IAAIA,IAAI,MAAM,EAAE;YACdC,OAAO,CAAC,CAAC,EAAEA,KAAK,cAAc,EAAED,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD;QACA,IAAIA,IAAI,QAAQ,EAAE;YAChBC,OAAO,CAAC,CAAC,EAAEA,KAAK,qBAAqB,EAAED,IAAI,QAAQ,CAAC,EAAE,CAAC;QACzD;QACA,OAAOC;IACT;IAEA,KAAKC,OAAe,EAAE,GAAGC,cAAwB,EAAQ;QACvDC,QAAQ,GAAG,CAACF,YAAYC;IAC1B;AACF;AAEO,MAAME,SAASA;IAMpB,oBAAoC;QAClC,OAAO,IAAI,CAAC,cAAc;IAC5B;IANA,YAAYC,iBAA6CC,SAAS,CAAE;QADpE;QAEE,IAAI,CAAC,cAAc,GAAGD,kBAAkB,IAAIlB,cAAcA;IAC5D;AAKF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handoff.js","sources":["../../src/handoff.ts"],"sourcesContent":["import axios from 'axios'\n\nimport { PATH_PAYLOAD_IDENTIFIER } from './constants'\nimport {\n BotonicAction,\n type BotonicActionType,\n EVENT_FORMAT_VERSION,\n type Session,\n} from './models'\n\nconst HUBTYPE_API_URL = 'https://api.hubtype.com'\n\nexport interface HubtypeAgentsInfo {\n attending_count: number\n email: string\n idle_count: number\n last_message_sent: string\n status: string\n}\n\nexport interface BackendContext {\n timeoutMs: number\n}\n\nexport interface VacationRange {\n end_date: number // timestamp\n id: number\n start_date: number // timestamp\n}\n\nexport type HandoffExtraData = {\n language?: string\n url?: string\n location?: string\n}\n\nexport interface BotEventData {\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n}\n\nexport interface FormattedBotEventData {\n format_version: number\n flow_id: string\n flow_name: string\n flow_node_id: string\n flow_node_content_id: string\n}\n\nexport enum HelpdeskEvent {\n StatusChanged = 'status_changed',\n AgentMessageCreated = 'agent_message_created',\n QueuePositionChanged = 'queue_position_changed',\n}\n\nfunction contextDefaults(context: any): BackendContext {\n return {\n timeoutMs: context.timeoutMs || 10000,\n }\n}\n\nexport async function getOpenQueues(\n session: Session,\n context = {}\n): Promise<{ queues: string[] }> {\n //be aware of https://github.com/axios/axios/issues/1543\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const endpointUrl = `${baseUrl}/v1/queues/get_open_queues/`\n context = contextDefaults(context)\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: endpointUrl,\n data: { bot_id: session.bot.id },\n timeout: (context as BackendContext).timeoutMs,\n })\n return resp.data\n}\n\nexport class HandOffBuilder {\n _session: Session\n _queue: string\n _onFinish: string\n _email: string\n _agentId: string\n _forceAssignIfNotAvailable: boolean\n _autoAssignOnWaiting: boolean\n _note: string\n _caseInfo: string\n _autoIdleMessage: string\n _shadowing: boolean\n _extraData: HandoffExtraData\n _bot_event: FormattedBotEventData\n _subscribeHelpdeskEvents: HelpdeskEvent[]\n\n constructor(session: Session) {\n this._session = session\n }\n\n withQueue(queueNameOrId: string): this {\n this._queue = queueNameOrId\n return this\n }\n\n withOnFinishPayload(payload: string): this {\n this._onFinish = payload\n return this\n }\n\n withOnFinishPath(path: string): this {\n this._onFinish = `${PATH_PAYLOAD_IDENTIFIER}${path}`\n return this\n }\n\n withAgentEmail(email: string): this {\n this._email = email\n return this\n }\n\n withAgentId(agentId: string): this {\n this._agentId = agentId\n return this\n }\n\n withForceAssignIfNotAvailable(forceAssign: boolean): this {\n this._forceAssignIfNotAvailable = forceAssign\n return this\n }\n\n withAutoAssignOnWaiting(autoAssignOnWaiting: boolean): this {\n this._autoAssignOnWaiting = autoAssignOnWaiting\n return this\n }\n\n withNote(note: string): this {\n this._note = note\n return this\n }\n\n withCaseInfo(caseInfo: string): this {\n this._caseInfo = caseInfo\n return this\n }\n\n withAutoIdleMessage(message: string): this {\n this._autoIdleMessage = message\n return this\n }\n\n withShadowing(shadowing = true): this {\n this._shadowing = shadowing\n return this\n }\n\n withExtraData(extraData: HandoffExtraData): this {\n this._extraData = extraData\n return this\n }\n\n withBotEvent(botEvent: BotEventData): this {\n this._bot_event = {\n format_version: EVENT_FORMAT_VERSION,\n flow_id: botEvent.flowId,\n flow_name: botEvent.flowName,\n flow_node_id: botEvent.flowNodeId,\n flow_node_content_id: botEvent.flowNodeContentId,\n }\n return this\n }\n\n withSubscribeHelpdeskEvents(events: HelpdeskEvent[]): this {\n this._subscribeHelpdeskEvents = events\n return this\n }\n\n async handOff(): Promise<void> {\n return _humanHandOff(\n this._session,\n this._queue,\n this._onFinish,\n this._email,\n this._agentId,\n this._forceAssignIfNotAvailable,\n this._autoAssignOnWaiting,\n this._caseInfo,\n this._note,\n this._autoIdleMessage,\n this._shadowing,\n this._extraData,\n this._bot_event,\n this._subscribeHelpdeskEvents\n )\n }\n}\n\n/**\n * @deprecated use {@link HandOffBuilder} class instead\n */\nexport async function humanHandOff(session, queueNameOrId = '', onFinish) {\n const builder = new HandOffBuilder(session)\n if (queueNameOrId) {\n builder.withQueue(queueNameOrId)\n }\n if (onFinish) {\n if (onFinish.path) {\n builder.withOnFinishPath(onFinish.path)\n } else if (onFinish.payload) {\n builder.withOnFinishPayload(onFinish.payload)\n } else {\n throw new Error('onFinish requires payload or path field')\n }\n }\n return builder.handOff()\n}\n\nexport interface HubtypeHandoffParams {\n queue?: string\n agent_email?: string\n agent_id?: string\n force_assign_if_not_available?: boolean\n auto_assign_on_waiting?: boolean\n case_info?: string\n note?: string\n auto_idle_message?: string\n shadowing?: boolean\n on_finish?: string\n case_extra_data?: HandoffExtraData\n bot_event?: FormattedBotEventData\n subscribe_helpdesk_events?: HelpdeskEvent[]\n}\nasync function _humanHandOff(\n session: Session,\n queueNameOrId = '',\n onFinish: string,\n agentEmail = '',\n agentId = '',\n forceAssignIfNotAvailable = true,\n autoAssignOnWaiting = false,\n caseInfo = '',\n note = '',\n autoIdleMessage = '',\n shadowing = false,\n extraData: HandoffExtraData | undefined = undefined,\n botEvent: FormattedBotEventData,\n subscribeHelpdeskEvents: HelpdeskEvent[] = []\n) {\n const params: HubtypeHandoffParams = {}\n\n params.force_assign_if_not_available = forceAssignIfNotAvailable\n\n if (queueNameOrId) {\n params.queue = queueNameOrId\n }\n if (agentEmail) {\n params.agent_email = agentEmail\n }\n if (agentId) {\n params.agent_id = agentId\n }\n if (autoAssignOnWaiting) {\n params.auto_assign_on_waiting = autoAssignOnWaiting\n }\n if (caseInfo) {\n params.case_info = caseInfo\n }\n if (note) {\n params.note = note\n }\n if (autoIdleMessage) {\n params.auto_idle_message = autoIdleMessage\n }\n if (shadowing) {\n params.shadowing = shadowing\n }\n if (onFinish) {\n params.on_finish = onFinish\n }\n if (extraData) {\n params.case_extra_data = extraData\n }\n if (botEvent) {\n params.bot_event = botEvent\n }\n if (subscribeHelpdeskEvents.length > 0) {\n params.subscribe_helpdesk_events = subscribeHelpdeskEvents\n }\n session._botonic_action = `${BotonicAction.CreateCase}:${JSON.stringify(params)}`\n}\n\nexport async function storeCaseRating(\n session: Session,\n rating: number,\n context: any = {}\n): Promise<{ status: string }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const chatId = session.user.id\n context = contextDefaults(context)\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: `${baseUrl}/v1/chats/${chatId}/store_case_rating/`,\n data: { chat_id: chatId, rating },\n timeout: (context as BackendContext).timeoutMs,\n })\n return resp.data\n}\n\nexport async function getAvailableAgentsByQueue(\n session: Session,\n queueId: string\n): Promise<{ agents: string[] }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: `${baseUrl}/v1/queues/${queueId}/get_available_agents/`,\n })\n return resp.data\n}\n\nexport async function getAvailableAgents(\n session: Session\n): Promise<{ agents: HubtypeAgentsInfo[] }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const botId = session.bot.id\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'post',\n url: `${baseUrl}/v1/bots/${botId}/get_agents/`,\n })\n return resp.data\n}\n\nexport async function getAgentVacationRanges(\n session: Session,\n { agentId, agentEmail }: { agentId?: string; agentEmail?: string }\n): Promise<{ vacation_ranges: VacationRange[] }> {\n const baseUrl = session._hubtype_api || HUBTYPE_API_URL\n const botId = session.bot.id\n const resp = await axios({\n headers: {\n Authorization: `Bearer ${session._access_token}`,\n },\n method: 'get',\n url: `${baseUrl}/v1/bots/${botId}/get_agent_vacation_ranges/`,\n params: { agent_id: agentId, agent_email: agentEmail },\n })\n return resp.data\n}\n\nexport function cancelHandoff(\n session: Session,\n typification: string | null = null\n): void {\n let action: BotonicActionType = BotonicAction.DiscardCase\n if (typification) {\n action = `${action}:${JSON.stringify({ typification })}`\n }\n session._botonic_action = action\n}\n\nexport function deleteUser(session: Session): void {\n session._botonic_action = BotonicAction.DeleteUser\n}\n"],"names":["axios","PATH_PAYLOAD_IDENTIFIER","BotonicAction","EVENT_FORMAT_VERSION","HUBTYPE_API_URL","HelpdeskEvent","contextDefaults","context","getOpenQueues","session","baseUrl","endpointUrl","resp","HandOffBuilder","queueNameOrId","payload","path","email","agentId","forceAssign","autoAssignOnWaiting","note","caseInfo","message","shadowing","extraData","botEvent","events","_humanHandOff","humanHandOff","onFinish","builder","Error","agentEmail","forceAssignIfNotAvailable","autoIdleMessage","undefined","subscribeHelpdeskEvents","params","JSON","storeCaseRating","rating","chatId","getAvailableAgentsByQueue","queueId","getAvailableAgents","botId","getAgentVacationRanges","cancelHandoff","typification","action","deleteUser"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hubtype-service.js","sources":["../../src/hubtype-service.ts"],"sourcesContent":["import axios, { type AxiosResponse } from 'axios'\nimport Pusher, { type AuthOptions, type Channel, type Runtime } from 'pusher-js'\nimport type Channels from 'pusher-js/types/src/core/channels/channels'\n\nimport type { Input, SessionUser } from './models'\nimport { decompressData } from './pusher-utils'\n\ninterface UnsentInput {\n id: string\n ack: number\n unsentInput: Input\n}\n\ninterface BotonicHeaders {\n 'X-BOTONIC-USER-ID': string\n 'X-BOTONIC-LAST-MESSAGE-ID': string\n 'X-BOTONIC-LAST-MESSAGE-UPDATE-DATE': string\n}\n\nexport interface ServerConfig {\n activityTimeout?: number\n pongTimeout?: number\n}\n\ninterface HubtypeServiceArgs {\n appId: string\n user: SessionUser\n lastMessageId?: string\n lastMessageUpdateDate?: string\n onEvent: any\n unsentInputs: () => UnsentInput[]\n server?: ServerConfig\n}\n\nconst WEBCHAT_PUSHER_KEY =\n process.env.WEBCHAT_PUSHER_KEY || '434ca667c8e6cb3f641c' // pragma: allowlist secret\n\nconst HUBTYPE_API_URL = process.env.HUBTYPE_API_URL || 'https://api.hubtype.com'\n\nconst ACTIVITY_TIMEOUT = 20 * 1000 // https://pusher.com/docs/channels/using_channels/connection#activitytimeout-integer-\nconst PONG_TIMEOUT = 5 * 1000 // https://pusher.com/docs/channels/using_channels/connection#pongtimeout-integer-\n\n/**\n * Calls Hubtype APIs from Webchat\n */\nexport class HubtypeService {\n public appId: string\n public user: SessionUser\n public lastMessageId?: string\n public lastMessageUpdateDate?: string\n public onEvent: (event: any) => void\n public unsentInputs: () => UnsentInput[]\n // Pusher 5's CJS default is a namespace under NodeNext. Its named Runtime\n // interface exposes the same constructor without that interop ambiguity.\n public pusher: InstanceType<Parameters<Runtime['setup']>[0]> | null\n public channel: Channel\n public server?: ServerConfig\n public PUSHER_CONNECT_TIMEOUT_MS = 10000\n\n constructor({\n appId,\n user,\n lastMessageId,\n lastMessageUpdateDate,\n onEvent,\n unsentInputs,\n server,\n }: HubtypeServiceArgs) {\n this.appId = appId\n this.user = user || {}\n this.lastMessageId = lastMessageId\n this.lastMessageUpdateDate = lastMessageUpdateDate\n this.onEvent = onEvent\n this.unsentInputs = unsentInputs\n this.server = server\n\n if (this.user.id && (lastMessageId || lastMessageUpdateDate)) {\n // It's safe not awaiting Promise because:\n // * it will never be called from AWS lambda\n // * though init() is called again from postMesage, it does nothing if Pusher already created\n this.init()\n }\n }\n\n init(\n user?: SessionUser,\n lastMessageId?: string,\n lastMessageUpdateDate?: string\n ): Promise<void> {\n if (user) {\n this.user = user\n }\n\n if (lastMessageId) {\n this.lastMessageId = lastMessageId\n }\n\n if (lastMessageUpdateDate) {\n this.lastMessageUpdateDate = lastMessageUpdateDate\n }\n\n return this._initPusher()\n }\n\n _initPusher(): Promise<void> {\n if (this.pusher) {\n return Promise.resolve()\n }\n if (!this.user.id || !this.appId) {\n // TODO recover user & appId somehow\n return Promise.reject('No User or appId. Clear cache and reload')\n }\n this.pusher = new Pusher(WEBCHAT_PUSHER_KEY, {\n cluster: 'eu',\n authEndpoint: `${HUBTYPE_API_URL}/v1/provider_accounts/webhooks/webchat/${this.appId}/auth/`,\n forceTLS: true,\n auth: {\n headers: this.constructHeaders(),\n } as AuthOptions,\n ...this.resolveServerConfig(),\n })\n this.channel = this.pusher.subscribe(this.pusherChannel)\n const connectionPromise = new Promise<void>((resolve, reject) => {\n const cleanAndReject = msg => {\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n clearTimeout(connectTimeout)\n this.destroyPusher()\n reject(msg)\n }\n const connectTimeout = setTimeout(\n () => cleanAndReject('Connection Timeout'),\n this.PUSHER_CONNECT_TIMEOUT_MS\n )\n this.channel.bind('pusher:subscription_succeeded', () => {\n // Once subscribed, we know that authentication has been done: https://pusher.com/docs/channels/server_api/authenticating-users\n this.onConnectionRegained()\n clearTimeout(connectTimeout)\n resolve()\n })\n this.channel.bind('botonic_response', data => this.onPusherEvent(data))\n this.channel.bind('botonic_response_compressed', compressedData => {\n try {\n const data = JSON.parse(decompressData(compressedData))\n this.onPusherEvent(data)\n } catch (e) {\n console.error('Error: Unable to decompress data', e)\n }\n })\n this.channel.bind('update_message_info', data => this.onPusherEvent(data))\n\n this.pusher?.connection.bind('error', event => {\n if (event.type === 'WebSocketError') {\n this.handleConnectionChange(false)\n } else {\n const errorMsg = event.error?.data\n ? event.error.data.code || event.error.data.message\n : 'Connection error'\n cleanAndReject(`Pusher error (${errorMsg})`)\n }\n })\n })\n this.pusher.connection.bind('state_change', states => {\n if (states.current === 'connecting') {\n this.updateAuthHeaders()\n }\n if (states.current === 'connected') {\n this.handleConnectionChange(true)\n }\n if (states.current === 'unavailable') {\n this.handleConnectionChange(false)\n }\n })\n\n return connectionPromise\n }\n\n constructHeaders(): BotonicHeaders {\n const headers = {}\n if (this.user?.id) {\n headers['X-BOTONIC-USER-ID'] = this.user.id\n }\n\n if (this.lastMessageId) {\n headers['X-BOTONIC-LAST-MESSAGE-ID'] = this.lastMessageId\n }\n\n if (this.lastMessageUpdateDate) {\n headers['X-BOTONIC-LAST-MESSAGE-UPDATE-DATE'] = this.lastMessageUpdateDate\n }\n\n return headers as BotonicHeaders\n }\n\n resolveServerConfig(): ServerConfig {\n if (!this.server) {\n return { activityTimeout: ACTIVITY_TIMEOUT, pongTimeout: PONG_TIMEOUT }\n }\n return {\n activityTimeout: this.server.activityTimeout || ACTIVITY_TIMEOUT,\n pongTimeout: this.server.pongTimeout || PONG_TIMEOUT,\n }\n }\n\n updateAuthHeaders(): void {\n if (this.pusher) {\n this.pusher.config.auth.headers = {\n ...this.pusher.config.auth.headers,\n ...this.constructHeaders(),\n }\n }\n }\n\n handleConnectionChange(online: boolean): void {\n this.onPusherEvent({ action: 'connectionChange', online })\n }\n\n onPusherEvent(event: any): void {\n if (this.onEvent && typeof this.onEvent === 'function') {\n this.onEvent(event)\n }\n }\n\n get pusherChannel(): string {\n return `private-encrypted-${this.appId}-${this.user.id}`\n }\n\n handleSentInput(message: any): void {\n this.onEvent({\n action: 'update_message_info',\n message: { id: message.id, ack: 1 },\n })\n }\n\n handleUnsentInput(message: any): void {\n this.onEvent({\n action: 'update_message_info',\n message: { id: message.id, ack: 0, unsentInput: message },\n })\n }\n\n async postMessage(user: SessionUser, message: any): Promise<void> {\n try {\n await this.init(user)\n await axios.post(\n `${HUBTYPE_API_URL}/v1/provider_accounts/webhooks/webchat/${this.appId}/`,\n {\n sender: this.user,\n message: message,\n },\n {\n validateStatus: status => status === 200,\n }\n )\n this.handleSentInput(message)\n } catch (_e) {\n this.handleUnsentInput(message)\n }\n return Promise.resolve()\n }\n\n static async getWebchatVisibility(\n appId: string\n ): Promise<AxiosResponse<any>> {\n return axios.get(\n `${HUBTYPE_API_URL}/v1/provider_accounts/${appId}/visibility/`\n )\n }\n\n destroyPusher(): void {\n if (!this.pusher) {\n return\n }\n\n this.pusher.disconnect()\n this.pusher.unsubscribe(this.pusherChannel)\n this.pusher.unbind_all()\n this.pusher.channels = {} as Channels\n this.pusher = null\n }\n\n async onConnectionRegained(): Promise<void> {\n await this.resendUnsentInputs()\n }\n\n async resendUnsentInputs(): Promise<void> {\n for (const message of this.unsentInputs()) {\n message.unsentInput &&\n (await this.postMessage(this.user, message.unsentInput))\n }\n }\n}\n"],"names":["axios","Pusher","decompressData","WEBCHAT_PUSHER_KEY","process","HUBTYPE_API_URL","ACTIVITY_TIMEOUT","PONG_TIMEOUT","HubtypeService","user","lastMessageId","lastMessageUpdateDate","Promise","connectionPromise","resolve","reject","cleanAndReject","msg","clearTimeout","connectTimeout","setTimeout","data","compressedData","JSON","e","console","event","errorMsg","states","headers","online","message","status","_e","appId","onEvent","unsentInputs","server"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["export * from './constants'\nexport * from './core-bot'\nexport * from './debug'\nexport * from './handoff'\nexport * from './hubtype-service'\nexport * from './models'\nexport * from './plugins'\nexport * from './routing'\nexport * from './utils'\n"],"names":[],"mappings":";;;;;;;;;AAA2B;AACD;AACH;AACE;AACQ;AACT;AACC;AACA;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"models/ai-agents.js","sources":["../../../src/models/ai-agents.ts"],"sourcesContent":["import type { z } from 'zod'\n\nexport enum OutputMessageType {\n Text = 'text',\n TextWithButtons = 'textWithButtons',\n BotExecutor = 'botExecutor',\n Carousel = 'carousel',\n Exit = 'exit',\n}\n\nexport interface BaseMessage<T extends string = OutputMessageType> {\n type: T\n}\n\nexport interface Button {\n text: string\n payload?: string\n url?: string\n target?: string\n}\nexport interface ButtonWithPayload {\n text: string\n payload: string\n}\n\nexport interface TextMessage extends BaseMessage {\n type: OutputMessageType.Text\n content: {\n text: string\n }\n}\n\nexport interface TextWithButtonsMessage extends BaseMessage {\n type: OutputMessageType.TextWithButtons\n content: {\n text: string\n buttons: Button[]\n }\n}\n\nexport interface BotExecutorMessage extends BaseMessage {\n type: OutputMessageType.BotExecutor\n content: {\n text: string\n buttons: ButtonWithPayload[]\n }\n}\n\ninterface CarouselElement {\n title: string\n subtitle: string\n image: string\n button: Button\n}\n\nexport interface CarouselMessage extends BaseMessage {\n type: OutputMessageType.Carousel\n content: {\n text?: string\n elements: CarouselElement[]\n }\n}\n\nexport interface ExitMessage extends BaseMessage {\n type: OutputMessageType.Exit\n}\n\nexport type OutputMessage<Extra extends BaseMessage<string> = never> =\n | TextMessage\n | TextWithButtonsMessage\n | BotExecutorMessage\n | CarouselMessage\n | ExitMessage\n | Extra\n\nexport type AgenticOutputMessage<Extra extends BaseMessage<string> = never> =\n Exclude<OutputMessage<Extra>, ExitMessage>\n\nexport interface ToolExecution {\n toolName: string\n toolArguments: Record<string, any>\n toolResults?: string\n knowledgebaseSourcesIds?: string[]\n knowledgebaseChunksIds?: string[]\n}\n\nexport interface AvailableSpecialist {\n name: string\n description: string\n}\n\nexport interface RunResult<Extra extends BaseMessage<string> = never> {\n messages: AgenticOutputMessage<Extra>[]\n toolsExecuted: ToolExecution[]\n memoryLength: number\n exit: boolean\n error: boolean\n inputGuardrailsTriggered: string[]\n outputGuardrailsTriggered: string[]\n startingAgentName: string\n lastAgentName: string\n availableSpecialists: AvailableSpecialist[]\n isTransferredToSpecialist: boolean\n}\n\nexport type InferenceResponse<Extra extends BaseMessage<string> = never> =\n RunResult<Extra>\n\nexport interface GuardrailRule {\n name: string\n description: string\n}\nexport enum VerbosityLevel {\n Low = 'low',\n Medium = 'medium',\n High = 'high',\n}\n\nexport enum ReasoningEffort {\n None = 'none',\n Low = 'low',\n Medium = 'medium',\n High = 'high',\n}\n\nexport interface HubtypeAssistantMessage {\n role: 'assistant'\n content: string\n}\n\nexport interface HubtypeUserMessage {\n role: 'user'\n content: string\n}\n\nexport enum AiAgentType {\n Specialist = 'specialist',\n Router = 'router',\n}\n\nexport type AiAgentArgs = AiAgentSpecialistArgs | AIAgentRouterArgs\n\nexport type AiAgentBaseArgs = {\n type: AiAgentType\n name: string\n instructions: string\n model: string\n verbosity: VerbosityLevel\n reasoningEffort?: ReasoningEffort\n disableForceRetrieveKnowledge?: boolean // If true, the agent will not force the retrieve knowledge tool to be used.\n inputGuardrailRules?: GuardrailRule[]\n previousHubtypeMessages?: HubtypeAssistantMessage[]\n outputMessagesSchemas?: z.ZodObject<any>[]\n forceToolNameOverride?: string\n}\n\nexport interface AiAgentSpecialistArgs extends AiAgentBaseArgs {\n type: AiAgentType.Specialist\n activeTools: { name: string }[]\n sourceIds: string[]\n}\n\ninterface AIAgentRoute extends AiAgentSpecialistArgs {\n description: string\n}\n\nexport interface AIAgentRouterArgs extends AiAgentBaseArgs {\n type: AiAgentType.Router\n specialists: AIAgentRoute[]\n}\n"],"names":["OutputMessageType","VerbosityLevel","ReasoningEffort","AiAgentType"],"mappings":"AAEO,IAAKA,2BAAiBA,0BAAjBA;;;;;;WAAAA;MAMX;AAwGM,IAAKC,wBAAcA,0BAAdA;;;;WAAAA;MAIX;AAEM,IAAKC,yBAAeA,0BAAfA;;;;;WAAAA;MAKX;AAYM,IAAKC,qBAAWA,0BAAXA;;;WAAAA;MAGX"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"models/bot-config.js","sources":["../../../src/models/bot-config.ts"],"sourcesContent":["import type { core } from 'zod'\n\n// This types are used in the bot-config.ts file to load the bot config when deploy a bot.\nexport interface BotConfigJSON {\n tools: ToolConfigJSON[]\n payloads: string[]\n webviews: WebviewConfigJSON[]\n variables?: VariableConfigJSON[]\n}\n\nexport interface ToolConfigJSON {\n name: string\n schema?: core.JSONSchema.JSONSchema\n description: string\n}\n\nexport interface WebviewConfigJSON {\n name: string\n}\n\nexport enum VariableType {\n String = 'string',\n Number = 'number',\n Boolean = 'boolean',\n}\n\nexport interface VariableConfigJSON {\n key_path: string\n type: VariableType\n}\n"],"names":["VariableType"],"mappings":"AAoBO,IAAKA,uBAAYA,0BAAZA;;;;WAAAA;MAIX"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"models/hubtype-analytics.js","sources":["../../../src/models/hubtype-analytics.ts"],"sourcesContent":["import type { AvailableSpecialist, ToolExecution } from './ai-agents'\n\nexport const EVENT_FORMAT_VERSION = 5\n\nexport enum EventAction {\n AiAgent = 'ai_agent',\n FeedbackCase = 'feedback_case',\n FeedbackMessage = 'feedback_message',\n FeedbackConversation = 'feedback_conversation',\n FeedbackWebview = 'feedback_webview',\n FlowNode = 'flow_node',\n ConditionalCountry = 'conditional_country',\n ConditionalQueueStatus = 'conditional_queue_status',\n ConditionalCustom = 'conditional_custom',\n ConditionalChannel = 'conditional_channel',\n BotAction = 'bot_action',\n WebviewActionTriggered = 'webview_action_triggered',\n HandoffOption = 'handoff_option',\n HandoffSuccess = 'handoff_success',\n HandoffFail = 'handoff_fail',\n Keyword = 'nlu_keyword',\n IntentSmart = 'nlu_intent_smart',\n Fallback = 'fallback',\n WebviewStep = 'webview_step',\n WebviewEnd = 'webview_end',\n Custom = 'custom',\n RedirectFlow = 'redirect_flow',\n CaptureUserInput = 'capture_user_input',\n AiAgentRouter = 'ai_agent_router',\n}\n\nexport interface HtBaseEventProps {\n action: EventAction\n}\n\nexport interface HtBaseEventAllFlowProps extends HtBaseEventProps {\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n flowNodeIsMeaningful: boolean\n}\n\nexport interface EventFeedback extends HtBaseEventProps {\n action:\n | EventAction.FeedbackCase\n | EventAction.FeedbackConversation\n | EventAction.FeedbackMessage\n | EventAction.FeedbackWebview\n feedbackTargetId: string\n feedbackGroupId: string\n possibleOptions: string[]\n possibleValues?: number[]\n option: string\n value?: number\n comment?: string\n}\n\nexport interface EventFlow extends HtBaseEventProps {\n action: EventAction.FlowNode\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n flowNodeIsMeaningful?: boolean\n}\n\nexport interface EventBotAction extends HtBaseEventAllFlowProps {\n action: EventAction.BotAction\n payload: string\n}\n\nexport interface EventConditionalCountry extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalCountry\n country: string\n}\n\nexport interface EventConditionalQueueStatus extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalQueueStatus\n queueId: string\n queueName: string\n isQueueOpen: boolean\n isAvailableAgent: boolean\n}\n\nexport interface EventConditionalCustom extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalCustom\n conditionalVariable: string\n variableFormat: string\n operator: string\n}\n\nexport interface EventConditionalChannel extends HtBaseEventAllFlowProps {\n action: EventAction.ConditionalChannel\n channel: string\n}\n\nexport interface EventHandoff extends HtBaseEventProps {\n action: EventAction.HandoffSuccess | EventAction.HandoffFail\n flowThreadId?: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n queueId: string\n queueName: string\n caseId?: string\n isQueueOpen?: boolean\n isAvailableAgent?: boolean\n isThresholdReached?: boolean\n}\n\nexport interface EventHandoffOption extends HtBaseEventProps {\n action: EventAction.HandoffOption\n flowThreadId?: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n queueId?: string\n queueName?: string\n}\n\nexport interface EventKeyword extends HtBaseEventProps {\n action: EventAction.Keyword\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n nluKeywordName: string\n nluKeywordIsRegex?: boolean\n nluKeywordMessageId: string\n userInput: string\n}\n\nexport interface EventIntentSmart extends HtBaseEventProps {\n action: EventAction.IntentSmart\n flowThreadId: string\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n nluIntentSmartTitle: string\n nluIntentSmartNumUsed: number\n nluIntentSmartMessageId: string\n userInput: string\n}\n\nexport interface EventWebviewActionTriggered extends HtBaseEventAllFlowProps {\n action: EventAction.WebviewActionTriggered\n webviewTargetId: string\n webviewName: string\n webviewParams?: Record<string, string>\n}\n\nexport interface EventAiAgent extends HtBaseEventAllFlowProps {\n action: EventAction.AiAgent\n toolsExecuted: ToolExecution[]\n inputMessageId: string\n memoryLength: number\n inputGuardrailsTriggered: string[]\n outputGuardrailsTriggered: string[]\n exit: boolean\n error: boolean\n}\n\nexport interface EventAiAgentRouter extends HtBaseEventAllFlowProps {\n action: EventAction.AiAgentRouter\n inputMessageId: string\n memoryLength: number\n inputGuardrailsTriggered: string[]\n outputGuardrailsTriggered: string[]\n exit: boolean\n error: boolean\n startingAgentName: string\n lastAgentName: string\n availableSpecialists: AvailableSpecialist[]\n isTransferredToSpecialist: boolean\n}\n\nexport interface EventRedirectFlow extends HtBaseEventAllFlowProps {\n action: EventAction.RedirectFlow\n flowTargetId: string\n flowTargetName: string\n}\n\nexport interface EventCaptureUserInput extends HtBaseEventAllFlowProps {\n action: EventAction.CaptureUserInput\n fieldName: string\n userInput: string\n captureSuccess: boolean\n messageId: string\n}\n\nexport interface EventFallback extends HtBaseEventProps {\n action: EventAction.Fallback\n flowId: string\n flowName: string\n flowNodeId: string\n flowNodeContentId: string\n userInput: string\n fallbackOut: number\n fallbackMessageId: string\n}\n\nexport interface EventWebviewStep extends HtBaseEventProps {\n action: EventAction.WebviewStep\n flowThreadId?: string\n webviewThreadId: string\n webviewName: string\n webviewStepName: string\n webviewStepNumber: number\n}\n\nexport interface EventWebviewEnd extends HtBaseEventProps {\n action: EventAction.WebviewEnd\n flowThreadId?: string\n webviewThreadId: string\n webviewName: string\n webviewStepName?: string\n webviewStepNumber?: number\n webviewEndFailType?: WebviewEndFailType\n webviewEndFailMessage?: string\n}\n\nexport enum WebviewEndFailType {\n CanceledByUser = 'canceled_by_user',\n ApiError = 'api_error',\n NeedsEscalation = 'needs_escalation',\n}\n\nexport interface EventCustom extends HtBaseEventProps {\n action: EventAction.Custom\n customFields?: Record<string, any>\n customSensitiveFields?: Record<string, any>\n}\n"],"names":["EVENT_FORMAT_VERSION","EventAction","WebviewEndFailType"],"mappings":"AAEO,MAAMA,oBAAoBA,GAAG,EAAC;AAE9B,IAAKC,6BAAWA,0BAAXA;;;;;;;;;;;;;;;;;;;;;;;;;WAAAA;MAyBX;AAuMM,IAAKC,oCAAkBA,0BAAlBA;;;;WAAAA;MAIX"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"models/index.js","sources":["../../../src/models/index.ts"],"sourcesContent":["export * from './ai-agents'\nexport * from './bot-config'\nexport * from './hubtype-analytics'\nexport * from './legacy-types'\n"],"names":[],"mappings":";;;;AAA2B;AACC;AACO;AACL"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"models/legacy-types.js","sources":["../../../src/models/legacy-types.ts"],"sourcesContent":["// TODO: This file contains all the legacy types we had in index.ts. After some refactors, we should be able to get rid of many of them.\n\nexport enum CASE_STATUS {\n WAITING = 'status_waiting',\n ATTENDING = 'status_attending',\n IDLE = 'status_idle',\n RESOLVED = 'status_resolved',\n}\n\nexport type CaseStatusType =\n | CASE_STATUS.ATTENDING\n | CASE_STATUS.IDLE\n | CASE_STATUS.RESOLVED\n | CASE_STATUS.WAITING\n\nexport enum CASE_RESOLUTION {\n OK = 'result_ok',\n NOK = 'result_nok',\n NOT_SOLVED = 'result_not_solved',\n BANNED = 'result_banned',\n}\n\nexport type CaseResolution =\n | CASE_RESOLUTION.BANNED\n | CASE_RESOLUTION.NOK\n | CASE_RESOLUTION.NOT_SOLVED\n | CASE_RESOLUTION.OK\n\nexport enum PROVIDER {\n APPLE = 'apple',\n DEV = 'dev',\n FACEBOOK = 'facebook',\n GENERIC = 'generic',\n INSTAGRAM = 'instagram',\n INTERCOM = 'intercom',\n SMOOCH = 'smooch',\n TELEGRAM = 'telegram',\n TWITTER = 'twitter',\n WEBCHAT = 'webchat',\n WECHAT = 'wechat',\n WHATSAPP = 'whatsapp',\n}\n\nexport type ProviderType =\n | PROVIDER.DEV\n | PROVIDER.FACEBOOK\n | PROVIDER.GENERIC\n | PROVIDER.INSTAGRAM\n | PROVIDER.INTERCOM\n | PROVIDER.SMOOCH\n | PROVIDER.TELEGRAM\n | PROVIDER.TWITTER\n | PROVIDER.WEBCHAT\n | PROVIDER.WECHAT\n | PROVIDER.WHATSAPP\n\nexport enum INPUT {\n TEXT = 'text',\n POSTBACK = 'postback',\n AUDIO = 'audio',\n IMAGE = 'image',\n VIDEO = 'video',\n DOCUMENT = 'document',\n LOCATION = 'location',\n CONTACT = 'contact',\n BUTTON_MESSAGE = 'buttonmessage',\n CAROUSEL = 'carousel',\n CUSTOM = 'custom',\n WEBCHAT_SETTINGS = 'webchatsettings',\n WHATSAPP_TEMPLATE = 'whatsapptemplate',\n RAW = 'raw',\n CHAT_EVENT = 'chatevent',\n WHATSAPP_BUTTON_LIST = 'whatsapp-button-list',\n WHATSAPP_CTA_URL_BUTTON = 'whatsapp-cta-url-button',\n WHATSAPP_REQUEST_CONTACT_INFO = 'whatsapp-request-contact-info',\n WHATSAPP_CATALOG = 'whatsapp-catalog',\n WHATSAPP_PRODUCT = 'whatsapp-product',\n WHATSAPP_PRODUCT_LIST = 'whatsapp-product-list',\n WHATSAPP_PRODUCT_CAROUSEL = 'whatsapp-product-carousel',\n WHATSAPP_MEDIA_CAROUSEL = 'whatsapp-media-carousel',\n WHATSAPP_ORDER = 'whatsapp_order',\n EVENT_AGENT_MESSAGE_CREATED = 'case_event_agent_message_created',\n EVENT_QUEUE_POSITION_CHANGED = 'case_event_queue_position_changed',\n EVENT_CASE_STATUS_CHANGED = 'case_event_status_changed',\n SYSTEM_DEBUG_TRACE = 'system_debug_trace',\n}\n\ninterface PluginConstructor<T> {\n new (arg: T): Plugin\n}\n\nexport interface PluginConfig<T> {\n id: string\n options?: T\n resolve: { default: PluginConstructor<T> }\n}\n\nexport type ResolvedPlugins = Record<string, Plugin>\n\nexport type InputType =\n | INPUT.AUDIO\n | INPUT.BUTTON_MESSAGE\n | INPUT.CAROUSEL\n | INPUT.CONTACT\n | INPUT.CUSTOM\n | INPUT.DOCUMENT\n | INPUT.IMAGE\n | INPUT.LOCATION\n | INPUT.POSTBACK\n | INPUT.TEXT\n | INPUT.VIDEO\n | INPUT.CHAT_EVENT\n | INPUT.WEBCHAT_SETTINGS\n | INPUT.WHATSAPP_TEMPLATE\n | INPUT.WHATSAPP_BUTTON_LIST\n | INPUT.WHATSAPP_CTA_URL_BUTTON\n | INPUT.WHATSAPP_REQUEST_CONTACT_INFO\n | INPUT.WHATSAPP_CATALOG\n | INPUT.WHATSAPP_PRODUCT\n | INPUT.WHATSAPP_PRODUCT_LIST\n | INPUT.WHATSAPP_PRODUCT_CAROUSEL\n | INPUT.WHATSAPP_MEDIA_CAROUSEL\n | INPUT.WHATSAPP_ORDER\n | INPUT.EVENT_AGENT_MESSAGE_CREATED\n | INPUT.EVENT_QUEUE_POSITION_CHANGED\n | INPUT.EVENT_CASE_STATUS_CHANGED\n\n/** Generated by Translation plugins: GoogleTranslation **/\nexport interface Translations {\n [languageCode: string]: string\n}\n\nexport enum NluType {\n Keyword = 'keyword',\n SmartIntent = 'smart-intent',\n}\n\nexport interface Input {\n text?: string\n src?: string\n data?: string\n path?: string\n payload?: string\n referral?: string\n type: InputType\n context?: {\n campaign?: Campaign\n campaigns_v2?: CampaignV2[]\n salesforce?: {\n access_token: string\n }\n }\n transcript?: string\n message_id: string\n bot_interaction_id: string\n catalog_id?: string\n product_items?: ProductItem[]\n nluResolution?: {\n type: NluType\n matchedValue: string\n payload?: string\n }\n origin?: string\n}\n\nexport interface CaseEventQueuePositionChangedInput {\n type: INPUT.EVENT_QUEUE_POSITION_CHANGED\n case_id: string\n prev_queue_position: number | null\n prev_queue_position_notified_at: string | null\n current_queue_position: number\n current_queue_position_notified_at: string\n total_queue_waiting_cases_number: number\n}\n\nexport enum CaseStatus {\n Waiting = 'status_waiting',\n Attending = 'status_attending',\n Idle = 'status_idle',\n Resolved = 'status_resolved',\n}\n\nexport interface CaseEventStatusChangedInput {\n type: INPUT.EVENT_CASE_STATUS_CHANGED\n case_id: string\n prev_status: CaseStatus | null\n next_status: CaseStatus\n}\n\nexport interface CaseEventAgentMessageCreatedInput {\n type: INPUT.EVENT_AGENT_MESSAGE_CREATED\n agent_id?: string\n agent_name?: string\n message?: {\n type: string\n data: string\n }\n}\n\ninterface ProductItem {\n product_retailer_id: string\n quantity: number\n item_price: number\n currency: string\n}\n\nexport interface Campaign {\n id: string\n name: string\n status: string\n start_date: string\n end_date: string\n bot_path: string\n template_name: string\n}\n\nexport interface CampaignV2 {\n id: string\n name: string\n agent_context?: string\n end_date?: string\n}\n\nexport interface ContactInfo {\n name: string\n type: string\n value: string\n description?: string\n}\n\nexport interface SessionUser<TExtraData = any> {\n id: string\n // login\n username?: string\n // person name\n name?: string\n // whatsapp, telegram,...\n provider: ProviderType\n // The provider's user id\n extra_data?: TExtraData\n contact_info?: ContactInfo[]\n imp_id?: string\n provider_id?: string\n locale: string\n country: string\n system_locale: string\n system_locale_updated?: boolean\n}\n\nexport interface HubtypeCaseContactReason {\n id: string\n name: string\n project_id: string\n}\n\nexport interface SessionBot {\n id: string\n name?: string\n}\n\nexport interface Session<TExtraData = any> {\n bot: SessionBot\n __retries: number\n _access_token: string\n _hubtype_api: string\n is_first_interaction: boolean\n is_test_integration: boolean\n last_session?: any\n organization_id: string\n organization: string\n user: SessionUser<TExtraData>\n // after handoff\n _botonic_action?: BotonicActionType\n _hubtype_case_resolution?: CaseResolution\n _hubtype_case_id?: string\n _hubtype_case_typification?: string\n _hubtype_case_contact_reasons?: HubtypeCaseContactReason[]\n _shadowing?: boolean\n external?: any\n zendesk_ticket_id?: string\n flow_thread_id?: string\n __campaign?: {\n id: string\n path: string\n active: boolean\n }\n capture_user_input?: {\n node_id: string\n }\n}\n\nexport type InputMatcher = (input: Input) => boolean\nexport type ParamsMatcher =\n | { [key: string]: string }\n | ((params: { [key: string]: string }) => boolean)\nexport type SessionMatcher<TExtraData = any> = (\n session: Session<TExtraData>\n) => boolean\nexport type RequestMatcher<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> = (request: BotContext<TPlugins, TExtraData>) => boolean\nexport type StringMatcher = RegExp | string | ((data: string) => boolean)\n\nexport type RouteMatcher =\n | InputMatcher\n | ParamsMatcher\n | RequestMatcher\n | SessionMatcher\n | StringMatcher\n\nexport interface Route<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> {\n action?: any\n childRoutes?: Route[]\n lastRoutePath?: string\n ignoreRetry?: boolean\n path: RoutePath\n redirect?: string\n retry?: number\n\n // matchers\n input?: InputMatcher\n params?: ParamsMatcher\n payload?: StringMatcher\n request?: RequestMatcher<TPlugins, TExtraData>\n session?: SessionMatcher<TExtraData>\n text?: StringMatcher\n data?: StringMatcher\n type?: StringMatcher\n}\n\nexport type Routes<R = Route> = R[] | ((request: BotContext) => R[])\n\nexport interface BotRequest<TExtraData = any> {\n input: Input\n lastRoutePath: RoutePath\n session: Session<TExtraData>\n settings: BotSettings\n secrets: BotSecrets\n}\n\nexport interface BotSettings {\n HUBTYPE_API_URL: string\n STATIC_URL: string\n LITELLM_API_URL: string\n AZURE_OPENAI_API_BASE: string\n AZURE_OPENAI_API_VERSION: string\n LANGUAGE_DETECTION_ENABLED?: boolean\n CUSTOM_SHORT_URL_HOST: string | null\n custom: Record<string, any>\n}\n\nexport interface BotSecrets {\n HUBTYPE_ACCESS_TOKEN: string\n LITELLM_API_KEY: string\n AZURE_OPENAI_API_KEY: string\n custom: Record<string, any>\n}\n\nexport interface BotContext<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> extends BotRequest<TExtraData> {\n getUserCountry: () => string\n getUserLocale: () => string\n getSystemLocale: () => string\n setUserCountry: (country: string) => void\n setUserLocale: (locale: string) => void\n setSystemLocale: (locale: string) => void\n defaultDelay: number\n defaultTyping: number\n params: Record<string, string>\n plugins: TPlugins\n}\n\n/** The response of the bot for the triggered actions, which can be\n * the one matched by the routes, the default action and the retry actions.\n * See Response at @botonic/react's index.d.ts for the React type\n * */\nexport interface BotResponse extends BotRequest {\n response: any\n}\n\nexport type PluginPreRequest<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> = BotContext<TPlugins, TExtraData>\n\nexport type PluginPostRequest<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n TExtraData = any,\n> = BotContext<TPlugins, TExtraData> & {\n response: string | null\n}\n\nexport interface Plugin {\n post?(request: PluginPostRequest): void | Promise<void>\n pre?(request: PluginPreRequest): void | Promise<void>\n}\n\nexport interface Params {\n [key: string]: any\n}\n\nexport type Nullable<T> = T | null\n\nexport type Action = Nullable<() => any>\nexport type RoutePath = Nullable<string>\n\nexport interface ProcessInputResult {\n action: Action\n emptyAction: Action\n fallbackAction: Action\n lastRoutePath: RoutePath\n params: Params\n}\n\nexport type MatchedValue = boolean | RegExpExecArray | null\n\nexport type RoutingState = {\n currentRoute: Nullable<Route>\n matchedRoute: Nullable<Route>\n params: Params\n isFlowBroken: boolean\n}\n\nexport interface RouteParams {\n route: Nullable<Route>\n params: Params\n}\nexport interface PathParams {\n path: RoutePath\n params: Params\n}\n\nexport type MatchingProp =\n | 'text'\n | 'payload'\n | 'type'\n | 'input'\n | 'session'\n | 'request'\n\nexport type Matcher = string | RegExp | ((args) => boolean)\n\nexport type BotonicActionType =\n | `${BotonicAction.CreateCase}${BotonicActionSeparator}${string}`\n | `${BotonicAction.Redirect}${BotonicActionSeparator}${string}`\n | `${BotonicAction.DiscardCase}${BotonicActionSeparator}${string}`\n | `${BotonicAction.DiscardCase}`\n | `${BotonicAction.DeleteUser}`\n\ntype BotonicActionSeparator = ':'\n\nexport enum BotonicAction {\n Redirect = 'redirect_action',\n CreateCase = 'create_case',\n DeleteUser = 'delete_user',\n DiscardCase = 'discard_case',\n}\n"],"names":["CASE_STATUS","CASE_RESOLUTION","PROVIDER","INPUT","NluType","CaseStatus","BotonicAction"],"mappings":"AAAA,wIAAwI;AAEjI,IAAKA,wBAAWA,0BAAXA;;;;;WAAAA;MAKX;AAQM,IAAKC,4BAAeA,0BAAfA;;;;;WAAAA;MAKX;AAQM,IAAKC,qBAAQA,0BAARA;;;;;;;;;;;;;WAAAA;MAaX;AAeM,IAAKC,kBAAKA,0BAALA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAAAA;MA6BX;AA+CM,IAAKC,oBAAOA,0BAAPA;;;WAAAA;MAGX;AAwCM,IAAKC,uBAAUA,0BAAVA;;;;;WAAAA;MAKX;AAqRM,IAAKC,0BAAaA,0BAAbA;;;;;WAAAA;MAKX"}
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugins.js","sources":["../../src/plugins.ts"],"sourcesContent":["import type { BotContext, Plugin } from './models'\n\ninterface RunPluginArgs {\n botContext: BotContext\n mode: PluginMode\n response?: string | null\n}\n\ntype PluginMode = 'pre' | 'post'\n\nexport async function runPlugins({\n botContext,\n mode,\n response = null,\n}: RunPluginArgs): Promise<void> {\n const plugins = botContext.plugins\n for (const key in plugins) {\n const plugin: Plugin = plugins[key]\n try {\n if (mode === 'pre' && typeof plugin.pre === 'function') {\n await plugin.pre(botContext)\n }\n if (mode === 'post' && typeof plugin.post === 'function') {\n await plugin.post({\n ...botContext,\n response,\n })\n }\n } catch (e) {\n console.log(e)\n }\n }\n}\n"],"names":["runPlugins","botContext","mode","response","plugins","key","plugin","e","console"],"mappings":"AAUO,eAAeA,UAAUA,CAAC,EAC/BC,UAAU,EACVC,IAAI,EACJC,WAAW,IAAI,EACD;IACd,MAAMC,UAAUH,WAAW,OAAO;IAClC,IAAK,MAAMI,OAAOD,QAAS;QACzB,MAAME,SAAiBF,OAAO,CAACC,IAAI;QACnC,IAAI;YACF,IAAIH,SAAS,SAAS,OAAOI,OAAO,GAAG,KAAK,YAAY;gBACtD,MAAMA,OAAO,GAAG,CAACL;YACnB;YACA,IAAIC,SAAS,UAAU,OAAOI,OAAO,IAAI,KAAK,YAAY;gBACxD,MAAMA,OAAO,IAAI,CAAC;oBAChB,GAAGL,UAAU;oBACbE;gBACF;YACF;QACF,EAAE,OAAOI,GAAG;YACVC,QAAQ,GAAG,CAACD;QACd;IACF;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pusher-utils.js","sources":["../../src/pusher-utils.ts"],"sourcesContent":["import { inflate } from 'pako'\n\n/**\n *\n * @param compressedData a string representing gzipped data previously encoded to base64 for very large contents\n * @returns a string representing the information of a very large content\n * Ref: https://stackoverflow.com/questions/4875020/javascript-decompress-inflate-unzip-ungzip-strings (check jsfiddle proposal)\n */\nexport function decompressData(compressedData: string): string {\n const strData = atob(compressedData) // Decode base64 (convert ascii to binary)\n const charData = strData.split('').map(x => x.charCodeAt(0)) // Convert binary string to character-number array\n const binData = new Uint8Array(charData) // Turn number array into byte-array\n const data = inflate(binData)\n return new TextDecoder('utf-8').decode(data)\n}\n"],"names":["inflate","decompressData","compressedData","strData","atob","charData","x","binData","Uint8Array","data","TextDecoder"],"mappings":";;;AAA8B;AAE9B;;;;;CAKC,GACM,SAASC,cAAcA,CAACC,cAAsB;IACnD,MAAMC,UAAUC,KAAKF,gBAAgB,0CAA0C;;IAC/E,MAAMG,WAAWF,QAAQ,KAAK,CAAC,IAAI,GAAG,CAACG,CAAAA,IAAKA,EAAE,UAAU,CAAC,IAAI,kDAAkD;;IAC/G,MAAMC,UAAU,IAAIC,WAAWH,UAAU,oCAAoC;;IAC7E,MAAMI,OAAOT,OAAOA,CAACO;IACrB,OAAO,IAAIG,YAAY,SAAS,MAAM,CAACD;AACzC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing/index.js","sources":["../../../src/routing/index.ts"],"sourcesContent":["export * from './router'\nexport * from './router-utils'\n"],"names":[],"mappings":";;AAAwB;AACM"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing/router-utils.js","sources":["../../../src/routing/router-utils.ts"],"sourcesContent":["import {\n EMPTY_ACTION_PATH,\n NOT_FOUND_PATH,\n PATH_PAYLOAD_IDENTIFIER,\n PATH_PAYLOAD_REGEXP,\n} from '../constants'\nimport type {\n Action,\n BotContext,\n Input,\n Params,\n PathParams,\n Route,\n Routes,\n} from '../models'\n\nexport class NoMatchingRouteError extends Error {\n input: Input\n constructor(input: Input) {\n super(\n `No route found for input '${JSON.stringify(\n input\n )}' and no ${NOT_FOUND_PATH} route defined`\n )\n this.input = input\n }\n}\n\nexport function isPathPayload(payload?: string): boolean {\n if (!payload) {\n return false\n }\n const isPathPayload = PATH_PAYLOAD_REGEXP.exec(payload)\n return Boolean(isPathPayload)\n}\n\nexport function getPathParamsFromPathPayload(payload?: string): PathParams {\n const defaultPathParams = {\n path: null,\n params: {},\n }\n if (!payload) {\n return defaultPathParams\n }\n if (!isPathPayload(payload)) {\n return defaultPathParams\n }\n try {\n const pathWithParams = payload.split(PATH_PAYLOAD_IDENTIFIER)[1]\n if (!pathWithParams) {\n throw `${PATH_PAYLOAD_IDENTIFIER} is empty`\n }\n const [path, params] = pathWithParams.split('?')\n return { path: path ?? null, params: pathParamsToParams(params) }\n } catch (e) {\n console.error('Error getting path and params from input.payload:', e)\n return defaultPathParams\n }\n}\n\nexport function pathParamsToParams(pathParams?: string): Params {\n if (!pathParams) {\n return {}\n }\n try {\n const params = {}\n const searchParams = new URLSearchParams(pathParams)\n for (const [key, value] of searchParams) {\n params[key] = value\n }\n return params\n } catch (_e) {\n return {}\n }\n}\n\nexport function getEmptyAction(childRoutes?: Route[]): Action {\n if (!childRoutes) {\n return null\n }\n const emptyActionRoute = childRoutes.find(r => r.path === EMPTY_ACTION_PATH)\n if (!emptyActionRoute) {\n return null\n }\n return emptyActionRoute.action\n}\n\nexport function getNotFoundAction(input: Input, routes: Route[]): Action {\n const notFoundActionRoute = routes.find(r => r.path === NOT_FOUND_PATH)\n if (!notFoundActionRoute) {\n throw new NoMatchingRouteError(input)\n }\n return notFoundActionRoute.action\n}\n\nexport async function getComputedRoutes(\n routes: Routes,\n botContext: BotContext\n): Promise<Route[]> {\n if (routes instanceof Function) {\n return await getComputedRoutes(await routes(botContext), botContext)\n }\n for (const [key, route] of Object.entries(routes) as any) {\n if (route.childRoutes && route.childRoutes instanceof Function) {\n routes[key].childRoutes = await getComputedRoutes(\n await route.childRoutes(botContext),\n botContext\n )\n } else {\n routes[key] = route\n }\n }\n return routes\n}\n"],"names":["EMPTY_ACTION_PATH","NOT_FOUND_PATH","PATH_PAYLOAD_IDENTIFIER","PATH_PAYLOAD_REGEXP","NoMatchingRouteError","Error","input","JSON","isPathPayload","payload","Boolean","getPathParamsFromPathPayload","defaultPathParams","pathWithParams","path","params","pathParamsToParams","e","console","pathParams","searchParams","URLSearchParams","key","value","_e","getEmptyAction","childRoutes","emptyActionRoute","r","getNotFoundAction","routes","notFoundActionRoute","getComputedRoutes","botContext","Function","route","Object"],"mappings":";;;;;;;;;;;;;;AAKqB;AAWd,MAAMI,oBAAoBA,SAASC;IAExC,YAAYC,KAAY,CAAE;QACxB,KAAK,CACH,CAAC,0BAA0B,EAAEC,KAAK,SAAS,CACzCD,OACA,SAAS,EAAEL,cAAcA,CAAC,cAAc,CAAC,GAL/C;QAOE,IAAI,CAAC,KAAK,GAAGK;IACf;AACF;AAEO,SAASE,0BAAaA,CAACC,OAAgB;IAC5C,IAAI,CAACA,SAAS;QACZ,OAAO;IACT;IACA,MAAMD,gBAAgBL,wBAAwB,CAACM;IAC/C,OAAOC,QAAQF;AACjB;AAEO,SAASG,4BAA4BA,CAACF,OAAgB;IAC3D,MAAMG,oBAAoB;QACxB,MAAM;QACN,QAAQ,CAAC;IACX;IACA,IAAI,CAACH,SAAS;QACZ,OAAOG;IACT;IACA,IAAI,CAACJ,0BAAaA,CAACC,UAAU;QAC3B,OAAOG;IACT;IACA,IAAI;QACF,MAAMC,iBAAiBJ,QAAQ,KAAK,CAACP,uBAAuBA,CAAC,CAAC,EAAE;QAChE,IAAI,CAACW,gBAAgB;YACnB,MAAM,GAAGX,uBAAuBA,CAAC,SAAS,CAAC;QAC7C;QACA,MAAM,CAACY,MAAMC,OAAO,GAAGF,eAAe,KAAK,CAAC;QAC5C,OAAO;YAAE,MAAMC,QAAQ;YAAM,QAAQE,kBAAkBA,CAACD;QAAQ;IAClE,EAAE,OAAOE,GAAG;QACVC,QAAQ,KAAK,CAAC,qDAAqDD;QACnE,OAAOL;IACT;AACF;AAEO,SAASI,kBAAkBA,CAACG,UAAmB;IACpD,IAAI,CAACA,YAAY;QACf,OAAO,CAAC;IACV;IACA,IAAI;QACF,MAAMJ,SAAS,CAAC;QAChB,MAAMK,eAAe,IAAIC,gBAAgBF;QACzC,KAAK,MAAM,CAACG,KAAKC,MAAM,IAAIH,aAAc;YACvCL,MAAM,CAACO,IAAI,GAAGC;QAChB;QACA,OAAOR;IACT,EAAE,OAAOS,IAAI;QACX,OAAO,CAAC;IACV;AACF;AAEO,SAASC,cAAcA,CAACC,WAAqB;IAClD,IAAI,CAACA,aAAa;QAChB,OAAO;IACT;IACA,MAAMC,mBAAmBD,YAAY,IAAI,CAACE,CAAAA,IAAKA,EAAE,IAAI,KAAK5B,iBAAiBA;IAC3E,IAAI,CAAC2B,kBAAkB;QACrB,OAAO;IACT;IACA,OAAOA,iBAAiB,MAAM;AAChC;AAEO,SAASE,iBAAiBA,CAACvB,KAAY,EAAEwB,MAAe;IAC7D,MAAMC,sBAAsBD,OAAO,IAAI,CAACF,CAAAA,IAAKA,EAAE,IAAI,KAAK3B,cAAcA;IACtE,IAAI,CAAC8B,qBAAqB;QACxB,MAAM,IAAI3B,oBAAoBA,CAACE;IACjC;IACA,OAAOyB,oBAAoB,MAAM;AACnC;AAEO,eAAeC,iBAAiBA,CACrCF,MAAc,EACdG,UAAsB;IAEtB,IAAIH,kBAAkBI,UAAU;QAC9B,OAAO,MAAMF,iBAAiBA,CAAC,MAAMF,OAAOG,aAAaA;IAC3D;IACA,KAAK,MAAM,CAACX,KAAKa,MAAM,IAAIC,OAAO,OAAO,CAACN,QAAgB;QACxD,IAAIK,MAAM,WAAW,IAAIA,MAAM,WAAW,YAAYD,UAAU;YAC9DJ,MAAM,CAACR,IAAI,CAAC,WAAW,GAAG,MAAMU,iBAAiBA,CAC/C,MAAMG,MAAM,WAAW,CAACF,aACxBA;QAEJ,OAAO;YACLH,MAAM,CAACR,IAAI,GAAGa;QAChB;IACF;IACA,OAAOL;AACT"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing/router.js","sources":["../../../src/routing/router.ts"],"sourcesContent":["import { NOT_FOUND_PATH } from '../constants'\nimport { RouteInspector } from '../debug/inspector'\nimport type {\n Input,\n MatchedValue,\n Matcher,\n MatchingProp,\n Nullable,\n ProcessInputResult,\n Route,\n RouteParams,\n RoutePath,\n RoutingState,\n Session,\n} from '../models'\nimport { cloneObject } from '../utils'\nimport {\n getEmptyAction,\n getNotFoundAction,\n getPathParamsFromPathPayload,\n isPathPayload,\n} from './router-utils'\n\nexport class Router {\n routes: Route[]\n routeInspector: RouteInspector\n\n constructor(\n routes: Route[],\n routeInspector: RouteInspector | undefined = undefined\n ) {\n this.routes = routes\n this.routeInspector = routeInspector || new RouteInspector()\n }\n\n /**\n * Processes an input and return a representation of the new bot state.\n * The algorithm is splitted in two main parts:\n * 1. Getting the current routing state.\n * 2. Given a routing state, resolve the different possible scenarios and return the new bot state.\n * The new bot state can return three type of actions:\n * - action: an action directly resolved from a matching route\n * - emptyAction: optional action that can exists or not only within childRoutes\n * - fallbackAction: any other action that acts as a fallback (404, )\n */\n\n // eslint-disable-next-line complexity\n processInput(\n input: Input,\n session: Session,\n lastRoutePath: RoutePath = null\n ): ProcessInputResult {\n session.__retries = session?.__retries ?? 0\n\n // 1. Getting the current routing state.\n const { currentRoute, matchedRoute, params, isFlowBroken } =\n this.getRoutingState(input, session, lastRoutePath)\n\n const currentRoutePath = currentRoute?.path ?? null\n const matchedRoutePath = matchedRoute?.path ?? null\n\n // 2. Given a routing state, resolve the different possible scenarios and return the new bot state.\n\n /**\n * Redirect Scenario:\n * We have matched a redirect route with a given redirection path, so we try to obtain the redirectionRoute with getRouteByPath.\n * Independently of whether the redirectionRoute is found or not, the intent is to trigger a redirection which by definition breaks the flow, so retries are set to 0.\n * It has preference over ignoring retries.\n */\n if (matchedRoute?.redirect) {\n session.__retries = 0\n const redirectionRoute = this.getRouteByPath(matchedRoute.redirect)\n if (redirectionRoute) {\n return {\n action: redirectionRoute.action,\n emptyAction: getEmptyAction(redirectionRoute.childRoutes),\n fallbackAction: null,\n lastRoutePath: matchedRoute.redirect,\n params,\n }\n }\n return {\n action: null,\n emptyAction: null,\n fallbackAction: getNotFoundAction(input, this.routes),\n lastRoutePath: null,\n params,\n }\n }\n\n /**\n * Ignore Retry Scenario:\n * We have matched a route with an ignore retry, so we return directly the new bot state. The intent is to break the flow, so retries are set to 0.\n */\n if (matchedRoute?.ignoreRetry) {\n session.__retries = 0\n return {\n action: matchedRoute.action,\n emptyAction: getEmptyAction(matchedRoute.childRoutes),\n fallbackAction: null,\n lastRoutePath: matchedRoutePath,\n params,\n }\n }\n\n /**\n * Retry Scenario:\n * We were in a route which had retries enabled, so we check if the number of retries is exceeded.\n * If we have not surpassed the limit of retries and we haven't matched an ignoreRetry route, update them, and then return the new bot state.\n */\n if (\n isFlowBroken &&\n currentRoute &&\n currentRoute.retry &&\n session.__retries < currentRoute.retry\n ) {\n session.__retries = session.__retries !== 0 ? session.__retries + 1 : 1\n if (matchedRoute && matchedRoutePath !== NOT_FOUND_PATH) {\n return {\n action: currentRoute.action,\n emptyAction: getEmptyAction(matchedRoute.childRoutes),\n fallbackAction: matchedRoute.action,\n lastRoutePath: currentRoutePath,\n params,\n }\n }\n return {\n action: currentRoute.action ?? null,\n emptyAction: getEmptyAction(currentRoute.childRoutes),\n fallbackAction: getNotFoundAction(input, this.routes),\n lastRoutePath: currentRoutePath,\n params,\n }\n }\n\n /**\n * Default Scenario:\n * We have matched a route or not, but we don't need to execute retries logic, so retries stay to 0.\n */\n session.__retries = 0\n\n /**\n * Matching Route Scenario:\n * We have matched a route, so we return the new bot state.\n */\n if (matchedRoute && matchedRoutePath !== NOT_FOUND_PATH) {\n return {\n action: matchedRoute.action ?? null,\n emptyAction: getEmptyAction(matchedRoute.childRoutes),\n fallbackAction: null,\n lastRoutePath: matchedRoutePath,\n params,\n }\n }\n\n /**\n * 404 Scenario (No Route Found):\n * We have not matched any route, so we return the new bot state.\n */\n return {\n action: null,\n emptyAction: null,\n fallbackAction: getNotFoundAction(input, this.routes),\n params,\n lastRoutePath: currentRoutePath,\n }\n }\n\n /**\n * Find the route that matches the given input, if it match with some of the entries, return the whole Route of the entry with optional params captured if matcher was a regex.\n * IMPORTANT: It returns a cloned route instead of the route itself to avoid modifying original routes and introduce side effects\n * */\n getRoute(\n input: Input | Partial<Input>,\n routes: Route[],\n session: Session,\n lastRoutePath: RoutePath\n ): RouteParams | null {\n let params = {}\n const route = routes.find(r =>\n Object.entries(r)\n .filter(\n ([key, _]) =>\n key !== 'action' && key !== 'childRoutes' && key !== 'path'\n )\n .some(([key, value]) => {\n const match = this.matchRoute(\n r,\n key as MatchingProp,\n value as Matcher,\n input as Input,\n session,\n lastRoutePath\n )\n try {\n if (match !== null && typeof match !== 'boolean' && match.groups) {\n // Strip '[Object: null prototype]' from groups result: https://stackoverflow.com/a/62945609/6237608\n params = { ...match.groups }\n }\n } catch (_e) {}\n return Boolean(match)\n })\n )\n if (route) {\n return { route: cloneObject(route), params }\n }\n return null\n }\n\n /**\n * Find the route that matches the given path. Path can include concatenations, e.g: 'Flow1/Subflow1.1'.\n * IMPORTANT: It returns a cloned route instead of the route itself to avoid modifying original routes and introduce side effects\n * */\n getRouteByPath(\n path: RoutePath,\n routeList: Route[] = this.routes\n ): Nullable<Route> {\n if (!path) {\n return null\n }\n const [currentPath, ...childPath] = path.split('/')\n for (const route of routeList) {\n // iterate over all routeList\n if (route.path === currentPath) {\n if (route.childRoutes?.length && childPath.length > 0) {\n // evaluate childroute over next actions\n const computedRoute = this.getRouteByPath(\n childPath.join('/'),\n route.childRoutes\n )\n // IMPORTANT: Returning a new object to avoid modifying dev routes and introduce side effects\n if (computedRoute) {\n return cloneObject(computedRoute)\n }\n } else if (childPath.length === 0) {\n return cloneObject(route) // last action and found route\n }\n }\n }\n return null\n }\n\n /**\n * Returns the matched value for a specific route.\n * Matching Props: ('text' | 'payload' | 'intent' | 'type' | 'input' | 'session' | 'request' ...)\n * Matchers: (string: exact match | regex: regular expression match | function: return true)\n * input: user input object, e.g.: {type: 'text', data: 'Hi'}\n * */\n matchRoute(\n route: Route,\n prop: MatchingProp,\n matcher: Matcher,\n input: Input,\n session: Session,\n lastRoutePath: RoutePath\n ): MatchedValue {\n let value: any = null\n if (Object.keys(input).indexOf(prop) > -1) {\n value = input[prop]\n } else if (prop === 'text') {\n value = input.data\n } else if (prop === 'input') {\n value = input\n } else if (prop === 'session') {\n value = session\n } else if (prop === 'request') {\n value = { input, session, lastRoutePath }\n }\n const matched = this.matchValue(matcher, value)\n if (matched) {\n this.routeInspector.routeMatched(route, prop, matcher, value)\n } else {\n this.routeInspector.routeNotMatched(route, prop, matcher, value)\n }\n return matched\n }\n\n /**\n * Runs the matcher against the given value.\n * If there is a match, it will return a truthy value (true, RegExp result), o.w., it will return a falsy value.\n * */\n matchValue(matcher: Matcher, value: any): MatchedValue {\n if (typeof matcher === 'string') {\n return value === matcher\n }\n if (matcher instanceof RegExp) {\n if (value === undefined || value === null) {\n return false\n }\n return matcher.exec(value)\n }\n if (typeof matcher === 'function') {\n return matcher(value)\n }\n return false\n }\n\n /**\n * It resolves the current state of navigation. Two scenarios:\n * 1. Given a path payload input (__PATH_PAYLOAD__somePath?someParam=someValue), we can resolve the routing state directly from it (using getRouteByPath).\n * 2. Given any other type of input, we resolve the routing state with normal resolution (using getRoute).\n * */\n getRoutingState(\n input: Input,\n session: Session,\n lastRoutePath: RoutePath\n ): RoutingState {\n const currentRoute = this.getRouteByPath(lastRoutePath)\n if (currentRoute && lastRoutePath) {\n currentRoute.path = lastRoutePath\n }\n if (typeof input.payload === 'string' && isPathPayload(input.payload)) {\n return this.getRoutingStateFromPathPayload(currentRoute, input.payload)\n }\n return this.getRoutingStateFromInput(currentRoute, input, session)\n }\n\n /**\n * Given a non path payload input, try to run it against the routes, update matching routes information in consequence and dictamine if the flow has been broken.\n * */\n getRoutingStateFromInput(\n currentRoute: Nullable<Route>,\n input: Input,\n session: Session\n ): RoutingState {\n // get route depending of current ChildRoutes\n if (currentRoute?.childRoutes) {\n const routeParams = this.getRoute(\n input,\n currentRoute.childRoutes,\n session,\n currentRoute.path\n )\n if (routeParams) {\n return {\n currentRoute,\n matchedRoute: {\n ...routeParams.route,\n path:\n routeParams.route && currentRoute.path\n ? `${currentRoute.path}/${routeParams.route.path}`\n : currentRoute.path,\n },\n params: routeParams.params,\n isFlowBroken: false,\n }\n }\n }\n /**\n * we couldn't find a route in the state of the currentRoute childRoutes,\n * so let's find in the general routes\n */\n const routeParams = this.getRoute(\n input,\n this.routes,\n session,\n currentRoute?.path ?? null\n )\n const isFlowBroken = Boolean(currentRoute?.path)\n if (routeParams?.route) {\n return {\n currentRoute,\n matchedRoute: {\n ...routeParams.route,\n path: routeParams.route?.path ?? null,\n },\n params: routeParams.params,\n isFlowBroken,\n }\n }\n return {\n currentRoute,\n matchedRoute: null,\n params: {},\n isFlowBroken,\n }\n }\n\n /**\n * Given a path payload input, try to run the path against the routes, update matching routes information in consequence and dictamine if the flow has been broken.\n * */\n getRoutingStateFromPathPayload(\n currentRoute: Nullable<Route>,\n pathPayload: string\n ): RoutingState {\n const { path, params } = getPathParamsFromPathPayload(pathPayload)\n /**\n * shorthand function to update the matching information given a path\n */\n const getRoutingStateFromPath = (seekPath: string): RoutingState => {\n const matchedRoute = this.getRouteByPath(seekPath)\n if (!matchedRoute) {\n return {\n currentRoute,\n matchedRoute: null,\n params: {},\n isFlowBroken: true,\n }\n }\n return {\n currentRoute,\n matchedRoute: { ...matchedRoute, path: seekPath },\n params,\n isFlowBroken: false,\n }\n }\n /**\n * Given a valid path: 'Flow1/Subflow1' we are in one of the two scenarios below.\n */\n // 1. Received __PATH_PAYLOAD__Subflow2, so we need to first try to concatenate it with Flow1 (lastRoutePath)\n if (currentRoute?.path) {\n const routingState = getRoutingStateFromPath(\n `${currentRoute.path}/${path}`\n )\n if (routingState.matchedRoute) {\n return routingState\n }\n }\n // 2. Received __PATH_PAYLOAD__Flow1/Subflow1, so we can resolve it directly\n return getRoutingStateFromPath(path as string)\n }\n}\n"],"names":["NOT_FOUND_PATH","RouteInspector","cloneObject","getEmptyAction","getNotFoundAction","getPathParamsFromPathPayload","isPathPayload","Router","input","session","lastRoutePath","currentRoute","matchedRoute","params","isFlowBroken","currentRoutePath","matchedRoutePath","redirectionRoute","routes","route","r","Object","key","_","value","match","_e","Boolean","path","routeList","currentPath","childPath","computedRoute","prop","matcher","matched","RegExp","undefined","routeParams","pathPayload","getRoutingStateFromPath","seekPath","routingState","routeInspector"],"mappings":";;;;;;;;;;;;;;;;;;;;AAA6C;AACM;AAcb;AAMf;AAEhB,MAAMO,MAAMA;IAYjB;;;;;;;;;GASC,GAED,sCAAsC;IACtC,aACEC,KAAY,EACZC,OAAgB,EAChBC,gBAA2B,IAAI,EACX;QACpBD,QAAQ,SAAS,GAAGA,SAAS,aAAa;QAE1C,wCAAwC;QACxC,MAAM,EAAEE,YAAY,EAAEC,YAAY,EAAEC,MAAM,EAAEC,YAAY,EAAE,GACxD,IAAI,CAAC,eAAe,CAACN,OAAOC,SAASC;QAEvC,MAAMK,mBAAmBJ,cAAc,QAAQ;QAC/C,MAAMK,mBAAmBJ,cAAc,QAAQ;QAE/C,mGAAmG;QAEnG;;;;;KAKC,GACD,IAAIA,cAAc,UAAU;YAC1BH,QAAQ,SAAS,GAAG;YACpB,MAAMQ,mBAAmB,IAAI,CAAC,cAAc,CAACL,aAAa,QAAQ;YAClE,IAAIK,kBAAkB;gBACpB,OAAO;oBACL,QAAQA,iBAAiB,MAAM;oBAC/B,aAAad,cAAcA,CAACc,iBAAiB,WAAW;oBACxD,gBAAgB;oBAChB,eAAeL,aAAa,QAAQ;oBACpCC;gBACF;YACF;YACA,OAAO;gBACL,QAAQ;gBACR,aAAa;gBACb,gBAAgBT,iBAAiBA,CAACI,OAAO,IAAI,CAAC,MAAM;gBACpD,eAAe;gBACfK;YACF;QACF;QAEA;;;KAGC,GACD,IAAID,cAAc,aAAa;YAC7BH,QAAQ,SAAS,GAAG;YACpB,OAAO;gBACL,QAAQG,aAAa,MAAM;gBAC3B,aAAaT,cAAcA,CAACS,aAAa,WAAW;gBACpD,gBAAgB;gBAChB,eAAeI;gBACfH;YACF;QACF;QAEA;;;;KAIC,GACD,IACEC,gBACAH,gBACAA,aAAa,KAAK,IAClBF,QAAQ,SAAS,GAAGE,aAAa,KAAK,EACtC;YACAF,QAAQ,SAAS,GAAGA,QAAQ,SAAS,KAAK,IAAIA,QAAQ,SAAS,GAAG,IAAI;YACtE,IAAIG,gBAAgBI,qBAAqBhB,cAAcA,EAAE;gBACvD,OAAO;oBACL,QAAQW,aAAa,MAAM;oBAC3B,aAAaR,cAAcA,CAACS,aAAa,WAAW;oBACpD,gBAAgBA,aAAa,MAAM;oBACnC,eAAeG;oBACfF;gBACF;YACF;YACA,OAAO;gBACL,QAAQF,aAAa,MAAM,IAAI;gBAC/B,aAAaR,cAAcA,CAACQ,aAAa,WAAW;gBACpD,gBAAgBP,iBAAiBA,CAACI,OAAO,IAAI,CAAC,MAAM;gBACpD,eAAeO;gBACfF;YACF;QACF;QAEA;;;KAGC,GACDJ,QAAQ,SAAS,GAAG;QAEpB;;;KAGC,GACD,IAAIG,gBAAgBI,qBAAqBhB,cAAcA,EAAE;YACvD,OAAO;gBACL,QAAQY,aAAa,MAAM,IAAI;gBAC/B,aAAaT,cAAcA,CAACS,aAAa,WAAW;gBACpD,gBAAgB;gBAChB,eAAeI;gBACfH;YACF;QACF;QAEA;;;KAGC,GACD,OAAO;YACL,QAAQ;YACR,aAAa;YACb,gBAAgBT,iBAAiBA,CAACI,OAAO,IAAI,CAAC,MAAM;YACpDK;YACA,eAAeE;QACjB;IACF;IAEA;;;KAGG,GACH,SACEP,KAA6B,EAC7BU,MAAe,EACfT,OAAgB,EAChBC,aAAwB,EACJ;QACpB,IAAIG,SAAS,CAAC;QACd,MAAMM,QAAQD,OAAO,IAAI,CAACE,CAAAA,IACxBC,OAAO,OAAO,CAACD,GACZ,MAAM,CACL,CAAC,CAACE,KAAKC,EAAE,GACPD,QAAQ,YAAYA,QAAQ,iBAAiBA,QAAQ,QAExD,IAAI,CAAC,CAAC,CAACA,KAAKE,MAAM;gBACjB,MAAMC,QAAQ,IAAI,CAAC,UAAU,CAC3BL,GACAE,KACAE,OACAhB,OACAC,SACAC;gBAEF,IAAI;oBACF,IAAIe,UAAU,QAAQ,OAAOA,UAAU,aAAaA,MAAM,MAAM,EAAE;wBAChE,oGAAoG;wBACpGZ,SAAS;4BAAE,GAAGY,MAAM,MAAM;wBAAC;oBAC7B;gBACF,EAAE,OAAOC,IAAI,CAAC;gBACd,OAAOC,QAAQF;YACjB;QAEJ,IAAIN,OAAO;YACT,OAAO;gBAAE,OAAOjB,WAAWA,CAACiB;gBAAQN;YAAO;QAC7C;QACA,OAAO;IACT;IAEA;;;KAGG,GACH,eACEe,IAAe,EACfC,YAAqB,IAAI,CAAC,MAAM,EACf;QACjB,IAAI,CAACD,MAAM;YACT,OAAO;QACT;QACA,MAAM,CAACE,aAAa,GAAGC,UAAU,GAAGH,KAAK,KAAK,CAAC;QAC/C,KAAK,MAAMT,SAASU,UAAW;YAC7B,6BAA6B;YAC7B,IAAIV,MAAM,IAAI,KAAKW,aAAa;gBAC9B,IAAIX,MAAM,WAAW,EAAE,UAAUY,UAAU,MAAM,GAAG,GAAG;oBACrD,wCAAwC;oBACxC,MAAMC,gBAAgB,IAAI,CAAC,cAAc,CACvCD,UAAU,IAAI,CAAC,MACfZ,MAAM,WAAW;oBAEnB,6FAA6F;oBAC7F,IAAIa,eAAe;wBACjB,OAAO9B,WAAWA,CAAC8B;oBACrB;gBACF,OAAO,IAAID,UAAU,MAAM,KAAK,GAAG;oBACjC,OAAO7B,WAAWA,CAACiB,OAAO,8BAA8B;;gBAC1D;YACF;QACF;QACA,OAAO;IACT;IAEA;;;;;KAKG,GACH,WACEA,KAAY,EACZc,IAAkB,EAClBC,OAAgB,EAChB1B,KAAY,EACZC,OAAgB,EAChBC,aAAwB,EACV;QACd,IAAIc,QAAa;QACjB,IAAIH,OAAO,IAAI,CAACb,OAAO,OAAO,CAACyB,QAAQ,CAAC,GAAG;YACzCT,QAAQhB,KAAK,CAACyB,KAAK;QACrB,OAAO,IAAIA,SAAS,QAAQ;YAC1BT,QAAQhB,MAAM,IAAI;QACpB,OAAO,IAAIyB,SAAS,SAAS;YAC3BT,QAAQhB;QACV,OAAO,IAAIyB,SAAS,WAAW;YAC7BT,QAAQf;QACV,OAAO,IAAIwB,SAAS,WAAW;YAC7BT,QAAQ;gBAAEhB;gBAAOC;gBAASC;YAAc;QAC1C;QACA,MAAMyB,UAAU,IAAI,CAAC,UAAU,CAACD,SAASV;QACzC,IAAIW,SAAS;YACX,IAAI,CAAC,cAAc,CAAC,YAAY,CAAChB,OAAOc,MAAMC,SAASV;QACzD,OAAO;YACL,IAAI,CAAC,cAAc,CAAC,eAAe,CAACL,OAAOc,MAAMC,SAASV;QAC5D;QACA,OAAOW;IACT;IAEA;;;KAGG,GACH,WAAWD,OAAgB,EAAEV,KAAU,EAAgB;QACrD,IAAI,OAAOU,YAAY,UAAU;YAC/B,OAAOV,UAAUU;QACnB;QACA,IAAIA,mBAAmBE,QAAQ;YAC7B,IAAIZ,UAAUa,aAAab,UAAU,MAAM;gBACzC,OAAO;YACT;YACA,OAAOU,QAAQ,IAAI,CAACV;QACtB;QACA,IAAI,OAAOU,YAAY,YAAY;YACjC,OAAOA,QAAQV;QACjB;QACA,OAAO;IACT;IAEA;;;;KAIG,GACH,gBACEhB,KAAY,EACZC,OAAgB,EAChBC,aAAwB,EACV;QACd,MAAMC,eAAe,IAAI,CAAC,cAAc,CAACD;QACzC,IAAIC,gBAAgBD,eAAe;YACjCC,aAAa,IAAI,GAAGD;QACtB;QACA,IAAI,OAAOF,MAAM,OAAO,KAAK,YAAYF,aAAaA,CAACE,MAAM,OAAO,GAAG;YACrE,OAAO,IAAI,CAAC,8BAA8B,CAACG,cAAcH,MAAM,OAAO;QACxE;QACA,OAAO,IAAI,CAAC,wBAAwB,CAACG,cAAcH,OAAOC;IAC5D;IAEA;;KAEG,GACH,yBACEE,YAA6B,EAC7BH,KAAY,EACZC,OAAgB,EACF;QACd,6CAA6C;QAC7C,IAAIE,cAAc,aAAa;YAC7B,MAAM2B,cAAc,IAAI,CAAC,QAAQ,CAC/B9B,OACAG,aAAa,WAAW,EACxBF,SACAE,aAAa,IAAI;YAEnB,IAAI2B,aAAa;gBACf,OAAO;oBACL3B;oBACA,cAAc;wBACZ,GAAG2B,YAAY,KAAK;wBACpB,MACEA,YAAY,KAAK,IAAI3B,aAAa,IAAI,GAClC,GAAGA,aAAa,IAAI,CAAC,CAAC,EAAE2B,YAAY,KAAK,CAAC,IAAI,EAAE,GAChD3B,aAAa,IAAI;oBACzB;oBACA,QAAQ2B,YAAY,MAAM;oBAC1B,cAAc;gBAChB;YACF;QACF;QACA;;;KAGC,GACD,MAAMA,cAAc,IAAI,CAAC,QAAQ,CAC/B9B,OACA,IAAI,CAAC,MAAM,EACXC,SACAE,cAAc,QAAQ;QAExB,MAAMG,eAAea,QAAQhB,cAAc;QAC3C,IAAI2B,aAAa,OAAO;YACtB,OAAO;gBACL3B;gBACA,cAAc;oBACZ,GAAG2B,YAAY,KAAK;oBACpB,MAAMA,YAAY,KAAK,EAAE,QAAQ;gBACnC;gBACA,QAAQA,YAAY,MAAM;gBAC1BxB;YACF;QACF;QACA,OAAO;YACLH;YACA,cAAc;YACd,QAAQ,CAAC;YACTG;QACF;IACF;IAEA;;KAEG,GACH,+BACEH,YAA6B,EAC7B4B,WAAmB,EACL;QACd,MAAM,EAAEX,IAAI,EAAEf,MAAM,EAAE,GAAGR,4BAA4BA,CAACkC;QACtD;;KAEC,GACD,MAAMC,0BAA0B,CAACC;YAC/B,MAAM7B,eAAe,IAAI,CAAC,cAAc,CAAC6B;YACzC,IAAI,CAAC7B,cAAc;gBACjB,OAAO;oBACLD;oBACA,cAAc;oBACd,QAAQ,CAAC;oBACT,cAAc;gBAChB;YACF;YACA,OAAO;gBACLA;gBACA,cAAc;oBAAE,GAAGC,YAAY;oBAAE,MAAM6B;gBAAS;gBAChD5B;gBACA,cAAc;YAChB;QACF;QACA;;KAEC,GACD,8GAA8G;QAC9G,IAAIF,cAAc,MAAM;YACtB,MAAM+B,eAAeF,wBACnB,GAAG7B,aAAa,IAAI,CAAC,CAAC,EAAEiB,MAAM;YAEhC,IAAIc,aAAa,YAAY,EAAE;gBAC7B,OAAOA;YACT;QACF;QACA,4EAA4E;QAC5E,OAAOF,wBAAwBZ;IACjC;IAzYA,YACEV,MAAe,EACfyB,iBAA6CN,SAAS,CACtD;QANF;QACA;QAME,IAAI,CAAC,MAAM,GAAGnB;QACd,IAAI,CAAC,cAAc,GAAGyB,kBAAkB,IAAI1C,cAAcA;IAC5D;AAoYF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"testing/index.js","sources":["../../../src/testing/index.ts"],"sourcesContent":["import {\n type BotContext,\n type BotRequest,\n type BotSecrets,\n type BotSettings,\n type ContactInfo,\n INPUT,\n type Input,\n PROVIDER,\n type ProviderType,\n type ResolvedPlugins,\n type Session,\n type SessionUser,\n} from '../models'\n\n// ---------------------------------------------------------------------------\n// Default values\n// ---------------------------------------------------------------------------\n\nexport const TEST_DEFAULTS = {\n HUBTYPE_API_URL: 'https://api.hubtype.com',\n STATIC_URL: 'https://static.hubtype.com',\n LITELLM_API_URL: 'https://api.litellm.com',\n AZURE_OPENAI_API_BASE: 'https://api.openai.com',\n AZURE_OPENAI_API_VERSION: '2026-02-01',\n LANGUAGE_DETECTION_ENABLED: true,\n HUBTYPE_ACCESS_TOKEN: 'testAccessToken', // pragma: allowlist secret\n LITELLM_API_KEY: 'testLiteLLMAPIKey', // pragma: allowlist secret\n AZURE_OPENAI_API_KEY: 'testAzureOpenAIAPIKey', // pragma: allowlist secret\n ACCESS_TOKEN: 'fake_access_token',\n HUBTYPE_API_HOST: 'https://api.hubtype.com',\n FLOW_THREAD_ID: 'testFlowThreadId',\n BOT_ID: 'testBotId',\n USER_ID: 'testUserId',\n ORG_ID: 'testOrgId',\n ORG_NAME: 'testOrg',\n PROVIDER: PROVIDER.WEBCHAT as ProviderType,\n LOCALE: 'en',\n COUNTRY: 'US',\n BOT_INTERACTION_ID: 'testInteractionId',\n MESSAGE_ID: 'testMessageId',\n LAST_ROUTE_PATH: '',\n}\n\n// ---------------------------------------------------------------------------\n// Leaf factories\n// ---------------------------------------------------------------------------\n\nexport function createTestSettings(\n overrides?: Partial<BotSettings>\n): BotSettings {\n return {\n HUBTYPE_API_URL: TEST_DEFAULTS.HUBTYPE_API_URL,\n STATIC_URL: TEST_DEFAULTS.STATIC_URL,\n LITELLM_API_URL: TEST_DEFAULTS.LITELLM_API_URL,\n AZURE_OPENAI_API_BASE: TEST_DEFAULTS.AZURE_OPENAI_API_BASE,\n AZURE_OPENAI_API_VERSION: TEST_DEFAULTS.AZURE_OPENAI_API_VERSION,\n LANGUAGE_DETECTION_ENABLED: TEST_DEFAULTS.LANGUAGE_DETECTION_ENABLED,\n CUSTOM_SHORT_URL_HOST: null,\n custom: {},\n ...overrides,\n }\n}\n\nexport function createTestSecrets(overrides?: Partial<BotSecrets>): BotSecrets {\n return {\n HUBTYPE_ACCESS_TOKEN: TEST_DEFAULTS.HUBTYPE_ACCESS_TOKEN,\n LITELLM_API_KEY: TEST_DEFAULTS.LITELLM_API_KEY,\n AZURE_OPENAI_API_KEY: TEST_DEFAULTS.AZURE_OPENAI_API_KEY,\n custom: {},\n ...overrides,\n }\n}\n\nexport interface TestUserOptions {\n id?: string\n provider?: ProviderType\n locale?: string\n country?: string\n systemLocale?: string\n contactInfo?: ContactInfo[]\n extraData?: Record<string, any>\n}\n\nexport function createTestSessionUser(\n options?: TestUserOptions\n): SessionUser<Record<string, any>> {\n const locale = options?.locale ?? TEST_DEFAULTS.LOCALE\n const country = options?.country ?? TEST_DEFAULTS.COUNTRY\n return {\n id: options?.id ?? TEST_DEFAULTS.USER_ID,\n provider: options?.provider ?? TEST_DEFAULTS.PROVIDER,\n locale,\n country,\n system_locale: options?.systemLocale ?? locale,\n contact_info: options?.contactInfo ?? [],\n extra_data: options?.extraData ?? {},\n }\n}\n\nexport interface TestSessionOptions {\n user?: TestUserOptions\n botId?: string\n organization?: string\n organizationId?: string\n isFirstInteraction?: boolean\n isTestIntegration?: boolean\n accessToken?: string\n hubtypeApi?: string\n flowThreadId?: string\n retries?: number\n shadowing?: boolean\n hubtypeCaseId?: string\n captureUserInputNodeId?: string\n}\n\nexport function createTestSession(\n options?: TestSessionOptions\n): Session<Record<string, any>> {\n return {\n bot: { id: options?.botId ?? TEST_DEFAULTS.BOT_ID },\n user: createTestSessionUser(options?.user),\n organization: options?.organization ?? TEST_DEFAULTS.ORG_NAME,\n organization_id: options?.organizationId ?? TEST_DEFAULTS.ORG_ID,\n is_first_interaction: options?.isFirstInteraction ?? false,\n is_test_integration: options?.isTestIntegration ?? false,\n _access_token: options?.accessToken ?? TEST_DEFAULTS.ACCESS_TOKEN,\n _hubtype_api: options?.hubtypeApi ?? TEST_DEFAULTS.HUBTYPE_API_HOST,\n flow_thread_id: options?.flowThreadId ?? TEST_DEFAULTS.FLOW_THREAD_ID,\n __retries: options?.retries ?? 0,\n _shadowing: options?.shadowing,\n _hubtype_case_id: options?.hubtypeCaseId,\n capture_user_input: options?.captureUserInputNodeId\n ? { node_id: options.captureUserInputNodeId }\n : undefined,\n }\n}\n\nexport interface TestInputOptions {\n type?: Input['type']\n data?: string\n text?: string\n payload?: string\n src?: string\n botInteractionId?: string\n messageId?: string\n context?: Input['context']\n transcript?: string\n}\n\nexport function createTestInput(options?: TestInputOptions): Input {\n return {\n type: options?.type ?? INPUT.TEXT,\n data: options?.data,\n text: options?.text ?? options?.data,\n payload: options?.payload,\n src: options?.src,\n transcript: options?.transcript,\n context: options?.context,\n bot_interaction_id:\n options?.botInteractionId ?? TEST_DEFAULTS.BOT_INTERACTION_ID,\n message_id: options?.messageId ?? TEST_DEFAULTS.MESSAGE_ID,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Composite factories\n// ---------------------------------------------------------------------------\n\nexport interface TestBotRequestOptions {\n input?: TestInputOptions | Input\n session?: TestSessionOptions | Session\n lastRoutePath?: string\n settings?: Partial<BotSettings> | BotSettings\n secrets?: Partial<BotSecrets> | BotSecrets\n}\n\nfunction isFullInput(v: TestInputOptions | Input): v is Input {\n return 'bot_interaction_id' in v && 'message_id' in v\n}\n\nfunction isFullSession(v: TestSessionOptions | Session): v is Session {\n return 'bot' in v && '__retries' in v\n}\n\nfunction isFullSettings(\n v: Partial<BotSettings> | BotSettings\n): v is BotSettings {\n return (\n 'HUBTYPE_API_URL' in v &&\n 'STATIC_URL' in v &&\n 'LITELLM_API_URL' in v &&\n 'AZURE_OPENAI_API_BASE' in v &&\n 'AZURE_OPENAI_API_VERSION' in v &&\n 'LANGUAGE_DETECTION_ENABLED' in v &&\n 'CUSTOM_SHORT_URL_HOST' in v &&\n 'custom' in v\n )\n}\n\nfunction isFullSecrets(v: Partial<BotSecrets> | BotSecrets): v is BotSecrets {\n return (\n 'HUBTYPE_ACCESS_TOKEN' in v &&\n 'LITELLM_API_KEY' in v &&\n 'AZURE_OPENAI_API_KEY' in v &&\n 'custom' in v\n )\n}\n\nexport function createTestBotRequest(\n options?: TestBotRequestOptions\n): BotRequest {\n const input =\n options?.input == null\n ? createTestInput()\n : isFullInput(options.input)\n ? options.input\n : createTestInput(options.input)\n\n const session =\n options?.session == null\n ? createTestSession()\n : isFullSession(options.session)\n ? options.session\n : createTestSession(options.session)\n\n const settings =\n options?.settings == null\n ? createTestSettings()\n : isFullSettings(options.settings)\n ? options.settings\n : createTestSettings(options.settings)\n\n const secrets =\n options?.secrets == null\n ? createTestSecrets()\n : isFullSecrets(options.secrets)\n ? options.secrets\n : createTestSecrets(options.secrets)\n\n return {\n input,\n session,\n lastRoutePath: options?.lastRoutePath ?? TEST_DEFAULTS.LAST_ROUTE_PATH,\n settings,\n secrets,\n }\n}\n\nexport interface TestBotContextOptions<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n> extends TestBotRequestOptions {\n plugins?: TPlugins\n params?: Record<string, string>\n defaultDelay?: number\n defaultTyping?: number\n}\n\nexport function createTestBotContext<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n>(options?: TestBotContextOptions<TPlugins>): BotContext<TPlugins> {\n const request = createTestBotRequest(options)\n\n const sessionForLocale =\n options?.session == null\n ? createTestSession()\n : isFullSession(options.session)\n ? options.session\n : createTestSession(options.session)\n\n const locale = sessionForLocale.user.locale\n const country = sessionForLocale.user.country\n const systemLocale = sessionForLocale.user.system_locale\n\n return {\n ...request,\n plugins: options?.plugins ?? ({} as TPlugins),\n params: options?.params ?? {},\n defaultDelay: options?.defaultDelay ?? 0,\n defaultTyping: options?.defaultTyping ?? 0,\n getUserLocale: () => locale,\n getUserCountry: () => country,\n getSystemLocale: () => systemLocale,\n setUserLocale: () => undefined,\n setUserCountry: () => undefined,\n setSystemLocale: () => undefined,\n }\n}\n\n/**\n * Alias for `createTestBotContext` typed as `PluginPreRequest`.\n * PluginPreRequest === BotContext in @botonic/core.\n */\nexport const createTestPluginPreRequest = createTestBotContext\n\nexport interface TestPluginPostRequestOptions<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n> extends TestBotContextOptions<TPlugins> {\n response?: string | null\n}\n\nexport function createTestPluginPostRequest<\n TPlugins extends ResolvedPlugins = ResolvedPlugins,\n>(\n options?: TestPluginPostRequestOptions<TPlugins>\n): BotContext<TPlugins> & { response: string | null } {\n return {\n ...createTestBotContext(options),\n response: options?.response ?? null,\n }\n}\n"],"names":["INPUT","PROVIDER","TEST_DEFAULTS","createTestSettings","overrides","createTestSecrets","createTestSessionUser","options","locale","country","createTestSession","undefined","createTestInput","isFullInput","v","isFullSession","isFullSettings","isFullSecrets","createTestBotRequest","input","session","settings","secrets","createTestBotContext","request","sessionForLocale","systemLocale","createTestPluginPreRequest","createTestPluginPostRequest"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils/bot-config.js","sources":["../../../src/utils/bot-config.ts"],"sourcesContent":["import { type ZodType, z } from 'zod'\nimport { type VariableConfigJSON, VariableType } from '../models/index'\n\nconst SESSION_USER_EXTRA_DATA_PREFIX = 'session.user.extra_data'\n\nexport const BASE_SESSION_VARIABLES: VariableConfigJSON[] = [\n { key_path: 'input.data', type: VariableType.String },\n { key_path: 'input.type', type: VariableType.String },\n {\n key_path: 'session.is_first_interaction',\n type: VariableType.Boolean,\n },\n {\n key_path: 'session.is_test_integration',\n type: VariableType.Boolean,\n },\n { key_path: 'session._shadowing', type: VariableType.Boolean },\n { key_path: 'session.user.locale', type: VariableType.String },\n {\n key_path: 'session.user.country',\n type: VariableType.String,\n },\n { key_path: 'session.user.system_locale', type: VariableType.String },\n { key_path: 'session.user.username', type: VariableType.String },\n {\n key_path: 'session.user.unformatted_phone_number',\n type: VariableType.String,\n },\n]\n\nexport function getSessionVariables(\n extraDataSchema?: ZodType\n): VariableConfigJSON[] {\n const variables = [...BASE_SESSION_VARIABLES]\n\n if (extraDataSchema) {\n variables.push(...getSessionVariablesFromZodSchema(extraDataSchema))\n }\n\n return variables\n}\n\nfunction getSessionVariablesFromZodSchema(\n schema: ZodType\n): VariableConfigJSON[] {\n const jsonSchema = z.toJSONSchema(schema) as JsonSchemaNode\n\n if (!jsonSchema.properties) {\n return []\n }\n\n return Object.entries(jsonSchema.properties).flatMap(\n ([key, propertySchema]) =>\n getSessionVariablesFromJsonSchema(\n propertySchema,\n `${SESSION_USER_EXTRA_DATA_PREFIX}.${key}`\n )\n )\n}\n\nfunction getSessionVariablesFromJsonSchema(\n schema: JsonSchemaNode,\n keyPath: string\n): VariableConfigJSON[] {\n const type = getJsonSchemaType(schema)\n\n // TODO:Arrays are not supported yet. Review in the future, how to handle them\n // in the frontend feature-flow-builder and in the plugin-flow-builder.\n if (type === 'array') {\n return []\n }\n\n if (type === 'object' && schema.properties) {\n return Object.entries(schema.properties).flatMap(([key, propertySchema]) =>\n getSessionVariablesFromJsonSchema(propertySchema, `${keyPath}.${key}`)\n )\n }\n\n const variableType = getVariableTypeFromJsonSchema(schema)\n if (!variableType) {\n return []\n }\n\n return [{ key_path: keyPath, type: variableType }]\n}\n\nfunction getJsonSchemaType(schema: JsonSchemaNode): string | undefined {\n const resolved = resolveJsonSchemaNode(schema)\n const { type } = resolved\n\n if (Array.isArray(type)) {\n return type.find(candidate => candidate !== 'null')\n }\n\n return type\n}\n\nfunction getVariableTypeFromJsonSchema(\n schema: JsonSchemaNode\n): VariableType | undefined {\n const resolved = resolveJsonSchemaNode(schema)\n const type = getJsonSchemaType(resolved)\n\n // enum is transformed to string. Review in the future, how to handle them\n if (type === 'string' || resolved.enum !== undefined) {\n return VariableType.String\n }\n\n if (type === 'number' || type === 'integer') {\n return VariableType.Number\n }\n\n if (type === 'boolean') {\n return VariableType.Boolean\n }\n\n return undefined\n}\n\ntype JsonSchemaNode = {\n type?: string | string[]\n enum?: unknown[]\n properties?: Record<string, JsonSchemaNode>\n anyOf?: JsonSchemaNode[]\n}\n\nfunction resolveJsonSchemaNode(schema: JsonSchemaNode): JsonSchemaNode {\n if (schema.anyOf?.length) {\n const nonNullSchema = schema.anyOf.find(\n candidate => candidate.type !== 'null'\n )\n if (nonNullSchema) {\n return resolveJsonSchemaNode(nonNullSchema)\n }\n }\n\n return schema\n}\n"],"names":["z","VariableType","SESSION_USER_EXTRA_DATA_PREFIX","BASE_SESSION_VARIABLES","getSessionVariables","extraDataSchema","variables","getSessionVariablesFromZodSchema","schema","jsonSchema","Object","key","propertySchema","getSessionVariablesFromJsonSchema","keyPath","type","getJsonSchemaType","variableType","getVariableTypeFromJsonSchema","resolved","resolveJsonSchemaNode","Array","candidate","undefined","nonNullSchema"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils/check-providers.js","sources":["../../../src/utils/check-providers.ts"],"sourcesContent":["import { PROVIDER, type Session } from '../models/legacy-types'\n\n// To check Provider in session\nexport function isDev(session: Session) {\n return session.user.provider === PROVIDER.DEV\n}\n\nexport function isWebchat(session: Session) {\n // When the provider is DEV should we return true because it is a webchat?\n return session.user.provider === PROVIDER.WEBCHAT\n}\n\nexport function isWhatsapp(session: Session) {\n return session.user.provider === PROVIDER.WHATSAPP\n}\n\nexport function isTelegram(session: Session) {\n return session.user.provider === PROVIDER.TELEGRAM\n}\n\nexport function isFacebook(session: Session) {\n return session.user.provider === PROVIDER.FACEBOOK\n}\n\nexport function isInstagram(session: Session) {\n return session.user.provider === PROVIDER.INSTAGRAM\n}\n\nexport function isTwitter(session: Session) {\n return session.user.provider === PROVIDER.TWITTER\n}\n"],"names":["PROVIDER","isDev","session","isWebchat","isWhatsapp","isTelegram","isFacebook","isInstagram","isTwitter"],"mappings":";;;AAA+D;AAE/D,+BAA+B;AACxB,SAASC,KAAKA,CAACC,OAAgB;IACpC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,YAAY;AAC/C;AAEO,SAASG,SAASA,CAACD,OAAgB;IACxC,0EAA0E;IAC1E,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,gBAAgB;AACnD;AAEO,SAASI,UAAUA,CAACF,OAAgB;IACzC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,iBAAiB;AACpD;AAEO,SAASK,UAAUA,CAACH,OAAgB;IACzC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,iBAAiB;AACpD;AAEO,SAASM,UAAUA,CAACJ,OAAgB;IACzC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,iBAAiB;AACpD;AAEO,SAASO,WAAWA,CAACL,OAAgB;IAC1C,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,kBAAkB;AACrD;AAEO,SAASQ,SAASA,CAACN,OAAgB;IACxC,OAAOA,QAAQ,IAAI,CAAC,QAAQ,KAAKF,gBAAgB;AACnD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils/functional.js","sources":["../../../src/utils/functional.ts"],"sourcesContent":["export const isNode = (): boolean => {\n // @ts-expect-error\n return typeof IS_NODE !== 'undefined'\n ? // @ts-ignore\n IS_NODE\n : typeof process !== 'undefined' &&\n process.versions !== null &&\n process.versions.node !== null\n}\n\nexport const isBrowser = (): boolean => {\n // @ts-expect-error\n return typeof IS_BROWSER !== 'undefined'\n ? // @ts-ignore\n IS_BROWSER\n : typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n !window.process?.versions?.node // In Jest window.process?.versions?.node is defined\n}\n\nexport const isMobile = (mobileBreakpoint = 460): boolean => {\n if (isBrowser()) {\n const w = Math.max(\n document.documentElement.clientWidth,\n window.innerWidth || 0\n )\n if (w < mobileBreakpoint) {\n return true\n }\n }\n return false\n}\n\nexport function isFunction(o: any): boolean {\n return typeof o === 'function'\n}\n\nexport function cloneObject(object: any): any {\n if (!object) {\n return {}\n }\n return { ...object }\n}\n\nexport const params2queryString = (params: { [key: string]: string }): string =>\n Object.entries(params)\n .map(([k, v]: any) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&')\n\n// Joins path segments. Preserves initial \"/\" and resolves \"..\" and \".\"\n// Does not support using \"..\" to go above/outside the root.\n// This means that join(\"foo\", \"../../bar\") will not resolve to \"../bar\"\nexport const join = (...segments: string[]): string => {\n // Split the inputs into a list of path commands.\n let parts: string[] = []\n for (let i = 0, l = segments.length; i < l; i++) {\n parts = parts.concat(segments[i].split('/'))\n }\n // Interpret the path commands to get the new resolved path.\n const newParts: string[] = []\n for (let i = 0, l = parts.length; i < l; i++) {\n const part = parts[i]\n // Remove leading and trailing slashes\n // Also remove \".\" segments\n if (!part || part === '.') {\n continue\n }\n // Interpret \"..\" to pop the last segment\n if (part === '..') {\n newParts.pop()\n }\n // Push new path segments.\n else {\n newParts.push(part)\n }\n }\n // Preserve the initial slash if there was one.\n if (parts[0] === '') {\n newParts.unshift('')\n }\n // Turn back into a single string path.\n return newParts.join('/') || (newParts.length ? '/' : '.')\n}\n\n// A simple function to get the dirname of a path\n// Trailing slashes are ignored. Leading slash is preserved.\nexport const dirname = (path: string): string => join(path, '..')\n"],"names":["isNode","IS_NODE","process","isBrowser","IS_BROWSER","window","isMobile","mobileBreakpoint","w","Math","document","isFunction","o","cloneObject","object","params2queryString","params","Object","k","v","encodeURIComponent","join","segments","parts","i","l","newParts","part","dirname","path"],"mappings":"AAAO,MAAMA,MAAMA,GAAG;IACpB,mBAAmB;IACnB,OAAO,OAAOC,YAAY,cAEtBA,UACA,OAAOC,YAAY,eACjBA,QAAQ,QAAQ,KAAK,QACrBA,QAAQ,QAAQ,CAAC,IAAI,KAAK;AAClC,EAAC;AAEM,MAAMC,SAASA,GAAG;IACvB,mBAAmB;IACnB,OAAO,OAAOC,eAAe,cAEzBA,aACA,OAAOC,WAAW,eAChB,OAAOA,OAAO,QAAQ,KAAK,eAC3B,CAACA,OAAO,OAAO,EAAE,UAAU,KAAK,oDAAoD;;AAC5F,EAAC;AAEM,MAAMC,QAAQA,GAAG,CAACC,mBAAmB,GAAG;IAC7C,IAAIJ,SAASA,IAAI;QACf,MAAMK,IAAIC,KAAK,GAAG,CAChBC,SAAS,eAAe,CAAC,WAAW,EACpCL,OAAO,UAAU,IAAI;QAEvB,IAAIG,IAAID,kBAAkB;YACxB,OAAO;QACT;IACF;IACA,OAAO;AACT,EAAC;AAEM,SAASI,UAAUA,CAACC,CAAM;IAC/B,OAAO,OAAOA,MAAM;AACtB;AAEO,SAASC,WAAWA,CAACC,MAAW;IACrC,IAAI,CAACA,QAAQ;QACX,OAAO,CAAC;IACV;IACA,OAAO;QAAE,GAAGA,MAAM;IAAC;AACrB;AAEO,MAAMC,kBAAkBA,GAAG,CAACC,SACjCC,OAAO,OAAO,CAACD,QACZ,GAAG,CAAC,CAAC,CAACE,GAAGC,EAAO,GAAK,GAAGC,mBAAmBF,GAAG,CAAC,EAAEE,mBAAmBD,IAAI,EACxE,IAAI,CAAC,KAAI;AAEd,wEAAwE;AACxE,4DAA4D;AAC5D,wEAAwE;AACjE,MAAME,IAAIA,GAAG,CAAC,GAAGC;IACtB,iDAAiD;IACjD,IAAIC,QAAkB,EAAE;IACxB,IAAK,IAAIC,IAAI,GAAGC,IAAIH,SAAS,MAAM,EAAEE,IAAIC,GAAGD,IAAK;QAC/CD,QAAQA,MAAM,MAAM,CAACD,QAAQ,CAACE,EAAE,CAAC,KAAK,CAAC;IACzC;IACA,4DAA4D;IAC5D,MAAME,WAAqB,EAAE;IAC7B,IAAK,IAAIF,IAAI,GAAGC,IAAIF,MAAM,MAAM,EAAEC,IAAIC,GAAGD,IAAK;QAC5C,MAAMG,OAAOJ,KAAK,CAACC,EAAE;QACrB,sCAAsC;QACtC,2BAA2B;QAC3B,IAAI,CAACG,QAAQA,SAAS,KAAK;YACzB;QACF;QACA,yCAAyC;QACzC,IAAIA,SAAS,MAAM;YACjBD,SAAS,GAAG;QACd,OAEK;YACHA,SAAS,IAAI,CAACC;QAChB;IACF;IACA,+CAA+C;IAC/C,IAAIJ,KAAK,CAAC,EAAE,KAAK,IAAI;QACnBG,SAAS,OAAO,CAAC;IACnB;IACA,uCAAuC;IACvC,OAAOA,SAAS,IAAI,CAAC,QAASA,CAAAA,SAAS,MAAM,GAAG,MAAM,GAAE;AAC1D,EAAC;AAED,iDAAiD;AACjD,4DAA4D;AACrD,MAAME,OAAOA,GAAG,CAACC,OAAyBR,IAAIA,CAACQ,MAAM,MAAK"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils/index.js","sources":["../../../src/utils/index.ts"],"sourcesContent":["export * from './bot-config'\nexport * from './check-providers'\nexport * from './functional'\n"],"names":[],"mappings":";;;AAA4B;AACK;AACL"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes