From 97987e9af466e6bb926b3812975eb891d13559a3 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Tue, 26 Mar 2024 16:47:26 -0400 Subject: [PATCH 01/12] feat: enable choice trace --- .../lib/execute-function/lib/adapt-trace.ts | 45 +++++++++++++++++-- .../runtime-command/trace-command.dto.ts | 36 +++++++++++++-- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts index 0a5920fb0..facd581c1 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts @@ -3,11 +3,13 @@ import { Utils } from '@voiceflow/common'; import { SimpleAction, + SimpleActionButton, SimpleAudioTrace, - SimpleButton, SimpleCard, SimpleCardV2Trace, SimpleCarouselTrace, + SimpleChoiceTrace, + SimpleGeneralButton, SimpleSpeakTrace, SimpleTextTrace, SimpleTraceType, @@ -85,7 +87,7 @@ const adaptAction = (action: SimpleAction): BaseRequest.Action.BaseAction => { }; }; -const adaptButton = (button: SimpleButton): BaseRequest.ActionRequestButton => { +const adaptActionButton = (button: SimpleActionButton): BaseRequest.ActionRequestButton => { return { name: button.name, request: { @@ -98,11 +100,33 @@ const adaptButton = (button: SimpleButton): BaseRequest.ActionRequestButton => { }; }; +const toFunctionGeneralButtonName = (name: string) => { + const buttonName = `function-button:${name}`; + if (!isFunctionGeneralButtonName(buttonName)) { + throw new Error('invalud button name'); + } + return buttonName; +}; + +const isFunctionGeneralButtonName = (name: string) => /^function-button:[A-Z_a-z][\dA-Za-z]*$/.test(name); + +const adaptGeneralButton = (button: SimpleGeneralButton): BaseRequest.GeneralRequestButton => { + return { + name: button.name, + request: { + type: toFunctionGeneralButtonName(button.payload.code), + payload: { + label: button.name, + }, + }, + }; +}; + const adaptCard = (card: SimpleCard): BaseNode.Carousel.TraceCarouselCard => { return { ...card, id: cuid.slug(), - buttons: (card.buttons ?? []).map((but) => adaptButton(but)), + buttons: (card.buttons ?? []).map((but) => adaptActionButton(but)), }; }; @@ -124,11 +148,22 @@ const adaptCardV2Trace = (trace: SimpleCardV2Trace): Trace => { type: TraceType.CARD_V2, payload: { ...trace.payload, - buttons: (trace.payload.buttons ?? []).map((but) => adaptButton(but)), + buttons: (trace.payload.buttons ?? []).map((but) => adaptActionButton(but)), }, } satisfies BaseTrace.CardV2; }; +const adaptChoiceTrace = (trace: SimpleChoiceTrace): Trace => { + return { + ...trace, + type: TraceType.CHOICE, + payload: { + ...trace.payload, + buttons: (trace.payload.buttons ?? []).map((but) => adaptGeneralButton(but)), + }, + } satisfies BaseTrace.Choice; +}; + export function adaptTrace(trace: Trace): Trace { if (!isSimpleTrace(trace)) return trace; @@ -145,6 +180,8 @@ export function adaptTrace(trace: Trace): Trace { return adaptCarouselTrace(trace); case SimpleTraceType.CardV2: return adaptCardV2Trace(trace); + case SimpleTraceType.Choice: + return adaptChoiceTrace(trace); default: return trace; } diff --git a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts index b07e4b941..1c5e692c8 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts @@ -9,8 +9,13 @@ export enum SimpleTraceType { Visual = 'visual', CardV2 = 'cardV2', Carousel = 'carousel', + Choice = 'choice', } +const constraints = { + MAX_SMALL_STRING_LENGTH: 128, +} as const; + export const TraceDTO = z .object({ type: z.string({ @@ -87,14 +92,27 @@ export const SimpleActionDTO = z.discriminatedUnion('type', [SimpleURLActionDTO] export type SimpleAction = z.infer; -export const SimpleButtonDTO = z.object({ - name: z.string(), +export const SimpleActionButtonDTO = z.object({ + name: z.string().describe('Text for the button UI'), payload: z.object({ + type: z + .literal('action') + .optional() + .describe('Type of the button. Optional due to backwards compatibility reasons'), actions: z.array(SimpleActionDTO), }), }); -export type SimpleButton = z.infer; +export type SimpleActionButton = z.infer; + +export const SimpleGeneralButtonDTO = z.object({ + name: z.string().describe('Text for the button UI'), + payload: z.object({ + code: z.string().max(constraints.MAX_SMALL_STRING_LENGTH).describe('Defines the custom button request type'), + }), +}); + +export type SimpleGeneralButton = z.infer; export const SimpleCardDTO = z.object({ imageUrl: z.string(), @@ -102,7 +120,7 @@ export const SimpleCardDTO = z.object({ description: z.object({ text: z.string(), }), - buttons: z.array(SimpleButtonDTO).optional(), + buttons: z.array(SimpleActionButtonDTO).optional(), }); export type SimpleCard = z.infer; @@ -124,6 +142,15 @@ export const SimpleCarouselTraceDTO = TraceDTO.extend({ export type SimpleCarouselTrace = z.infer; +export const SimpleChoiceTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Choice), + payload: z.object({ + buttons: z.array(SimpleGeneralButtonDTO), + }), +}).passthrough(); + +export type SimpleChoiceTrace = z.infer; + export const SimpleTraceDTO = z.discriminatedUnion('type', [ SimpleTextTraceDTO, SimpleSpeakTraceDTO, @@ -132,6 +159,7 @@ export const SimpleTraceDTO = z.discriminatedUnion('type', [ SimpleVisualTraceDTO, SimpleCardV2TraceDTO, SimpleCarouselTraceDTO, + SimpleChoiceTraceDTO, ]); export type SimpleTrace = z.infer; From 97137e41588634691a2020dfecc3ba23ef889aa1 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Wed, 27 Mar 2024 16:24:58 -0400 Subject: [PATCH 02/12] feat: refactored simplified types and added next many command --- .../lib/execute-function/lib/adapt-trace.ts | 35 ++-- .../execute-function/lib/is-simple-trace.ts | 4 +- .../lib/execute-function/lib/validate-next.ts | 4 +- .../execute-function/lib/validate-trace.ts | 3 +- .../function-exception/function.exception.ts | 2 +- .../button/action-button.dto.ts | 26 +++ .../button/general-button.dto.ts | 18 +++ .../function/runtime-command/card/card.dto.ts | 14 ++ .../function/runtime-command/constants.ts | 3 + .../runtime-command/next-command.dto.ts | 12 +- .../runtime-command/trace-command.dto.ts | 153 ++---------------- .../runtime-command/trace/audio.dto.ts | 13 ++ .../runtime-command/trace/base.dto.ts | 13 ++ .../runtime-command/trace/cardV2.dto.ts | 12 ++ .../runtime-command/trace/carousel.dto.ts | 16 ++ .../runtime-command/trace/choice.dto.ts | 14 ++ .../runtime-command/trace/debug.dto.ts | 13 ++ .../trace/simple-trace-type.enum.ts | 10 ++ .../runtime-command/trace/speak.dto.ts | 15 ++ .../runtime-command/trace/text.dto.ts | 13 ++ .../runtime-command/trace/visual.dto.ts | 13 ++ .../transfer/matched-transfer.dto.ts | 12 ++ .../runtime-command/transfer/transfer.dto.ts | 19 +++ 23 files changed, 263 insertions(+), 174 deletions(-) create mode 100644 runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/card/card.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/constants.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/simple-trace-type.enum.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/transfer/transfer.dto.ts diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts index facd581c1..4fd373acc 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts @@ -1,21 +1,18 @@ import { BaseNode, BaseRequest, BaseTrace } from '@voiceflow/base-types'; import { Utils } from '@voiceflow/common'; -import { - SimpleAction, - SimpleActionButton, - SimpleAudioTrace, - SimpleCard, - SimpleCardV2Trace, - SimpleCarouselTrace, - SimpleChoiceTrace, - SimpleGeneralButton, - SimpleSpeakTrace, - SimpleTextTrace, - SimpleTraceType, - SimpleVisualTrace, - Trace, -} from '../../../runtime-command/trace-command.dto'; +import { SimpleAction, SimpleActionButton } from '../../../runtime-command/button/action-button.dto'; +import { SimpleGeneralButton } from '../../../runtime-command/button/general-button.dto'; +import { SimpleCard } from '../../../runtime-command/card/card.dto'; +import { SimpleAudioTrace } from '../../../runtime-command/trace/audio.dto'; +import { Trace } from '../../../runtime-command/trace/base.dto'; +import { SimpleCardV2Trace } from '../../../runtime-command/trace/cardv2.dto'; +import { SimpleCarouselTrace } from '../../../runtime-command/trace/carousel.dto'; +import { SimpleChoiceTrace } from '../../../runtime-command/trace/choice.dto'; +import { SimpleTraceType } from '../../../runtime-command/trace/simple-trace-type.enum'; +import { SimpleSpeakTrace } from '../../../runtime-command/trace/speak.dto'; +import { SimpleTextTrace } from '../../../runtime-command/trace/text.dto'; +import { SimpleVisualTrace } from '../../../runtime-command/trace/visual.dto'; import { isSimpleTrace } from './is-simple-trace'; const { cuid } = Utils.id; @@ -101,15 +98,9 @@ const adaptActionButton = (button: SimpleActionButton): BaseRequest.ActionReques }; const toFunctionGeneralButtonName = (name: string) => { - const buttonName = `function-button:${name}`; - if (!isFunctionGeneralButtonName(buttonName)) { - throw new Error('invalud button name'); - } - return buttonName; + return `function-button:${name}`; }; -const isFunctionGeneralButtonName = (name: string) => /^function-button:[A-Z_a-z][\dA-Za-z]*$/.test(name); - const adaptGeneralButton = (button: SimpleGeneralButton): BaseRequest.GeneralRequestButton => { return { name: button.name, diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts index e64427be5..7dbe255d5 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts @@ -1,4 +1,6 @@ -import { SimpleTrace, SimpleTraceDTO, SimpleTraceType, Trace } from '../../../runtime-command/trace-command.dto'; +import { Trace } from '../../../runtime-command/trace/base.dto'; +import { SimpleTraceType } from '../../../runtime-command/trace/simple-trace-type.enum'; +import { SimpleTrace, SimpleTraceDTO } from '../../../runtime-command/trace-command.dto'; export const isSimpleTrace = (trace: Trace): trace is SimpleTrace => SimpleTraceDTO.safeParse(trace).success; diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts index 57c2b9f7e..3367941d9 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts @@ -1,8 +1,8 @@ -import { isNextPath, NextCommand } from '../../../runtime-command/next-command.dto'; +import { NextCommand, NextPathDTO } from '../../../runtime-command/next-command.dto'; import { FunctionPathException } from '../exceptions/function-path.exception'; export function validateNext(next: NextCommand, expectedPathCodes: Array) { - if (isNextPath(next) && !expectedPathCodes.includes(next.path)) { + if (NextPathDTO.safeParse(next).success && !expectedPathCodes.includes(next.path)) { throw new FunctionPathException(next.path, expectedPathCodes); } } diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts index 5fc7baa2f..673134081 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts @@ -1,6 +1,7 @@ import { InvalidRuntimeCommandException } from '@/runtime/lib/HTTPClient/function-lambda/exceptions/invalid-runtime-command.exception'; -import { SimpleTraceDTO, Trace } from '../../../runtime-command/trace-command.dto'; +import { Trace } from '../../../runtime-command/trace/base.dto'; +import { SimpleTraceDTO } from '../../../runtime-command/trace-command.dto'; import { isSimpleTraceType } from './is-simple-trace'; export function parseTrace(trace: Trace): Trace { diff --git a/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts b/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts index ab614bcd0..6a9e36ffe 100644 --- a/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts +++ b/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts @@ -2,7 +2,7 @@ import { BaseNode } from '@voiceflow/base-types'; import { HTTPException } from '@voiceflow/exception'; import { match } from 'ts-pattern'; -import { Trace } from '../../runtime-command/trace-command.dto'; +import { Trace } from '../../runtime-command/trace/base.dto'; export abstract class FunctionException extends Error { abstract get message(): string; diff --git a/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts new file mode 100644 index 000000000..396c630ee --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts @@ -0,0 +1,26 @@ +import { BaseRequest } from '@voiceflow/base-types'; +import { z } from 'zod'; + +export const SimpleURLActionDTO = z.object({ + type: z.literal(BaseRequest.Action.ActionType.OPEN_URL), + url: z.string(), +}); + +export type SimpleURLAction = z.infer; + +export const SimpleActionDTO = z.discriminatedUnion('type', [SimpleURLActionDTO]); + +export type SimpleAction = z.infer; + +export const SimpleActionButtonDTO = z.object({ + name: z.string().describe('Text for the button UI'), + payload: z.object({ + type: z + .literal('action') + .optional() + .describe('Type of the button. Optional due to backwards compatibility reasons'), + actions: z.array(SimpleActionDTO), + }), +}); + +export type SimpleActionButton = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts new file mode 100644 index 000000000..b73adc26f --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts @@ -0,0 +1,18 @@ +import { z } from 'zod'; + +export const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z][\dA-Za-z]*$/; + +export const isFunctionButtonName = (name: string) => FUNCTION_BUTTON_NAME_REGEX.test(name); + +export const SimpleGeneralButtonDTO = z.object({ + name: z.string().describe('Text for the button UI'), + payload: z.object({ + code: z + .string() + .max(constraints.MAX_SMALL_STRING_LENGTH) + .regex(FUNCTION_BUTTON_NAME_REGEX) + .describe('Defines the custom button request type'), + }), +}); + +export type SimpleGeneralButton = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/card/card.dto.ts b/runtime/lib/Handlers/function/runtime-command/card/card.dto.ts new file mode 100644 index 000000000..32d2648e2 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/card/card.dto.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; + +import { SimpleActionButtonDTO } from '../button/action-button.dto'; + +export const SimpleCardDTO = z.object({ + imageUrl: z.string(), + title: z.string(), + description: z.object({ + text: z.string(), + }), + buttons: z.array(SimpleActionButtonDTO).optional(), +}); + +export type SimpleCard = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/constants.ts b/runtime/lib/Handlers/function/runtime-command/constants.ts new file mode 100644 index 000000000..743024e9c --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/constants.ts @@ -0,0 +1,3 @@ +const constraints = { + MAX_SMALL_STRING_LENGTH: 128, +} as const; diff --git a/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts b/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts index becea68f8..3e79eed1b 100644 --- a/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts @@ -1,5 +1,8 @@ import { z } from 'zod'; +import { MatchedTransferDTO } from './transfer/matched-transfer.dto'; +import { TransferDTO } from './transfer/transfer.dto'; + export const NextPathDTO = z .object({ path: z.string({ @@ -11,9 +14,12 @@ export const NextPathDTO = z export type NextPath = z.infer; -// !TODO! - Add `NextStageDTO` to `NextCommandDTO` +export const NextManyCommandDTO = z.object({ + listen: z.literal(true), + defaultTo: TransferDTO, + to: z.array(MatchedTransferDTO), +}); + export const NextCommandDTO = NextPathDTO; export type NextCommand = z.infer; - -export const isNextPath = (val: unknown): val is NextPath => NextPathDTO.safeParse(val).success; diff --git a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts index 1c5e692c8..7de9e4b4e 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts @@ -1,32 +1,14 @@ -import { BaseNode, BaseRequest } from '@voiceflow/base-types'; import { z } from 'zod'; -export enum SimpleTraceType { - Text = 'text', - Speak = 'speak', - Audio = 'audio', - Debug = 'debug', - Visual = 'visual', - CardV2 = 'cardV2', - Carousel = 'carousel', - Choice = 'choice', -} - -const constraints = { - MAX_SMALL_STRING_LENGTH: 128, -} as const; - -export const TraceDTO = z - .object({ - type: z.string({ - required_error: `A Voiceflow trace must define a 'type' property`, - invalid_type_error: `Property 'type' of a Voiceflow trace must be a string`, - }), - payload: z.unknown().optional(), - }) - .passthrough(); - -export type Trace = z.infer; +import { SimpleAudioTraceDTO } from './trace/audio.dto'; +import { TraceDTO } from './trace/base.dto'; +import { SimpleCardV2TraceDTO } from './trace/cardv2.dto'; +import { SimpleCarouselTraceDTO } from './trace/carousel.dto'; +import { SimpleChoiceTraceDTO } from './trace/choice.dto'; +import { SimpleDebugTraceDTO } from './trace/debug.dto'; +import { SimpleSpeakTraceDTO } from './trace/speak.dto'; +import { SimpleTextTraceDTO } from './trace/text.dto'; +import { SimpleVisualTraceDTO } from './trace/visual.dto'; export const TraceCommandDTO = z.array(TraceDTO, { invalid_type_error: 'A trace command must be a list of valid Voiceflow trace types', @@ -34,123 +16,6 @@ export const TraceCommandDTO = z.array(TraceDTO, { export type TraceCommand = z.infer; -export const SimpleTextTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Text), - payload: z.object({ - message: z.string(), - }), -}).passthrough(); - -export type SimpleTextTrace = z.infer; - -export const SimpleSpeakTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Speak), - payload: z.object({ - message: z.string(), - voice: z.string().optional(), - src: z.string().optional(), - }), -}).passthrough(); - -export type SimpleSpeakTrace = z.infer; - -export const SimpleAudioTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Audio), - payload: z.object({ - src: z.string().optional(), - }), -}).passthrough(); - -export type SimpleAudioTrace = z.infer; - -export const SimpleDebugTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Debug), - payload: z.object({ - message: z.string(), - }), -}).passthrough(); - -export type SimpleDebugTrace = z.infer; - -export const SimpleVisualTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Visual), - payload: z.object({ - image: z.string(), - }), -}).passthrough(); - -export type SimpleVisualTrace = z.infer; - -export const SimpleURLActionDTO = z.object({ - type: z.literal(BaseRequest.Action.ActionType.OPEN_URL), - url: z.string(), -}); - -export type SimpleURLAction = z.infer; - -export const SimpleActionDTO = z.discriminatedUnion('type', [SimpleURLActionDTO]); - -export type SimpleAction = z.infer; - -export const SimpleActionButtonDTO = z.object({ - name: z.string().describe('Text for the button UI'), - payload: z.object({ - type: z - .literal('action') - .optional() - .describe('Type of the button. Optional due to backwards compatibility reasons'), - actions: z.array(SimpleActionDTO), - }), -}); - -export type SimpleActionButton = z.infer; - -export const SimpleGeneralButtonDTO = z.object({ - name: z.string().describe('Text for the button UI'), - payload: z.object({ - code: z.string().max(constraints.MAX_SMALL_STRING_LENGTH).describe('Defines the custom button request type'), - }), -}); - -export type SimpleGeneralButton = z.infer; - -export const SimpleCardDTO = z.object({ - imageUrl: z.string(), - title: z.string(), - description: z.object({ - text: z.string(), - }), - buttons: z.array(SimpleActionButtonDTO).optional(), -}); - -export type SimpleCard = z.infer; - -export const SimpleCardV2TraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.CardV2), - payload: SimpleCardDTO, -}).passthrough(); - -export type SimpleCardV2Trace = z.infer; - -export const SimpleCarouselTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Carousel), - payload: z.object({ - layout: z.nativeEnum(BaseNode.Carousel.CarouselLayout).optional(), - cards: z.array(SimpleCardDTO), - }), -}).passthrough(); - -export type SimpleCarouselTrace = z.infer; - -export const SimpleChoiceTraceDTO = TraceDTO.extend({ - type: z.literal(SimpleTraceType.Choice), - payload: z.object({ - buttons: z.array(SimpleGeneralButtonDTO), - }), -}).passthrough(); - -export type SimpleChoiceTrace = z.infer; - export const SimpleTraceDTO = z.discriminatedUnion('type', [ SimpleTextTraceDTO, SimpleSpeakTraceDTO, diff --git a/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts new file mode 100644 index 000000000..cd20ed32d --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleAudioTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Audio), + payload: z.object({ + src: z.string().optional(), + }), +}).passthrough(); + +export type SimpleAudioTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts new file mode 100644 index 000000000..f8dbc2414 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +export const TraceDTO = z + .object({ + type: z.string({ + required_error: `A Voiceflow trace must define a 'type' property`, + invalid_type_error: `Property 'type' of a Voiceflow trace must be a string`, + }), + payload: z.unknown().optional(), + }) + .passthrough(); + +export type Trace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts new file mode 100644 index 000000000..97e25110a --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +import { SimpleCardDTO } from '../card/card.dto'; +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleCardV2TraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.CardV2), + payload: SimpleCardDTO, +}).passthrough(); + +export type SimpleCardV2Trace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts new file mode 100644 index 000000000..3c3fb6427 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts @@ -0,0 +1,16 @@ +import { BaseNode } from '@voiceflow/base-types'; +import { z } from 'zod'; + +import { SimpleCardDTO } from '../card/card.dto'; +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleCarouselTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Carousel), + payload: z.object({ + layout: z.nativeEnum(BaseNode.Carousel.CarouselLayout).optional(), + cards: z.array(SimpleCardDTO), + }), +}).passthrough(); + +export type SimpleCarouselTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts new file mode 100644 index 000000000..40b09e745 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; + +import { SimpleGeneralButtonDTO } from '../button/general-button.dto'; +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleChoiceTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Choice), + payload: z.object({ + buttons: z.array(SimpleGeneralButtonDTO), + }), +}).passthrough(); + +export type SimpleChoiceTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts new file mode 100644 index 000000000..f0c3c4f40 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleDebugTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Debug), + payload: z.object({ + message: z.string(), + }), +}).passthrough(); + +export type SimpleDebugTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/simple-trace-type.enum.ts b/runtime/lib/Handlers/function/runtime-command/trace/simple-trace-type.enum.ts new file mode 100644 index 000000000..664fa53d1 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/simple-trace-type.enum.ts @@ -0,0 +1,10 @@ +export enum SimpleTraceType { + Text = 'text', + Speak = 'speak', + Audio = 'audio', + Debug = 'debug', + Visual = 'visual', + CardV2 = 'cardV2', + Carousel = 'carousel', + Choice = 'choice', +} diff --git a/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts new file mode 100644 index 000000000..43ee9be69 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts @@ -0,0 +1,15 @@ +import { z } from 'zod'; + +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleSpeakTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Speak), + payload: z.object({ + message: z.string(), + voice: z.string().optional(), + src: z.string().optional(), + }), +}).passthrough(); + +export type SimpleSpeakTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts new file mode 100644 index 000000000..3ccc5474d --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleTextTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Text), + payload: z.object({ + message: z.string(), + }), +}).passthrough(); + +export type SimpleTextTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts new file mode 100644 index 000000000..7e3a3d8d4 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { TraceDTO } from './base.dto'; +import { SimpleTraceType } from './simple-trace-type.enum'; + +export const SimpleVisualTraceDTO = TraceDTO.extend({ + type: z.literal(SimpleTraceType.Visual), + payload: z.object({ + image: z.string(), + }), +}).passthrough(); + +export type SimpleVisualTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts b/runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts new file mode 100644 index 000000000..71adfee4e --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +import { TransferDTO } from './transfer.dto'; + +export const MatchedTransferDTO = z.object({ + on: z.record(z.any()).describe('An underscore-query matching criteria object'), + dest: z + .union([z.string(), TransferDTO]) + .describe('If `string`, then this is a path transfer. Otherwise, it is an object specifying the kind of transfer'), +}); + +export type MatchedTransfer = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/transfer/transfer.dto.ts b/runtime/lib/Handlers/function/runtime-command/transfer/transfer.dto.ts new file mode 100644 index 000000000..a0cd66606 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/transfer/transfer.dto.ts @@ -0,0 +1,19 @@ +import { z } from 'zod'; + +export enum TransferType { + PATH = 'path', +} + +export const PathTransferDTO = z.object({ + type: z.literal(TransferType.PATH), + path: z.string({ + required_error: `One of the paths in the next command's \`to\` property is not defined`, + invalid_type_error: `Expected value of type 'string' for 'path' property`, + }), +}); + +export type PathTransfer = z.infer; + +export const TransferDTO = z.discriminatedUnion('type', [PathTransferDTO]); + +export type Transfer = z.infer; From c0877d552d30550e0fd4fc1411fa4f297a54080e Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Wed, 27 Mar 2024 18:34:03 -0400 Subject: [PATCH 03/12] feat: implemented listen functionality --- package.json | 1 + runtime/lib/Handlers/function/index.ts | 147 +++++++++++++++++- .../lib/execute-function/lib/adapt-trace.ts | 12 +- .../button/general-button.dto.ts | 4 +- .../runtime-command/next-command.dto.ts | 15 +- ...fer.dto.ts => conditional-transfer.dto.ts} | 4 +- typings/undescore-query.d.ts | 7 + yarn.lock | 8 + 8 files changed, 180 insertions(+), 18 deletions(-) rename runtime/lib/Handlers/function/runtime-command/transfer/{matched-transfer.dto.ts => conditional-transfer.dto.ts} (72%) create mode 100644 typings/undescore-query.d.ts diff --git a/package.json b/package.json index 9e9119329..983c0755f 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "slate": "0.72.3", "talisman": "^1.1.3", "ts-pattern": "^4.0.5", + "underscore-query": "^3.3.2", "unleash-client": "5.0.0", "validator": "^13.7.0", "words-to-numbers": "^1.5.1", diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index 17dd1df1d..a59b5bd1b 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -1,4 +1,5 @@ import { BaseTrace } from '@voiceflow/base-types'; +import { isGeneralRequest } from '@voiceflow/base-types/build/cjs/request'; import { BaseTraceFrame } from '@voiceflow/base-types/build/cjs/trace'; import { replaceVariables } from '@voiceflow/common'; import { @@ -7,16 +8,25 @@ import { FunctionCompiledNode, NodeType, } from '@voiceflow/dtos'; +import { NotImplementedException } from '@voiceflow/exception'; +import { isIntentRequest } from '@voiceflow/utils-designer'; +import { VoiceflowConstants } from '@voiceflow/voiceflow-types'; +import _ from 'lodash'; +import lodashModifier from 'underscore-query'; import { HandlerFactory } from '@/runtime/lib/Handler'; import Runtime from '../../Runtime'; import Store from '../../Runtime/Store'; import { executeFunction } from './lib/execute-function/execute-function'; +import { fromFunctionGeneralButtonName } from './lib/execute-function/lib/adapt-trace'; import { createFunctionExceptionDebugTrace } from './lib/function-exception/function.exception'; -import { NextCommand } from './runtime-command/next-command.dto'; +import { NextBranches, NextBranchesDTO, NextCommand } from './runtime-command/next-command.dto'; import { OutputVarsCommand } from './runtime-command/output-vars-command.dto'; import { TraceCommand } from './runtime-command/trace-command.dto'; +import { Transfer, TransferType } from './runtime-command/transfer/transfer.dto'; + +lodashModifier(_); const utilsObj = { replaceVariables, @@ -25,9 +35,15 @@ const utilsObj = { function applyOutputCommand( command: OutputVarsCommand, runtime: Runtime, - variables: Store, - outputVarDeclarations: FunctionCompiledDefinition['outputVars'], - outputVarAssignments: FunctionCompiledInvocation['outputVars'] + { + variables, + outputVarDeclarations, + outputVarAssignments, + }: { + variables: Store; + outputVarDeclarations: FunctionCompiledDefinition['outputVars']; + outputVarAssignments: FunctionCompiledInvocation['outputVars']; + } ): void { Object.keys(outputVarDeclarations).forEach((functionVarName) => { const diagramVariableName = outputVarAssignments[functionVarName]; @@ -45,13 +61,103 @@ function applyTraceCommand(command: TraceCommand, runtime: Runtime): void { }); } -function applyNextCommand(command: NextCommand, paths: FunctionCompiledInvocation['paths']): string | null { +function applyNextCommand( + command: NextCommand, + runtime: Runtime, + { nodeId, paths }: { nodeId: string; paths: FunctionCompiledInvocation['paths'] } +): string | null { + if ('listen' in command && command.listen) { + const { defaultTo, to } = command; + runtime.variables.set(VoiceflowConstants.BuiltInVariable.FUNCTION_CONDITIONAL_TRANSFERS, { defaultTo, to }); + return nodeId; + } if ('path' in command) { return paths[command.path] ?? null; } return null; } +function applyTransfer(transfer: string | Transfer, paths: FunctionCompiledInvocation['paths']) { + // Case 1 - `transfer` is a path string that must be mapped + if (typeof transfer === 'string') { + return paths[transfer]; + } + + // Case 2 - `transfer` is a Transfer object that can be anything such as a PathTransfer + if (transfer.type === TransferType.PATH) { + return paths[transfer.path]; + } + + throw new Error(`Function produced a transfer object with an unexpected type '${transfer.type}'`); +} + +interface FunctionRequestContext { + event?: { + code: string; // user-defined button type + }; + intent?: { + name: string; + confidence?: number; + entities: Record< + string, + { + name: string; + value: string; + } + >; + utterance?: string; + }; +} + +function handleListenResponse( + conditionalTransfers: NextBranches, + requestContext: FunctionRequestContext, + paths: FunctionCompiledInvocation['paths'] +): string { + // !TODO! - Remove the `any` cast here + const firstMatchingTransfer = conditionalTransfers.to.find( + (item) => (_ as any).query([requestContext], item.on).length > 0 + ); + + if (!firstMatchingTransfer) { + return applyTransfer(conditionalTransfers.defaultTo, paths); + } + + return applyTransfer(firstMatchingTransfer.dest, paths); +} + +function createFunctionRequestContext(runtime: Runtime): FunctionRequestContext { + const request = runtime.getRequest(); + + if (isIntentRequest(request)) { + const { + intent: { name }, + confidence, + entities = [], + query, + } = request.payload; + + return { + intent: { + name, + confidence, + entities: Object.fromEntries(entities.map((ent) => [ent.name, { name: ent.name, value: ent.value }])), + utterance: query, + }, + }; + } + + if (isGeneralRequest(request)) { + return { + event: { + code: fromFunctionGeneralButtonName(request.type), + }, + }; + } + + throw new NotImplementedException('Function received an unexpected request type'); +} + export const FunctionHandler: HandlerFactory = (utils) => ({ canHandle: (node) => node.type === NodeType.FUNCTION, @@ -59,6 +165,29 @@ export const FunctionHandler: HandlerFactory { return { ...acc, @@ -77,7 +206,11 @@ export const FunctionHandler: HandlerFactory { - return `function-button:${name}`; + return `${functionButtonPrefix}${name}`; +}; + +export const fromFunctionGeneralButtonName = (name: string) => { + if (!name.startsWith('function-button:')) { + throw new Error("failed to parse button name because it does not match the function's general button format"); + } + + return name.replace(functionButtonPrefix, ''); }; const adaptGeneralButton = (button: SimpleGeneralButton): BaseRequest.GeneralRequestButton => { diff --git a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts index b73adc26f..1be9098fe 100644 --- a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts @@ -1,8 +1,6 @@ import { z } from 'zod'; -export const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z][\dA-Za-z]*$/; - -export const isFunctionButtonName = (name: string) => FUNCTION_BUTTON_NAME_REGEX.test(name); +const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z][\dA-Za-z]*$/; export const SimpleGeneralButtonDTO = z.object({ name: z.string().describe('Text for the button UI'), diff --git a/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts b/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts index 3e79eed1b..ca07273d9 100644 --- a/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/next-command.dto.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; -import { MatchedTransferDTO } from './transfer/matched-transfer.dto'; +import { ConditionalTransferDTO } from './transfer/conditional-transfer.dto'; import { TransferDTO } from './transfer/transfer.dto'; export const NextPathDTO = z @@ -14,12 +14,17 @@ export const NextPathDTO = z export type NextPath = z.infer; -export const NextManyCommandDTO = z.object({ - listen: z.literal(true), +export const NextBranchesDTO = z.object({ defaultTo: TransferDTO, - to: z.array(MatchedTransferDTO), + to: z.array(ConditionalTransferDTO), +}); + +export type NextBranches = z.infer; + +export const NextManyCommandDTO = NextBranchesDTO.extend({ + listen: z.literal(true), }); -export const NextCommandDTO = NextPathDTO; +export const NextCommandDTO = z.union([NextPathDTO, NextManyCommandDTO]); export type NextCommand = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts b/runtime/lib/Handlers/function/runtime-command/transfer/conditional-transfer.dto.ts similarity index 72% rename from runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts rename to runtime/lib/Handlers/function/runtime-command/transfer/conditional-transfer.dto.ts index 71adfee4e..6d7c35020 100644 --- a/runtime/lib/Handlers/function/runtime-command/transfer/matched-transfer.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/transfer/conditional-transfer.dto.ts @@ -2,11 +2,11 @@ import { z } from 'zod'; import { TransferDTO } from './transfer.dto'; -export const MatchedTransferDTO = z.object({ +export const ConditionalTransferDTO = z.object({ on: z.record(z.any()).describe('An underscore-query matching criteria object'), dest: z .union([z.string(), TransferDTO]) .describe('If `string`, then this is a path transfer. Otherwise, it is an object specifying the kind of transfer'), }); -export type MatchedTransfer = z.infer; +export type ConditionalTransfer = z.infer; diff --git a/typings/undescore-query.d.ts b/typings/undescore-query.d.ts new file mode 100644 index 000000000..5cf7a61ed --- /dev/null +++ b/typings/undescore-query.d.ts @@ -0,0 +1,7 @@ +declare module 'underscore-query' { + // Need to use this `import` syntax so this is treated as a proper ambient module by TypeScript + // see: https://stackoverflow.com/questions/39040108/import-class-in-definition-file-d-ts + declare function lodashModifier(lodash: typeof import('lodash')): void; + + export default lodashModifier; +} diff --git a/yarn.lock b/yarn.lock index 15969745f..474775bd2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4723,6 +4723,7 @@ __metadata: typedoc: ^0.20.16 typedoc-plugin-sourcefile-url: ^1.0.6 typescript: 4.9.3 + underscore-query: ^3.3.2 unleash-client: 5.0.0 validator: ^13.7.0 words-to-numbers: ^1.5.1 @@ -17486,6 +17487,13 @@ __metadata: languageName: node linkType: hard +"underscore-query@npm:^3.3.2": + version: 3.3.2 + resolution: "underscore-query@npm:3.3.2" + checksum: 78b8944f2cff77e6400a33297a5f763f2f260a6eac648d97b985272b6695b47198652a6cc8ac100090778cdd225f37c0fdcb535232019992075e811294dee3a1 + languageName: node + linkType: hard + "undici-types@npm:~5.26.4": version: 5.26.5 resolution: "undici-types@npm:5.26.5" From 8c873a77ec3e9f4053ee0304879c3952dcc495b8 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Thu, 28 Mar 2024 12:11:20 -0400 Subject: [PATCH 04/12] refactor: changing types and fixing build issues --- runtime/lib/Handlers/function/index.ts | 36 +++++++---------- .../function/lib/event/event.types.ts | 39 +++++++++++++++++++ .../button/action-button.dto.ts | 4 +- .../button/button-type.enum.ts | 4 ++ .../button/general-button.dto.ts | 4 ++ .../function/runtime-command/constants.ts | 2 +- 6 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 runtime/lib/Handlers/function/lib/event/event.types.ts create mode 100644 runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index a59b5bd1b..0421b8a0b 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -9,7 +9,7 @@ import { NodeType, } from '@voiceflow/dtos'; import { NotImplementedException } from '@voiceflow/exception'; -import { isIntentRequest } from '@voiceflow/utils-designer'; +import { isIntentRequest, isTextRequest } from '@voiceflow/utils-designer'; import { VoiceflowConstants } from '@voiceflow/voiceflow-types'; import _ from 'lodash'; import lodashModifier from 'underscore-query'; @@ -18,6 +18,7 @@ import { HandlerFactory } from '@/runtime/lib/Handler'; import Runtime from '../../Runtime'; import Store from '../../Runtime/Store'; +import { EventType, FunctionRequestContext } from './lib/event/event.types'; import { executeFunction } from './lib/execute-function/execute-function'; import { fromFunctionGeneralButtonName } from './lib/execute-function/lib/adapt-trace'; import { createFunctionExceptionDebugTrace } from './lib/function-exception/function.exception'; @@ -91,24 +92,6 @@ function applyTransfer(transfer: string | Transfer, paths: FunctionCompiledInvoc throw new Error(`Function produced a transfer object with an unexpected type '${transfer.type}'`); } -interface FunctionRequestContext { - event?: { - code: string; // user-defined button type - }; - intent?: { - name: string; - confidence?: number; - entities: Record< - string, - { - name: string; - value: string; - } - >; - utterance?: string; - }; -} - function handleListenResponse( conditionalTransfers: NextBranches, requestContext: FunctionRequestContext, @@ -138,7 +121,8 @@ function createFunctionRequestContext(runtime: Runtime): FunctionRequestContext } = request.payload; return { - intent: { + event: { + type: EventType.INTENT, name, confidence, entities: Object.fromEntries(entities.map((ent) => [ent.name, { name: ent.name, value: ent.value }])), @@ -150,7 +134,17 @@ function createFunctionRequestContext(runtime: Runtime): FunctionRequestContext if (isGeneralRequest(request)) { return { event: { - code: fromFunctionGeneralButtonName(request.type), + type: EventType.GENERAL, + name: fromFunctionGeneralButtonName(request.type), + }, + }; + } + + if (isTextRequest(request)) { + return { + event: { + type: EventType.TEXT, + value: request.payload, }, }; } diff --git a/runtime/lib/Handlers/function/lib/event/event.types.ts b/runtime/lib/Handlers/function/lib/event/event.types.ts new file mode 100644 index 000000000..2e4e7eda4 --- /dev/null +++ b/runtime/lib/Handlers/function/lib/event/event.types.ts @@ -0,0 +1,39 @@ +export enum EventType { + GENERAL = 'general', + INTENT = 'intent', + TEXT = 'text', +} + +export interface BaseEvent { + type: EventType; +} + +export interface GeneralEvent extends BaseEvent { + type: EventType.GENERAL; + name: string; +} + +export interface IntentEvent extends BaseEvent { + type: EventType.INTENT; + name: string; + confidence?: number; + entities: Record< + string, + { + name: string; + value: string; + } + >; + utterance?: string; +} + +export interface TextEvent extends BaseEvent { + type: EventType.TEXT; + value: string; +} + +export type Event = GeneralEvent | IntentEvent | TextEvent; + +export interface FunctionRequestContext { + event?: Event; +} diff --git a/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts index 396c630ee..582834483 100644 --- a/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts @@ -1,6 +1,8 @@ import { BaseRequest } from '@voiceflow/base-types'; import { z } from 'zod'; +import { ButtonType } from './button-type.enum'; + export const SimpleURLActionDTO = z.object({ type: z.literal(BaseRequest.Action.ActionType.OPEN_URL), url: z.string(), @@ -16,7 +18,7 @@ export const SimpleActionButtonDTO = z.object({ name: z.string().describe('Text for the button UI'), payload: z.object({ type: z - .literal('action') + .literal(ButtonType.ACTION) .optional() .describe('Type of the button. Optional due to backwards compatibility reasons'), actions: z.array(SimpleActionDTO), diff --git a/runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts b/runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts new file mode 100644 index 000000000..ea6da9333 --- /dev/null +++ b/runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts @@ -0,0 +1,4 @@ +export enum ButtonType { + GENERAL = 'general', + ACTION = 'action', +} diff --git a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts index 1be9098fe..4b487427a 100644 --- a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts @@ -1,10 +1,14 @@ import { z } from 'zod'; +import { constraints } from '../constants'; +import { ButtonType } from './button-type.enum'; + const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z][\dA-Za-z]*$/; export const SimpleGeneralButtonDTO = z.object({ name: z.string().describe('Text for the button UI'), payload: z.object({ + type: z.literal(ButtonType.GENERAL), code: z .string() .max(constraints.MAX_SMALL_STRING_LENGTH) diff --git a/runtime/lib/Handlers/function/runtime-command/constants.ts b/runtime/lib/Handlers/function/runtime-command/constants.ts index 743024e9c..800c85742 100644 --- a/runtime/lib/Handlers/function/runtime-command/constants.ts +++ b/runtime/lib/Handlers/function/runtime-command/constants.ts @@ -1,3 +1,3 @@ -const constraints = { +export const constraints = { MAX_SMALL_STRING_LENGTH: 128, } as const; From 45ec35f7e11ee3055f3d82c798963022d387868b Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Thu, 28 Mar 2024 14:21:06 -0400 Subject: [PATCH 05/12] fix: displaying button trace on prototype tool --- runtime/lib/Handlers/function/index.ts | 5 ++++- .../function/lib/execute-function/lib/adapt-trace.ts | 2 +- .../function/lib/execute-function/lib/validate-next.ts | 5 +++-- .../function/runtime-command/button/general-button.dto.ts | 2 +- .../Handlers/function/runtime-command/trace-command.dto.ts | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index 0421b8a0b..6c3f5297d 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -67,9 +67,12 @@ function applyNextCommand( runtime: Runtime, { nodeId, paths }: { nodeId: string; paths: FunctionCompiledInvocation['paths'] } ): string | null { - if ('listen' in command && command.listen) { + if ('listen' in command) { + if (!command.listen) return null; + const { defaultTo, to } = command; runtime.variables.set(VoiceflowConstants.BuiltInVariable.FUNCTION_CONDITIONAL_TRANSFERS, { defaultTo, to }); + return nodeId; } if ('path' in command) { diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts index a27d00c3a..aa9e5ab41 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts @@ -6,7 +6,7 @@ import { SimpleGeneralButton } from '../../../runtime-command/button/general-but import { SimpleCard } from '../../../runtime-command/card/card.dto'; import { SimpleAudioTrace } from '../../../runtime-command/trace/audio.dto'; import { Trace } from '../../../runtime-command/trace/base.dto'; -import { SimpleCardV2Trace } from '../../../runtime-command/trace/cardv2.dto'; +import { SimpleCardV2Trace } from '../../../runtime-command/trace/cardV2.dto'; import { SimpleCarouselTrace } from '../../../runtime-command/trace/carousel.dto'; import { SimpleChoiceTrace } from '../../../runtime-command/trace/choice.dto'; import { SimpleTraceType } from '../../../runtime-command/trace/simple-trace-type.enum'; diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts index 3367941d9..104514330 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-next.ts @@ -2,7 +2,8 @@ import { NextCommand, NextPathDTO } from '../../../runtime-command/next-command. import { FunctionPathException } from '../exceptions/function-path.exception'; export function validateNext(next: NextCommand, expectedPathCodes: Array) { - if (NextPathDTO.safeParse(next).success && !expectedPathCodes.includes(next.path)) { - throw new FunctionPathException(next.path, expectedPathCodes); + const parsedNextPath = NextPathDTO.safeParse(next); + if (parsedNextPath.success && !expectedPathCodes.includes(parsedNextPath.data.path)) { + throw new FunctionPathException(parsedNextPath.data.path, expectedPathCodes); } } diff --git a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts index 4b487427a..ca3e4548a 100644 --- a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { constraints } from '../constants'; import { ButtonType } from './button-type.enum'; -const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z][\dA-Za-z]*$/; +const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z]\w*$/; export const SimpleGeneralButtonDTO = z.object({ name: z.string().describe('Text for the button UI'), diff --git a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts index 7de9e4b4e..ac16c177e 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { SimpleAudioTraceDTO } from './trace/audio.dto'; import { TraceDTO } from './trace/base.dto'; -import { SimpleCardV2TraceDTO } from './trace/cardv2.dto'; +import { SimpleCardV2TraceDTO } from './trace/cardV2.dto'; import { SimpleCarouselTraceDTO } from './trace/carousel.dto'; import { SimpleChoiceTraceDTO } from './trace/choice.dto'; import { SimpleDebugTraceDTO } from './trace/debug.dto'; From e86d371b892e1249e5cfccc5c12b150b65a4c8e8 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Thu, 28 Mar 2024 14:57:00 -0400 Subject: [PATCH 06/12] refactor: added global module declaration to lodash for underscore-query --- .../runtime/handlers/state/preliminary/index.ts | 3 ++- runtime/lib/Handlers/function/index.ts | 4 +--- typings/lodash.d.ts | 13 +++++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 typings/lodash.d.ts diff --git a/lib/services/runtime/handlers/state/preliminary/index.ts b/lib/services/runtime/handlers/state/preliminary/index.ts index 1fd78deda..da5cb8b5d 100644 --- a/lib/services/runtime/handlers/state/preliminary/index.ts +++ b/lib/services/runtime/handlers/state/preliminary/index.ts @@ -1,6 +1,6 @@ import { VoiceflowNode } from '@voiceflow/voiceflow-types'; -import { Action, Handler, HandlerFactory, IfV2Handler } from '@/runtime'; +import { Action, FunctionHandler, Handler, HandlerFactory, IfV2Handler } from '@/runtime'; import { isAlexaEventIntentRequest } from '../../../types'; import _V1Handler from '../../_v1'; @@ -14,6 +14,7 @@ import InteractionHandler from '../../interaction'; const _v1Handler = _V1Handler(); export const eventHandlers = [ + FunctionHandler(), ...GoToHandler(), CaptureHandler(), ...CaptureV2Handler(), diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index 6c3f5297d..c4c0dafc3 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -101,9 +101,7 @@ function handleListenResponse( paths: FunctionCompiledInvocation['paths'] ): string { // !TODO! - Remove the `any` cast here - const firstMatchingTransfer = conditionalTransfers.to.find( - (item) => (_ as any).query([requestContext], item.on).length > 0 - ); + const firstMatchingTransfer = conditionalTransfers.to.find((item) => _.query([requestContext], item.on).length > 0); if (!firstMatchingTransfer) { return applyTransfer(conditionalTransfers.defaultTo, paths); diff --git a/typings/lodash.d.ts b/typings/lodash.d.ts new file mode 100644 index 000000000..cb2ac2cf9 --- /dev/null +++ b/typings/lodash.d.ts @@ -0,0 +1,13 @@ +declare module 'lodash' { + /** + * The `query` function filters the `collection` based on the given `criteria`. + * + * This `_.query()` function is injected into the lodash object dynamically by the + * `underscore-query` library. + * + * See: https://www.npmjs.com/package/underscore-query + * + * !TODO! - Provide more specific typing on the `criteria` for better type-safety. + */ + declare function query(collection: T[], criteria: Record): T[]; +} From 65aba5bac389a67ebbd142fbdb38b0a7971be1a6 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Thu, 28 Mar 2024 16:45:28 -0400 Subject: [PATCH 07/12] docs: remove comment --- runtime/lib/Handlers/function/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index c4c0dafc3..4c698f025 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -100,7 +100,6 @@ function handleListenResponse( requestContext: FunctionRequestContext, paths: FunctionCompiledInvocation['paths'] ): string { - // !TODO! - Remove the `any` cast here const firstMatchingTransfer = conditionalTransfers.to.find((item) => _.query([requestContext], item.on).length > 0); if (!firstMatchingTransfer) { From 43ecdbbeb33b77954f886af37bdaf787c35af9f6 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Thu, 28 Mar 2024 16:54:08 -0400 Subject: [PATCH 08/12] refactor: move utility functions to appropriate files --- runtime/lib/Handlers/function/index.ts | 56 +------------------ .../function/lib/event/event.types.ts | 4 -- .../lib/request-context/request-context.ts | 55 ++++++++++++++++++ utils/underscore-query.ts | 6 ++ 4 files changed, 64 insertions(+), 57 deletions(-) create mode 100644 runtime/lib/Handlers/function/lib/request-context/request-context.ts create mode 100644 utils/underscore-query.ts diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index 4c698f025..4f799a8cd 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -1,5 +1,4 @@ import { BaseTrace } from '@voiceflow/base-types'; -import { isGeneralRequest } from '@voiceflow/base-types/build/cjs/request'; import { BaseTraceFrame } from '@voiceflow/base-types/build/cjs/trace'; import { replaceVariables } from '@voiceflow/common'; import { @@ -8,27 +7,21 @@ import { FunctionCompiledNode, NodeType, } from '@voiceflow/dtos'; -import { NotImplementedException } from '@voiceflow/exception'; -import { isIntentRequest, isTextRequest } from '@voiceflow/utils-designer'; import { VoiceflowConstants } from '@voiceflow/voiceflow-types'; -import _ from 'lodash'; -import lodashModifier from 'underscore-query'; +import _query from 'utils/underscore-query'; import { HandlerFactory } from '@/runtime/lib/Handler'; import Runtime from '../../Runtime'; import Store from '../../Runtime/Store'; -import { EventType, FunctionRequestContext } from './lib/event/event.types'; import { executeFunction } from './lib/execute-function/execute-function'; -import { fromFunctionGeneralButtonName } from './lib/execute-function/lib/adapt-trace'; import { createFunctionExceptionDebugTrace } from './lib/function-exception/function.exception'; +import { createFunctionRequestContext, FunctionRequestContext } from './lib/request-context/request-context'; import { NextBranches, NextBranchesDTO, NextCommand } from './runtime-command/next-command.dto'; import { OutputVarsCommand } from './runtime-command/output-vars-command.dto'; import { TraceCommand } from './runtime-command/trace-command.dto'; import { Transfer, TransferType } from './runtime-command/transfer/transfer.dto'; -lodashModifier(_); - const utilsObj = { replaceVariables, }; @@ -100,7 +93,7 @@ function handleListenResponse( requestContext: FunctionRequestContext, paths: FunctionCompiledInvocation['paths'] ): string { - const firstMatchingTransfer = conditionalTransfers.to.find((item) => _.query([requestContext], item.on).length > 0); + const firstMatchingTransfer = conditionalTransfers.to.find((item) => _query([requestContext], item.on).length > 0); if (!firstMatchingTransfer) { return applyTransfer(conditionalTransfers.defaultTo, paths); @@ -109,49 +102,6 @@ function handleListenResponse( return applyTransfer(firstMatchingTransfer.dest, paths); } -function createFunctionRequestContext(runtime: Runtime): FunctionRequestContext { - const request = runtime.getRequest(); - - if (isIntentRequest(request)) { - const { - intent: { name }, - confidence, - entities = [], - query, - } = request.payload; - - return { - event: { - type: EventType.INTENT, - name, - confidence, - entities: Object.fromEntries(entities.map((ent) => [ent.name, { name: ent.name, value: ent.value }])), - utterance: query, - }, - }; - } - - if (isGeneralRequest(request)) { - return { - event: { - type: EventType.GENERAL, - name: fromFunctionGeneralButtonName(request.type), - }, - }; - } - - if (isTextRequest(request)) { - return { - event: { - type: EventType.TEXT, - value: request.payload, - }, - }; - } - - throw new NotImplementedException('Function received an unexpected request type'); -} - export const FunctionHandler: HandlerFactory = (utils) => ({ canHandle: (node) => node.type === NodeType.FUNCTION, diff --git a/runtime/lib/Handlers/function/lib/event/event.types.ts b/runtime/lib/Handlers/function/lib/event/event.types.ts index 2e4e7eda4..56267e3ec 100644 --- a/runtime/lib/Handlers/function/lib/event/event.types.ts +++ b/runtime/lib/Handlers/function/lib/event/event.types.ts @@ -33,7 +33,3 @@ export interface TextEvent extends BaseEvent { } export type Event = GeneralEvent | IntentEvent | TextEvent; - -export interface FunctionRequestContext { - event?: Event; -} diff --git a/runtime/lib/Handlers/function/lib/request-context/request-context.ts b/runtime/lib/Handlers/function/lib/request-context/request-context.ts new file mode 100644 index 000000000..3dd139908 --- /dev/null +++ b/runtime/lib/Handlers/function/lib/request-context/request-context.ts @@ -0,0 +1,55 @@ +import { isGeneralRequest } from '@voiceflow/base-types/build/cjs/request'; +import { NotImplementedException } from '@voiceflow/exception'; +import { isIntentRequest, isTextRequest } from '@voiceflow/utils-designer'; + +import Runtime from '@/runtime/lib/Runtime'; + +import { Event, EventType } from '../event/event.types'; +import { fromFunctionGeneralButtonName } from '../execute-function/lib/adapt-trace'; + +export interface FunctionRequestContext { + event?: Event; +} + +export function createFunctionRequestContext(runtime: Runtime): FunctionRequestContext { + const request = runtime.getRequest(); + + if (isIntentRequest(request)) { + const { + intent: { name }, + confidence, + entities = [], + query, + } = request.payload; + + return { + event: { + type: EventType.INTENT, + name, + confidence, + entities: Object.fromEntries(entities.map((ent) => [ent.name, { name: ent.name, value: ent.value }])), + utterance: query, + }, + }; + } + + if (isGeneralRequest(request)) { + return { + event: { + type: EventType.GENERAL, + name: fromFunctionGeneralButtonName(request.type), + }, + }; + } + + if (isTextRequest(request)) { + return { + event: { + type: EventType.TEXT, + value: request.payload, + }, + }; + } + + throw new NotImplementedException('Function received an unexpected request type'); +} diff --git a/utils/underscore-query.ts b/utils/underscore-query.ts new file mode 100644 index 000000000..a174411ec --- /dev/null +++ b/utils/underscore-query.ts @@ -0,0 +1,6 @@ +import _ from 'lodash'; +import lodashModifier from 'underscore-query'; + +lodashModifier(_); + +export default _.query; From b595678abe1ee074bba2132b08215b50ba80ef07 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Tue, 2 Apr 2024 16:29:15 -0400 Subject: [PATCH 09/12] fix: build issues --- lib/services/test/index.ts | 4 ++-- package.json | 2 +- .../lib/execute-function/lib/adapt-trace.ts | 18 +++++++++--------- .../execute-function/lib/is-simple-trace.ts | 4 ++-- .../lib/execute-function/lib/validate-trace.ts | 4 ++-- .../function-exception/function.exception.ts | 4 ++-- .../runtime-command/trace-command.dto.ts | 4 ++-- .../runtime-command/trace/audio.dto.ts | 4 ++-- .../function/runtime-command/trace/base.dto.ts | 4 ++-- .../runtime-command/trace/cardV2.dto.ts | 4 ++-- .../runtime-command/trace/carousel.dto.ts | 4 ++-- .../runtime-command/trace/choice.dto.ts | 4 ++-- .../runtime-command/trace/debug.dto.ts | 4 ++-- .../runtime-command/trace/speak.dto.ts | 4 ++-- .../function/runtime-command/trace/text.dto.ts | 4 ++-- .../runtime-command/trace/visual.dto.ts | 4 ++-- typings/lodash.d.ts | 13 ------------- utils/underscore-query.ts | 5 ++++- yarn.lock | 13 ++++++++++++- 19 files changed, 54 insertions(+), 53 deletions(-) delete mode 100644 typings/lodash.d.ts diff --git a/lib/services/test/index.ts b/lib/services/test/index.ts index 922a69c46..93c6d2259 100644 --- a/lib/services/test/index.ts +++ b/lib/services/test/index.ts @@ -3,7 +3,7 @@ import { performance } from 'perf_hooks'; import { executeFunction } from '@/runtime/lib/Handlers/function/lib/execute-function/execute-function'; import { createFunctionExceptionDebugTrace } from '@/runtime/lib/Handlers/function/lib/function-exception/function.exception'; -import { Trace } from '@/runtime/lib/Handlers/function/runtime-command/trace-command.dto'; +import { UnknownTrace } from '@/runtime/lib/Handlers/function/runtime-command/trace/base.dto'; import { AbstractManager } from '../utils'; import { TestFunctionResponse } from './interface'; @@ -43,7 +43,7 @@ export class TestService extends AbstractManager { const executionTime = endTime - startTime; - const debugTrace: Trace = createFunctionExceptionDebugTrace(err); + const debugTrace: UnknownTrace = createFunctionExceptionDebugTrace(err); return { success: false, diff --git a/package.json b/package.json index 983c0755f..fcc5a7fca 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@voiceflow/utils-designer": "1.9.3", "@voiceflow/verror": "^1.1.3", "@voiceflow/voice-types": "2.9.83", - "@voiceflow/voiceflow-types": "3.27.0", + "@voiceflow/voiceflow-types": "3.28.0", "ajv": "6.12.3", "axios": "^0.21.1", "compression": "^1.7.4", diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts index aa9e5ab41..62aebd21b 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts @@ -5,7 +5,7 @@ import { SimpleAction, SimpleActionButton } from '../../../runtime-command/butto import { SimpleGeneralButton } from '../../../runtime-command/button/general-button.dto'; import { SimpleCard } from '../../../runtime-command/card/card.dto'; import { SimpleAudioTrace } from '../../../runtime-command/trace/audio.dto'; -import { Trace } from '../../../runtime-command/trace/base.dto'; +import { UnknownTrace } from '../../../runtime-command/trace/base.dto'; import { SimpleCardV2Trace } from '../../../runtime-command/trace/cardV2.dto'; import { SimpleCarouselTrace } from '../../../runtime-command/trace/carousel.dto'; import { SimpleChoiceTrace } from '../../../runtime-command/trace/choice.dto'; @@ -18,7 +18,7 @@ import { isSimpleTrace } from './is-simple-trace'; const { cuid } = Utils.id; const { TraceType } = BaseTrace; -const adaptTextTrace = (trace: SimpleTextTrace): Trace => { +const adaptTextTrace = (trace: SimpleTextTrace): UnknownTrace => { return { ...trace, type: TraceType.TEXT, @@ -32,7 +32,7 @@ const adaptTextTrace = (trace: SimpleTextTrace): Trace => { } satisfies BaseTrace.TextTrace; }; -const adaptSpeakTrace = (trace: SimpleSpeakTrace): Trace => { +const adaptSpeakTrace = (trace: SimpleSpeakTrace): UnknownTrace => { return { ...trace, type: TraceType.SPEAK, @@ -43,7 +43,7 @@ const adaptSpeakTrace = (trace: SimpleSpeakTrace): Trace => { } satisfies BaseTrace.SpeakTrace; }; -const adaptAudioTrace = (trace: SimpleAudioTrace): Trace => { +const adaptAudioTrace = (trace: SimpleAudioTrace): UnknownTrace => { return { ...trace, type: TraceType.SPEAK, @@ -54,7 +54,7 @@ const adaptAudioTrace = (trace: SimpleAudioTrace): Trace => { } satisfies BaseTrace.SpeakTrace; }; -const adaptVisualTrace = (trace: SimpleVisualTrace): Trace => { +const adaptVisualTrace = (trace: SimpleVisualTrace): UnknownTrace => { return { ...trace, type: TraceType.VISUAL, @@ -131,7 +131,7 @@ const adaptCard = (card: SimpleCard): BaseNode.Carousel.TraceCarouselCard => { }; }; -const adaptCarouselTrace = (trace: SimpleCarouselTrace): Trace => { +const adaptCarouselTrace = (trace: SimpleCarouselTrace): UnknownTrace => { return { ...trace, type: TraceType.CAROUSEL, @@ -143,7 +143,7 @@ const adaptCarouselTrace = (trace: SimpleCarouselTrace): Trace => { } satisfies BaseTrace.CarouselTrace; }; -const adaptCardV2Trace = (trace: SimpleCardV2Trace): Trace => { +const adaptCardV2Trace = (trace: SimpleCardV2Trace): UnknownTrace => { return { ...trace, type: TraceType.CARD_V2, @@ -154,7 +154,7 @@ const adaptCardV2Trace = (trace: SimpleCardV2Trace): Trace => { } satisfies BaseTrace.CardV2; }; -const adaptChoiceTrace = (trace: SimpleChoiceTrace): Trace => { +const adaptChoiceTrace = (trace: SimpleChoiceTrace): UnknownTrace => { return { ...trace, type: TraceType.CHOICE, @@ -165,7 +165,7 @@ const adaptChoiceTrace = (trace: SimpleChoiceTrace): Trace => { } satisfies BaseTrace.Choice; }; -export function adaptTrace(trace: Trace): Trace { +export function adaptTrace(trace: UnknownTrace): UnknownTrace { if (!isSimpleTrace(trace)) return trace; switch (trace.type) { diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts index 7dbe255d5..b76859f17 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/is-simple-trace.ts @@ -1,8 +1,8 @@ -import { Trace } from '../../../runtime-command/trace/base.dto'; +import { UnknownTrace } from '../../../runtime-command/trace/base.dto'; import { SimpleTraceType } from '../../../runtime-command/trace/simple-trace-type.enum'; import { SimpleTrace, SimpleTraceDTO } from '../../../runtime-command/trace-command.dto'; -export const isSimpleTrace = (trace: Trace): trace is SimpleTrace => SimpleTraceDTO.safeParse(trace).success; +export const isSimpleTrace = (trace: UnknownTrace): trace is SimpleTrace => SimpleTraceDTO.safeParse(trace).success; const simpleTraceTypes = new Set(Object.values(SimpleTraceType)); diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts index 673134081..6a155ae44 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/validate-trace.ts @@ -1,10 +1,10 @@ import { InvalidRuntimeCommandException } from '@/runtime/lib/HTTPClient/function-lambda/exceptions/invalid-runtime-command.exception'; -import { Trace } from '../../../runtime-command/trace/base.dto'; +import { UnknownTrace } from '../../../runtime-command/trace/base.dto'; import { SimpleTraceDTO } from '../../../runtime-command/trace-command.dto'; import { isSimpleTraceType } from './is-simple-trace'; -export function parseTrace(trace: Trace): Trace { +export function parseTrace(trace: UnknownTrace): UnknownTrace { if (isSimpleTraceType(trace.type)) { try { return SimpleTraceDTO.parse(trace); diff --git a/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts b/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts index 6a9e36ffe..2c0dbef35 100644 --- a/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts +++ b/runtime/lib/Handlers/function/lib/function-exception/function.exception.ts @@ -2,13 +2,13 @@ import { BaseNode } from '@voiceflow/base-types'; import { HTTPException } from '@voiceflow/exception'; import { match } from 'ts-pattern'; -import { Trace } from '../../runtime-command/trace/base.dto'; +import { UnknownTrace } from '../../runtime-command/trace/base.dto'; export abstract class FunctionException extends Error { abstract get message(): string; } -export function createFunctionExceptionDebugTrace(err: unknown): Trace { +export function createFunctionExceptionDebugTrace(err: unknown): UnknownTrace { const debugMessage = match(err) .when( (val): val is Error => val instanceof Error, diff --git a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts index ac16c177e..255013fd0 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace-command.dto.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { SimpleAudioTraceDTO } from './trace/audio.dto'; -import { TraceDTO } from './trace/base.dto'; +import { UnknownTraceDTO } from './trace/base.dto'; import { SimpleCardV2TraceDTO } from './trace/cardV2.dto'; import { SimpleCarouselTraceDTO } from './trace/carousel.dto'; import { SimpleChoiceTraceDTO } from './trace/choice.dto'; @@ -10,7 +10,7 @@ import { SimpleSpeakTraceDTO } from './trace/speak.dto'; import { SimpleTextTraceDTO } from './trace/text.dto'; import { SimpleVisualTraceDTO } from './trace/visual.dto'; -export const TraceCommandDTO = z.array(TraceDTO, { +export const TraceCommandDTO = z.array(UnknownTraceDTO, { invalid_type_error: 'A trace command must be a list of valid Voiceflow trace types', }); diff --git a/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts index cd20ed32d..0948d47e9 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/audio.dto.ts @@ -1,9 +1,9 @@ import { z } from 'zod'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleAudioTraceDTO = TraceDTO.extend({ +export const SimpleAudioTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Audio), payload: z.object({ src: z.string().optional(), diff --git a/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts index f8dbc2414..6271b1c89 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/base.dto.ts @@ -1,6 +1,6 @@ import { z } from 'zod'; -export const TraceDTO = z +export const UnknownTraceDTO = z .object({ type: z.string({ required_error: `A Voiceflow trace must define a 'type' property`, @@ -10,4 +10,4 @@ export const TraceDTO = z }) .passthrough(); -export type Trace = z.infer; +export type UnknownTrace = z.infer; diff --git a/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts index 97e25110a..2e07c2d4c 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/cardV2.dto.ts @@ -1,10 +1,10 @@ import { z } from 'zod'; import { SimpleCardDTO } from '../card/card.dto'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleCardV2TraceDTO = TraceDTO.extend({ +export const SimpleCardV2TraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.CardV2), payload: SimpleCardDTO, }).passthrough(); diff --git a/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts index 3c3fb6427..df9962f55 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/carousel.dto.ts @@ -2,10 +2,10 @@ import { BaseNode } from '@voiceflow/base-types'; import { z } from 'zod'; import { SimpleCardDTO } from '../card/card.dto'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleCarouselTraceDTO = TraceDTO.extend({ +export const SimpleCarouselTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Carousel), payload: z.object({ layout: z.nativeEnum(BaseNode.Carousel.CarouselLayout).optional(), diff --git a/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts index 40b09e745..7f84faa35 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/choice.dto.ts @@ -1,10 +1,10 @@ import { z } from 'zod'; import { SimpleGeneralButtonDTO } from '../button/general-button.dto'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleChoiceTraceDTO = TraceDTO.extend({ +export const SimpleChoiceTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Choice), payload: z.object({ buttons: z.array(SimpleGeneralButtonDTO), diff --git a/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts index f0c3c4f40..8de07ea70 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/debug.dto.ts @@ -1,9 +1,9 @@ import { z } from 'zod'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleDebugTraceDTO = TraceDTO.extend({ +export const SimpleDebugTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Debug), payload: z.object({ message: z.string(), diff --git a/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts index 43ee9be69..4264d89c5 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/speak.dto.ts @@ -1,9 +1,9 @@ import { z } from 'zod'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleSpeakTraceDTO = TraceDTO.extend({ +export const SimpleSpeakTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Speak), payload: z.object({ message: z.string(), diff --git a/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts index 3ccc5474d..af659c1b2 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/text.dto.ts @@ -1,9 +1,9 @@ import { z } from 'zod'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleTextTraceDTO = TraceDTO.extend({ +export const SimpleTextTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Text), payload: z.object({ message: z.string(), diff --git a/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts b/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts index 7e3a3d8d4..ea290831e 100644 --- a/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/trace/visual.dto.ts @@ -1,9 +1,9 @@ import { z } from 'zod'; -import { TraceDTO } from './base.dto'; +import { UnknownTraceDTO } from './base.dto'; import { SimpleTraceType } from './simple-trace-type.enum'; -export const SimpleVisualTraceDTO = TraceDTO.extend({ +export const SimpleVisualTraceDTO = UnknownTraceDTO.extend({ type: z.literal(SimpleTraceType.Visual), payload: z.object({ image: z.string(), diff --git a/typings/lodash.d.ts b/typings/lodash.d.ts deleted file mode 100644 index cb2ac2cf9..000000000 --- a/typings/lodash.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -declare module 'lodash' { - /** - * The `query` function filters the `collection` based on the given `criteria`. - * - * This `_.query()` function is injected into the lodash object dynamically by the - * `underscore-query` library. - * - * See: https://www.npmjs.com/package/underscore-query - * - * !TODO! - Provide more specific typing on the `criteria` for better type-safety. - */ - declare function query(collection: T[], criteria: Record): T[]; -} diff --git a/utils/underscore-query.ts b/utils/underscore-query.ts index a174411ec..bbe0d942f 100644 --- a/utils/underscore-query.ts +++ b/utils/underscore-query.ts @@ -3,4 +3,7 @@ import lodashModifier from 'underscore-query'; lodashModifier(_); -export default _.query; +// !TODO! - There must be a better way to type this. +const query = (collection: T[], criteria: Record): T[] => (_ as any).query(collection, criteria); + +export default query; diff --git a/yarn.lock b/yarn.lock index 474775bd2..86625745b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4658,7 +4658,7 @@ __metadata: "@voiceflow/utils-designer": 1.9.3 "@voiceflow/verror": ^1.1.3 "@voiceflow/voice-types": 2.9.83 - "@voiceflow/voiceflow-types": 3.27.0 + "@voiceflow/voiceflow-types": 3.28.0 ajv: 6.12.3 axios: ^0.21.1 chai: ^4.2.0 @@ -5107,6 +5107,17 @@ __metadata: languageName: node linkType: hard +"@voiceflow/voiceflow-types@npm:3.28.0": + version: 3.28.0 + resolution: "@voiceflow/voiceflow-types@npm:3.28.0" + dependencies: + "@voiceflow/base-types": 2.106.0 + "@voiceflow/chat-types": 2.13.104 + "@voiceflow/voice-types": 2.9.83 + checksum: 50b7c82d8dfe52b6a6c83ff62585f7c64137b47cd8582af95acdd8ad7243c23d7db0f05cad2fa622e4d2ae1583b11dbf0925197a66bb363d84d9225da1c8b162 + languageName: node + linkType: hard + "@vue/compiler-core@npm:3.4.15": version: 3.4.15 resolution: "@vue/compiler-core@npm:3.4.15" From 25d95f44c53c24ca75497731ccd5997f079baa66 Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Tue, 2 Apr 2024 16:59:03 -0400 Subject: [PATCH 10/12] feat: rework to use original request types --- .../function/lib/event/event.types.ts | 35 ----------------- .../lib/execute-function/lib/adapt-trace.ts | 16 +------- .../lib/request-context/request-context.ts | 39 +------------------ .../button/general-button.dto.ts | 17 ++------ 4 files changed, 7 insertions(+), 100 deletions(-) delete mode 100644 runtime/lib/Handlers/function/lib/event/event.types.ts diff --git a/runtime/lib/Handlers/function/lib/event/event.types.ts b/runtime/lib/Handlers/function/lib/event/event.types.ts deleted file mode 100644 index 56267e3ec..000000000 --- a/runtime/lib/Handlers/function/lib/event/event.types.ts +++ /dev/null @@ -1,35 +0,0 @@ -export enum EventType { - GENERAL = 'general', - INTENT = 'intent', - TEXT = 'text', -} - -export interface BaseEvent { - type: EventType; -} - -export interface GeneralEvent extends BaseEvent { - type: EventType.GENERAL; - name: string; -} - -export interface IntentEvent extends BaseEvent { - type: EventType.INTENT; - name: string; - confidence?: number; - entities: Record< - string, - { - name: string; - value: string; - } - >; - utterance?: string; -} - -export interface TextEvent extends BaseEvent { - type: EventType.TEXT; - value: string; -} - -export type Event = GeneralEvent | IntentEvent | TextEvent; diff --git a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts index 62aebd21b..f7760c8b8 100644 --- a/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts +++ b/runtime/lib/Handlers/function/lib/execute-function/lib/adapt-trace.ts @@ -97,25 +97,11 @@ const adaptActionButton = (button: SimpleActionButton): BaseRequest.ActionReques }; }; -const functionButtonPrefix = `function-button:`; - -const toFunctionGeneralButtonName = (name: string) => { - return `${functionButtonPrefix}${name}`; -}; - -export const fromFunctionGeneralButtonName = (name: string) => { - if (!name.startsWith('function-button:')) { - throw new Error("failed to parse button name because it does not match the function's general button format"); - } - - return name.replace(functionButtonPrefix, ''); -}; - const adaptGeneralButton = (button: SimpleGeneralButton): BaseRequest.GeneralRequestButton => { return { name: button.name, request: { - type: toFunctionGeneralButtonName(button.payload.code), + type: button.request.type, payload: { label: button.name, }, diff --git a/runtime/lib/Handlers/function/lib/request-context/request-context.ts b/runtime/lib/Handlers/function/lib/request-context/request-context.ts index 3dd139908..4300b02ab 100644 --- a/runtime/lib/Handlers/function/lib/request-context/request-context.ts +++ b/runtime/lib/Handlers/function/lib/request-context/request-context.ts @@ -1,53 +1,18 @@ import { isGeneralRequest } from '@voiceflow/base-types/build/cjs/request'; import { NotImplementedException } from '@voiceflow/exception'; -import { isIntentRequest, isTextRequest } from '@voiceflow/utils-designer'; import Runtime from '@/runtime/lib/Runtime'; -import { Event, EventType } from '../event/event.types'; -import { fromFunctionGeneralButtonName } from '../execute-function/lib/adapt-trace'; - export interface FunctionRequestContext { - event?: Event; + event?: unknown; } export function createFunctionRequestContext(runtime: Runtime): FunctionRequestContext { const request = runtime.getRequest(); - if (isIntentRequest(request)) { - const { - intent: { name }, - confidence, - entities = [], - query, - } = request.payload; - - return { - event: { - type: EventType.INTENT, - name, - confidence, - entities: Object.fromEntries(entities.map((ent) => [ent.name, { name: ent.name, value: ent.value }])), - utterance: query, - }, - }; - } - if (isGeneralRequest(request)) { return { - event: { - type: EventType.GENERAL, - name: fromFunctionGeneralButtonName(request.type), - }, - }; - } - - if (isTextRequest(request)) { - return { - event: { - type: EventType.TEXT, - value: request.payload, - }, + event: request, }; } diff --git a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts index ca3e4548a..1dd139a79 100644 --- a/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/button/general-button.dto.ts @@ -1,20 +1,11 @@ +import { BaseRequestDTO } from '@voiceflow/dtos'; import { z } from 'zod'; -import { constraints } from '../constants'; -import { ButtonType } from './button-type.enum'; - -const FUNCTION_BUTTON_NAME_REGEX = /^[A-Z_a-z]\w*$/; - export const SimpleGeneralButtonDTO = z.object({ name: z.string().describe('Text for the button UI'), - payload: z.object({ - type: z.literal(ButtonType.GENERAL), - code: z - .string() - .max(constraints.MAX_SMALL_STRING_LENGTH) - .regex(FUNCTION_BUTTON_NAME_REGEX) - .describe('Defines the custom button request type'), - }), + request: BaseRequestDTO.passthrough().describe( + 'The request object that will be sent back to the `runtime` if the button is clicked' + ), }); export type SimpleGeneralButton = z.infer; From 84f5afb4238bed9cb9524295225ce457fb9b1b1e Mon Sep 17 00:00:00 2001 From: Brennan Lu Date: Wed, 3 Apr 2024 11:43:24 -0400 Subject: [PATCH 11/12] fix: not running default path properly --- runtime/lib/Handlers/function/index.ts | 1 - .../function/lib/request-context/request-context.ts | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/lib/Handlers/function/index.ts b/runtime/lib/Handlers/function/index.ts index 4f799a8cd..3afcbadc9 100644 --- a/runtime/lib/Handlers/function/index.ts +++ b/runtime/lib/Handlers/function/index.ts @@ -160,7 +160,6 @@ export const FunctionHandler: HandlerFactory Date: Wed, 3 Apr 2024 12:51:18 -0400 Subject: [PATCH 12/12] refactor: remove unnecessary button type enum --- .../function/runtime-command/button/action-button.dto.ts | 6 ------ .../function/runtime-command/button/button-type.enum.ts | 4 ---- 2 files changed, 10 deletions(-) delete mode 100644 runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts diff --git a/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts b/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts index 582834483..68631de0b 100644 --- a/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts +++ b/runtime/lib/Handlers/function/runtime-command/button/action-button.dto.ts @@ -1,8 +1,6 @@ import { BaseRequest } from '@voiceflow/base-types'; import { z } from 'zod'; -import { ButtonType } from './button-type.enum'; - export const SimpleURLActionDTO = z.object({ type: z.literal(BaseRequest.Action.ActionType.OPEN_URL), url: z.string(), @@ -17,10 +15,6 @@ export type SimpleAction = z.infer; export const SimpleActionButtonDTO = z.object({ name: z.string().describe('Text for the button UI'), payload: z.object({ - type: z - .literal(ButtonType.ACTION) - .optional() - .describe('Type of the button. Optional due to backwards compatibility reasons'), actions: z.array(SimpleActionDTO), }), }); diff --git a/runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts b/runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts deleted file mode 100644 index ea6da9333..000000000 --- a/runtime/lib/Handlers/function/runtime-command/button/button-type.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum ButtonType { - GENERAL = 'general', - ACTION = 'action', -}