diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 1bc2a7b..9ecb785 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,6 @@
# Release Notes
+- [Version 2.7.2](#v272)
- [Version 2.7.1](#v271)
- [Version 2.7.0](#v270)
- [Version 2.6.8](#v268)
@@ -20,6 +21,17 @@
- [Version 2.4.3](#v243)
- [Version 2.4.2](#v242)
+## Version 2.7.2
+
+### New Features
+- Added new CMM message types and properties
+
+### Fixed Issues
+
+- Removed logging that might disclose sensitive info
+- Fixed name of bag item disambiguateMessage event in TypeScript
+- Fixed issue with nested items not supported in entity item event in TypeScript
+
## Version 2.7.1
### Fixed Issues
diff --git a/lib/dataquery/utils.js b/lib/dataquery/utils.js
index 25f1d16..1210825 100644
--- a/lib/dataquery/utils.js
+++ b/lib/dataquery/utils.js
@@ -31,7 +31,6 @@ async function invokeDataQueryEventHandlers(component, context) {
// update row with formatted value if attribute is included in the row and has a value
if (row[attributeName]) {
event.properties = {'attributeValue': row[attributeName]};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
row[attributeName] = returnValue
@@ -43,7 +42,6 @@ async function invokeDataQueryEventHandlers(component, context) {
let metadata = context.getAttributeUISettings(attributeName);
if (metadata) {
event.properties = {'settings': metadata};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setAttributeUISettings(attributeName, returnValue);
@@ -54,7 +52,6 @@ async function invokeDataQueryEventHandlers(component, context) {
let settings = context.getUISettings();
if (settings) {
event.properties = {'settings': settings};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setUISettings(returnValue);
@@ -63,21 +60,19 @@ async function invokeDataQueryEventHandlers(component, context) {
} else if (handlerPath === `entity.changeResponseData`) {
let data = context.getQueryResult() || [];
event.properties = {'responseData': data};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setQueryResult(returnValue);
}
} else if (handlerPath === `entity.changeBotMessages`) {
event.properties = {'messages': context.getRequest().candidateMessages};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.getResponse().messages = returnValue;
}
}
} else {
- logger.debug(`No handler found for event: ${handlerPath}`);
+ logger.error(`No handler found for event: ${handlerPath}`);
break;
}
}
diff --git a/lib/entity/utils.js b/lib/entity/utils.js
index 2ebdfd2..9ccaeb1 100644
--- a/lib/entity/utils.js
+++ b/lib/entity/utils.js
@@ -35,7 +35,6 @@ async function invokeResolveEntitiesEventHandlers(component, context) {
handlerPath = `entity.${eventName}`;
}
if (handler) {
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
// event handlers can be async (returning a promise), but we dont want to enforce
// every event handler is async, hence Promise.resolve wrapping of invocation
let returnValue = await Promise.resolve(handler(event.properties || {}, context));
@@ -43,7 +42,6 @@ async function invokeResolveEntitiesEventHandlers(component, context) {
let retValue = returnValue === undefined ? true : (returnValue+''==='true')
logger.debug(`${eventName} returned ${retValue}`);
if (eventName==='shouldPrompt') {
- logger.debug(`Adding ${itemName} to shouldPrompt cache with value ${retValue}`);
context._getShouldPromptCache()[itemName] = retValue;
if (retValue) {
// only invoke next shouldPrompt handler when current handler returned false
@@ -62,7 +60,7 @@ async function invokeResolveEntitiesEventHandlers(component, context) {
}
}
} else {
- logger.debug(`No handler found for event: ${handlerPath}`);
+ logger.error(`No handler found for event: ${handlerPath}`);
break;
}
}
diff --git a/package-lock.json b/package-lock.json
index 41a54af..7da28d1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@oracle/bots-node-sdk",
- "version": "2.7.1",
+ "version": "2.7.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index d591a47..212c8a0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@oracle/bots-node-sdk",
- "version": "2.7.1",
+ "version": "2.7.2",
"description": "Oracle Digital Assistant SDK for custom component development and webhook integrations",
"main": "index.js",
"browser": "index-browser.js",
diff --git a/ts/lib.ts b/ts/lib.ts
index cd7f566..ba71b6e 100644
--- a/ts/lib.ts
+++ b/ts/lib.ts
@@ -75,7 +75,7 @@ export namespace Lib {
export type EntityItemPublishPromptMessageEvent = lib.EntityItemPublishPromptMessageEvent
- export type EntityItemPublishDisambiguationMessageEvent = lib.EntityItemPublishDisambiguationMessageEvent
+ export type EntityItemPublishDisambiguateMessageEvent = lib.EntityItemPublishDisambiguateMessageEvent
export type EntityItemMaxPromptsReachedEvent = lib.EntityItemMaxPromptsReachedEvent
diff --git a/ts/lib/component/kinds.ts b/ts/lib/component/kinds.ts
index 4a6db5a..26050d6 100644
--- a/ts/lib/component/kinds.ts
+++ b/ts/lib/component/kinds.ts
@@ -67,10 +67,11 @@ export interface EntityEvent {
}
export interface EntityItemEvents {
+ items?: EntityItems;
shouldPrompt?(event: EntityValidateEvent, context: EntityResolutionContext): void
validate?(event: EntityItemValidateEvent, context: EntityResolutionContext): void
publishPromptMessage?(event: EntityItemPublishPromptMessageEvent, context: EntityResolutionContext): void
- publishDisambiguationMessage?(event: EntityItemPublishDisambiguationMessageEvent, context: EntityResolutionContext): void
+ publishDisambiguateMessage?(event: EntityItemPublishDisambiguateMessageEvent, context: EntityResolutionContext): void
maxPromptsReached?(event: EntityItemMaxPromptsReachedEvent, context: EntityResolutionContext): void
}
@@ -139,7 +140,7 @@ export interface EntityItemPublishPromptMessageEvent extends EntityBaseEvent {
promptCount: number;
}
-export interface EntityItemPublishDisambiguationMessageEvent extends EntityBaseEvent {
+export interface EntityItemPublishDisambiguateMessageEvent extends EntityBaseEvent {
disambiguationValues: object[];
}
diff --git a/ts/lib/dataquery/utils.ts b/ts/lib/dataquery/utils.ts
index 7da918b..6aa1005 100644
--- a/ts/lib/dataquery/utils.ts
+++ b/ts/lib/dataquery/utils.ts
@@ -34,7 +34,6 @@ export async function invokeDataQueryEventHandlers(component: DataQueryEventHand
// update row with formatted value if attribute is included in the row and has a value
if (row[attributeName]) {
event.properties = {'attributeValue': row[attributeName]};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
row[attributeName] = returnValue
@@ -46,7 +45,6 @@ export async function invokeDataQueryEventHandlers(component: DataQueryEventHand
let metadata = context.getAttributeUISettings(attributeName);
if (metadata) {
event.properties = {'settings': metadata};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setAttributeUISettings(attributeName, returnValue);
@@ -57,7 +55,6 @@ export async function invokeDataQueryEventHandlers(component: DataQueryEventHand
let settings = context.getUISettings();
if (settings) {
event.properties = {'settings': settings};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setUISettings(returnValue);
@@ -66,21 +63,19 @@ export async function invokeDataQueryEventHandlers(component: DataQueryEventHand
} else if (handlerPath === `entity.changeResponseData`) {
let data = context.getQueryResult() || [];
event.properties = {'responseData': data};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setQueryResult(returnValue);
}
} else if (handlerPath === `entity.changeBotMessages`) {
event.properties = {'messages': context.getRequest().candidateMessages};
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.getResponse().messages = returnValue;
}
}
} else {
- logger.debug(`No handler found for event: ${handlerPath}`);
+ logger.error(`No handler found for event: ${handlerPath}`);
break;
}
}
diff --git a/ts/lib/entity/utils.ts b/ts/lib/entity/utils.ts
index 26ac4c3..514e7de 100644
--- a/ts/lib/entity/utils.ts
+++ b/ts/lib/entity/utils.ts
@@ -33,15 +33,12 @@ export async function invokeResolveEntitiesEventHandlers(
handlerPath = `entity.${eventName}`;
}
if (handler) {
- logger.debug(`Invoking event handler ${handlerPath} with event: ${JSON.stringify(event)}`);
// event handlers can be async (returning a promise), but we dont want to enforce
// every event handler is async, hence Promise.resolve wrapping of invocation
let returnValue = await Promise.resolve(handler(event.properties || {}, context));
// make sure return value is a boolean
let retValue = returnValue === undefined ? true : (returnValue + '' === 'true')
- logger.debug(`${eventName} returned ${retValue}`);
if (eventName === 'shouldPrompt') {
- logger.debug(`Adding ${itemName} to shouldPrompt cache with value ${retValue}`);
context._getShouldPromptCache()[itemName] = retValue;
if (retValue) {
// only invoke next shouldPrompt handler when current handler returned false
@@ -60,7 +57,7 @@ export async function invokeResolveEntitiesEventHandlers(
}
}
} else {
- logger.debug(`No handler found for event: ${handlerPath}`);
+ logger.error(`No handler found for event: ${handlerPath}`);
break;
}
}
diff --git a/ts/lib2/llmcomponent/utils.ts b/ts/lib2/llmcomponent/utils.ts
index d6e24b5..c93d3bc 100644
--- a/ts/lib2/llmcomponent/utils.ts
+++ b/ts/lib2/llmcomponent/utils.ts
@@ -24,14 +24,11 @@ export async function invokeLlmComponentHandlers(component: LlmComponentHandler,
// event handlers can be async (returning a promise), but we dont want to enforce
// every event handler is async, hence Promise.resolve wrapping of invocation
if (eventName === `validateResponsePayload` || eventName === `validateRequestPayload`) {
- logger.debug(`Invoking event handler ${eventName}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
// make sure return value is a boolean
let retValue = returnValue === undefined ? true : (returnValue + '' === 'true')
- logger.debug(`${eventName} returned ${retValue}`);
context.getResponse().valid = retValue;
} else if (eventName === `changeBotMessages` ) {
- logger.debug(`Invoking event handler ${eventName}`);
// convert json messages to message class
const mf = context.getMessageFactory();
let messages = event.properties.messages.map(msg => mf.messageFromJson(msg));
@@ -48,11 +45,10 @@ export async function invokeLlmComponentHandlers(component: LlmComponentHandler,
let currMessages = context.getResponse().messages || [];
context.getResponse().messages = currMessages.concat(messages);
} else {
- logger.debug(`Invoking ${event.custom ? 'custom ' : ''}event handler ${eventName}`);
await Promise.resolve(handler(event.properties, context));
}
} else {
- logger.debug(`No handler found for event: ${eventName}`);
+ logger.error(`No handler found for event: ${eventName}`);
}
}
diff --git a/ts/lib2/llmtransformation/utils.ts b/ts/lib2/llmtransformation/utils.ts
index e745beb..84c3a10 100644
--- a/ts/lib2/llmtransformation/utils.ts
+++ b/ts/lib2/llmtransformation/utils.ts
@@ -18,20 +18,18 @@ export async function invokeLlmTransformationHandlers(component: LlmTransformati
// event handlers can be async (returning a promise), but we dont want to enforce
// every event handler is async, hence Promise.resolve wrapping of invocation
if (eventName === `transformRequestPayload`) {
- logger.debug(`Invoking event handler ${eventName}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setRequestPayload(returnValue);
}
} else if (eventName === `transformResponsePayload` || eventName === `transformErrorResponsePayload`) {
- logger.debug(`Invoking event handler ${eventName}`);
let returnValue = await Promise.resolve(handler(event.properties, context));
if (returnValue) {
context.setResponsePayload(returnValue);
}
}
} else {
- logger.debug(`No handler found for event: ${eventName}`);
+ logger.error(`No handler found for event: ${eventName}`);
}
}
diff --git a/ts/lib2/messagev2/action/action.ts b/ts/lib2/messagev2/action/action.ts
index 1fc2b30..5ec7a00 100644
--- a/ts/lib2/messagev2/action/action.ts
+++ b/ts/lib2/messagev2/action/action.ts
@@ -10,6 +10,7 @@ export class Action extends ChannelCustomizable {
private voice?: Voice;
private imageUrl?: string;
private style?: ActionStyle;
+ private displayType?: DisplayType;
/**
* Deserialize nested object properties into corresponding class instances
@@ -119,6 +120,24 @@ export class Action extends ChannelCustomizable {
return this;
}
+ /**
+ * Gets the style of the action.
+ * @returns {DisplayType} The display type of the action.
+ */
+ public getDisplayType(): DisplayType {
+ return this.displayType;
+ }
+
+ /**
+ * Sets the display type of the action.
+ * @param {DisplayType} displayType - The display type to set.
+ * @returns The current instance of the Action class.
+ */
+ public setDisplayType(displayType: DisplayType): this {
+ this.displayType = displayType;
+ return this;
+ }
+
}
/**
@@ -129,3 +148,12 @@ export enum ActionStyle {
danger = 'danger',
}
+/**
+ * Represents the display type of an action.
+ */
+export enum DisplayType {
+ button = 'button',
+ link = 'link',
+ icon = 'icon',
+}
+
diff --git a/ts/lib2/messagev2/action/index.ts b/ts/lib2/messagev2/action/index.ts
index 8cf5906..1c8ad17 100644
--- a/ts/lib2/messagev2/action/index.ts
+++ b/ts/lib2/messagev2/action/index.ts
@@ -1,4 +1,5 @@
export * from './callAction';
+export * from './popupAction';
export * from './action';
export * from './keyword';
export * from './locationAction';
diff --git a/ts/lib2/messagev2/action/popupAction.ts b/ts/lib2/messagev2/action/popupAction.ts
new file mode 100644
index 0000000..fd02c20
--- /dev/null
+++ b/ts/lib2/messagev2/action/popupAction.ts
@@ -0,0 +1,53 @@
+import { Action, NonRawMessage, MessageUtil } from '../internal';
+
+/**
+ * Represents a popup action. When clicked a popup dialog opens that shows the popup content
+ * @extends Action
+ */
+export class PopupAction extends Action {
+ public readonly type: string = 'popup';
+ private popupContent: NonRawMessage;
+
+ /**
+ * Creates an instance of PopupAction.
+ * @param label - The label of the popup action.
+ * @param popupContent - The popup content associated with the popup action.
+ */
+ constructor(label: string, popupContent: NonRawMessage) {
+ super(label);
+ this.popupContent = popupContent;
+ }
+
+ /**
+ * Deserialize nested object properties into corresponding class instances
+ */
+ public deserializeNestedProperties(): void {
+ super.deserializeNestedProperties();
+ if (this.popupContent) {
+ this.popupContent = MessageUtil.deserializeMessage(this.popupContent);
+ }
+ }
+
+ /**
+ * Gets the popup content associated with the popup action.
+ * @returns The popup content associated with the popup action.
+ */
+ public getPopupContent(): NonRawMessage {
+ return this.popupContent;
+ }
+
+ /**
+ * Sets the popup content associated with the popup action.
+ * @param popupContent - The popup content to set.
+ * @returns The current instance of the PopupAction class.
+ */
+ public setPopupContent(popupContent: NonRawMessage): this {
+ this.popupContent = popupContent;
+ return this;
+ }
+
+}
+
+
+
+
diff --git a/ts/lib2/messagev2/common/messageUtil.ts b/ts/lib2/messagev2/common/messageUtil.ts
index 4bee7e5..5bb6a45 100644
--- a/ts/lib2/messagev2/common/messageUtil.ts
+++ b/ts/lib2/messagev2/common/messageUtil.ts
@@ -4,7 +4,7 @@ import {
, TimePickerField, ToggleField, LinkField, Field, TextMessage, Attachment, AttachmentMessage, Card, CardMessage
, CommandMessage, EditFormMessage, FormMessage, FormSubmissionMessage, NonRawMessage, TableMessage, TableFormMessage, ReadOnlyForm
, PaginationInfo, ChannelExtensions, Row, TableHeading, Location, LocationMessage, PostbackMessage, TextStreamMessage
- , Column, FormRow, ActionField, MediaField
+ , Column, FormRow, ActionField, MediaField, PopupAction, UpdateApplicationContextCommandMessage, ExecuteApplicationActionCommandMessage
}
from '../internal';
@@ -55,6 +55,12 @@ export class MessageUtil {
case 'textStream':
msg = Object.assign(new TextStreamMessage(null, null, null, null), json);
break;
+ case 'updateApplicationContextCommand':
+ msg = Object.assign(new UpdateApplicationContextCommandMessage(null), json);
+ break;
+ case 'executeApplicationActionCommand':
+ msg = Object.assign(new ExecuteApplicationActionCommandMessage(null, null), json);
+ break;
default:
throw new Error(`Error deserializing message, unknown message type: ${type}`);
}
@@ -87,6 +93,9 @@ export class MessageUtil {
case 'submitForm':
action = Object.assign(new SubmitFormAction(null), json);
break;
+ case 'popup':
+ action = Object.assign(new PopupAction(null, null), json);
+ break;
case 'url':
action = Object.assign(new UrlAction(null, null), json);
break;
diff --git a/ts/lib2/messagev2/internal.ts b/ts/lib2/messagev2/internal.ts
index 66413ea..34c11ee 100644
--- a/ts/lib2/messagev2/internal.ts
+++ b/ts/lib2/messagev2/internal.ts
@@ -17,6 +17,7 @@ export * from './common/formRow';
export * from './action/action';
export * from './action/keyword';
export * from './action/callAction';
+export * from './action/popupAction';
export * from './action/locationAction';
export * from './action/postbackAction';
export * from './action/customEventAction';
@@ -48,6 +49,8 @@ export * from './messagePayload/textStreamMessage';
export * from './messagePayload/cardMessage';
export * from './messagePayload/attachmentMessage';
export * from './messagePayload/commandMessage';
+export * from './messagePayload/executeApplicationActionCommandMessage';
+export * from './messagePayload/updateApplicationContextCommandMessage';
export * from './messagePayload/editFormMessage';
export * from './messagePayload/formMessage';
export * from './messagePayload/rawMessage';
diff --git a/ts/lib2/messagev2/messageFactory.ts b/ts/lib2/messagev2/messageFactory.ts
index cd63750..f7c7400 100644
--- a/ts/lib2/messagev2/messageFactory.ts
+++ b/ts/lib2/messagev2/messageFactory.ts
@@ -3,8 +3,10 @@ import {
, Voice, MessageUtil, Row, TableHeading, DatePickerField, MultiSelectField, SelectFieldOption, NumberInputField, SingleSelectField
, TextField, TextInputField, TimePickerField, ToggleField, LinkField, Field, ReadOnlyField, TextMessage, Attachment, AttachmentType
, AttachmentMessage, Card, CardMessage, CommandMessage, CommandType, EditFormMessage, FormMessage, NonRawMessage, RawMessage
- , TableMessage, TableFormMessage, TextStreamMessage, StreamState, CustomEventAction
+ , TableMessage, TableFormMessage, TextStreamMessage, StreamState, CustomEventAction, PopupAction, ActionField, MediaField, MediaType
+ , Action
} from './internal';
+import { ExecuteApplicationActionCommandMessage, UpdateApplicationContextCommandMessage } from './messagePayload';
/**
* Factory class to create the various message types of Oracle Digital Assistant Conversation Message Model (CMM)
@@ -174,6 +176,26 @@ export class MessageFactory {
return new RawMessage(payload);
}
+ /**
+ * Creates an instance of the ExecuteApplicationActionCommandMessage class.
+ * @param {string} applicationName The name of the application
+ * @param {string} action The action to execute
+ * @returns {ExecuteApplicationActionCommandMessage} The created instance of the ExecuteApplicationActionCommandMessage.
+ */
+ public static createExecuteApplicationActionCommandMessage(applicationName: string, action: string):
+ ExecuteApplicationActionCommandMessage {
+ return new ExecuteApplicationActionCommandMessage(applicationName, action);
+ }
+
+ /**
+ * Creates an instance of the UpdateApplicationContextCommandMessage class.
+ * @param {string} applicationName The name of the application
+ * @returns {UpdateApplicationContextCommandMessage} The created instance of the UpdateApplicationContextCommandMessage.
+ */
+ public static createUpdateApplicationContextCommandMessage(applicationName: string): UpdateApplicationContextCommandMessage {
+ return new UpdateApplicationContextCommandMessage(applicationName);
+ }
+
/**
* Creates an instance of the PaginationInfo class.
* @param {number} totalCount The total count.
@@ -243,6 +265,16 @@ export class MessageFactory {
return new UrlAction(label, url);
}
+ /**
+ * Create a new Popup action
+ * @param {string} label The label of the Popup action.
+ * @param {NonRawMessage} popupContent The content shown in the popup.
+ * @returns {PopupAction} A new instance of the PopupAction class.
+ */
+ public static createPopupAction(label: string, popupContent: NonRawMessage): PopupAction {
+ return new PopupAction(label, popupContent);
+ }
+
/**
* Create a new Call action
* @param {string} label The label of the Call action.
@@ -368,26 +400,24 @@ export class MessageFactory {
return new LinkField(label, value, linkLabel);
}
- // fields below will be added in 23.08
-
- // /**
- // * Creates an instance of the ActionField class.
- // * @param action The action of the action field.
- // * @returns The created instance of the ActionField.
- // */
- // public static createActionField(action: Action) {
- // return new ActionField(action);
- // }
-
- // /**
- // * Creates an instance of the MediaField class.
- // * @param label The label of the field.
- // * @param value The URL value of the field
- // * @param mediaType The media type for the field.
- // * @returns The created instance of the MediaField.
- // */
- // public static createMediaField(label: string, value: string, mediaType: MediaType): MediaField {
- // return new MediaField(label, value, mediaType);
- // }
+ /**
+ * Creates an instance of the ActionField class.
+ * @param action The action of the action field.
+ * @returns The created instance of the ActionField.
+ */
+ public static createActionField(action: Action) {
+ return new ActionField(action);
+ }
+
+ /**
+ * Creates an instance of the MediaField class.
+ * @param label The label of the field.
+ * @param value The URL value of the field
+ * @param mediaType The media type for the field.
+ * @returns The created instance of the MediaField.
+ */
+ public static createMediaField(label: string, value: string, mediaType: MediaType): MediaField {
+ return new MediaField(label, value, mediaType);
+ }
}
diff --git a/ts/lib2/messagev2/messagePayload/commandMessage.ts b/ts/lib2/messagev2/messagePayload/commandMessage.ts
index a39055a..eee42af 100644
--- a/ts/lib2/messagev2/messagePayload/commandMessage.ts
+++ b/ts/lib2/messagev2/messagePayload/commandMessage.ts
@@ -63,5 +63,10 @@ export enum CommandType {
home = 'home',
exit = 'exit',
startDoNotDisturbMode = 'startDoNotDisturbMode',
- stopDoNotDisturbMode = 'stopDoNotDisturbMode'
+ stopDoNotDisturbMode = 'stopDoNotDisturbMode',
+ invokeFlow = 'invokeFlow',
+ updateApplicationContext = 'updateApplicationContext',
+ custom = 'custom',
+ replayRequest = 'replayRequest',
+ executeApplicationAction = 'executeApplicationAction'
}
diff --git a/ts/lib2/messagev2/messagePayload/executeApplicationActionCommandMessage.ts b/ts/lib2/messagev2/messagePayload/executeApplicationActionCommandMessage.ts
new file mode 100644
index 0000000..3158b76
--- /dev/null
+++ b/ts/lib2/messagev2/messagePayload/executeApplicationActionCommandMessage.ts
@@ -0,0 +1,81 @@
+import { CommandMessage, CommandType } from '../internal';
+
+/**
+ * Represents an execute application action command message.
+ * This message is used in co-pilot where this message is sent from the skill to the client to trigger a specific action in a
+ * page, e.g. updateing fields.
+ *
+ * @extends CommandMessage
+ */
+export class ExecuteApplicationActionCommandMessage extends CommandMessage {
+ public readonly type: string = 'executeApplicationActionCommand';
+ private applicationName: string;
+ private pageName?: string;
+ private action: string;
+
+ /**
+ * Creates an instance of the ExecuteApplicationActionCommandMessage class.
+ * @param {string} applicationName The name of the application
+ */
+ constructor(applicationName: string, action: string) {
+ super(CommandType.executeApplicationAction);
+ this.applicationName = applicationName;
+ this.action = action;
+ }
+
+
+ /**
+ * Gets the application name
+ * @returns {string} The name of the application
+ */
+ public getApplicationName(): string {
+ return this.applicationName;
+ }
+
+ /**
+ * Sets the application name
+ * @param {string} The name of the application
+ * @returns {this} The updated instance of the ExecuteApplicationActionCommandMessage.
+ */
+ public setApplicationName(applicationName: string): this {
+ this.applicationName = applicationName;
+ return this;
+ }
+
+ /**
+ * Gets the page name
+ * @returns {string} The name of the page
+ */
+ public getPageName(): string {
+ return this.pageName;
+ }
+
+ /**
+ * Sets the page name
+ * @param {string} The name of the page
+ * @returns {this} The updated instance of the ExecuteApplicationActionCommandMessage.
+ */
+ public setPageName(pageName: string): this {
+ this.pageName = pageName;
+ return this;
+ }
+
+ /**
+ * Gets the action
+ * @returns {string} The action
+ */
+ public getAction(): string {
+ return this.action;
+ }
+
+ /**
+ * Sets the action
+ * @param {string} The action
+ * @returns {this} The updated instance of the ExecuteApplicationActionCommandMessage.
+ */
+ public setAction(action: string): this {
+ this.action = action;
+ return this;
+ }
+
+}
diff --git a/ts/lib2/messagev2/messagePayload/index.ts b/ts/lib2/messagev2/messagePayload/index.ts
index 9ab06b8..3142641 100644
--- a/ts/lib2/messagev2/messagePayload/index.ts
+++ b/ts/lib2/messagev2/messagePayload/index.ts
@@ -3,6 +3,8 @@ export * from './textStreamMessage';
export * from './cardMessage';
export * from './attachmentMessage';
export * from './commandMessage';
+export * from './updateApplicationContextCommandMessage';
+export * from './executeApplicationActionCommandMessage';
export * from './editFormMessage';
export * from './formMessage';
export * from './rawMessage';
diff --git a/ts/lib2/messagev2/messagePayload/updateApplicationContextCommandMessage.ts b/ts/lib2/messagev2/messagePayload/updateApplicationContextCommandMessage.ts
new file mode 100644
index 0000000..d6d73fc
--- /dev/null
+++ b/ts/lib2/messagev2/messagePayload/updateApplicationContextCommandMessage.ts
@@ -0,0 +1,159 @@
+import { CommandMessage, CommandType } from '../internal';
+
+/**
+ * Represents the context source that initiates the application context update
+ */
+export enum ContextSource {
+ chatWindow = 'chatWindow',
+ UIWidget = 'UIWidget',
+ skill = 'skill'
+}
+
+/**
+ * Represents an update context command message.
+ * This message is used in co-pilot where the application context can be sent from the client to the skill to
+ * invoke or resume a flow, or it is sent from the skill to the client to trigger application navigation.
+ *
+ * @extends CommandMessage
+ */
+export class UpdateApplicationContextCommandMessage extends CommandMessage {
+ public readonly type: string = 'updateApplicationContextCommand';
+ private applicationName: string;
+ private pageName?: string;
+ private fieldName?: string;
+ private parameters?: Map;
+ private contextSource: ContextSource;
+ private reset?: boolean;
+
+ /**
+ * Creates an instance of the UpdateContextCommandMessage class.
+ * @param {string} applicationName The command type.
+ */
+ constructor(applicationName: string) {
+ super(CommandType.updateApplicationContext);
+ this.contextSource = ContextSource.skill;
+ this.applicationName = applicationName;
+ }
+
+ /**
+ * Gets the context source
+ * @returns {ContextSource} The context source
+ */
+ public getContextSource(): ContextSource {
+ return this.contextSource;
+ }
+
+ /**
+ * Gets the application name
+ * @returns {string} The name of the application
+ */
+ public getApplicationName(): string {
+ return this.applicationName;
+ }
+
+ /**
+ * Sets the application name
+ * @param {string} The name of the application
+ * @returns {this} The updated instance of the UpdateContextCommandMessage.
+ */
+ public setApplicationName(applicationName: string): this {
+ this.applicationName = applicationName;
+ return this;
+ }
+
+ /**
+ * Gets the page name
+ * @returns {string} The name of the page
+ */
+ public getPageName(): string {
+ return this.pageName;
+ }
+
+ /**
+ * Sets the page name
+ * @param {string} The name of the page
+ * @returns {this} The updated instance of the UpdateContextCommandMessage.
+ */
+ public setPageName(pageName: string): this {
+ this.pageName = pageName;
+ return this;
+ }
+
+ /**
+ * Gets the field name
+ * @returns {string} The name of the field
+ */
+ public getFieldName(): string {
+ return this.fieldName;
+ }
+
+ /**
+ * Sets the field name
+ * @param {string} The name of the field
+ * @returns {this} The updated instance of the UpdateContextCommandMessage.
+ */
+ public setFieldName(fieldName: string): this {
+ this.fieldName = fieldName;
+ return this;
+ }
+
+ /**
+ * Gets the parameters of the message.
+ * @returns {Map} The parameters of the message.
+ */
+ public getParameters(): Map {
+ return this.parameters;
+ }
+
+ /**
+ * Gets the value of a parameter.
+ * @param {string} parameterName The name of the parameter.
+ * @returns {any} The parameter value.
+ */
+ public getParameterValue(parameterName: string): any {
+ return this.parameters ? this.parameters[parameterName] : undefined;
+ }
+
+ /**
+ * Sets the parameters of the message.
+ * @param {Map} parameters The parameters to set.
+ * @returns {this} The current instance of the UpdateContextCommandMessage class.
+ */
+ public setParameters(parameters: Map): this {
+ this.parameters = parameters;
+ return this;
+ }
+
+ /**
+ * Add a parameter to the message.
+ * @param {string} name The name of the parameter.
+ * @param {any} value The value of the parameter.
+ * @returns {this} The current instance of the UpdateContextCommandMessage class.
+ */
+ public addParameter(name: string, value: any): this {
+ if (!this.parameters) {
+ this.parameters = new Map();
+ }
+ this.parameters[name] = value;
+ return this;
+ }
+
+ /**
+ * Returns the flow reset flag
+ * @returns {boolean} flow reset flag
+ */
+ public getReset(): boolean {
+ return this.reset;
+ }
+
+ /**
+ * Set the flow reset flag
+ * @param {boolean} reset The reset flag
+ * @returns {this} The current instance of the UpdateContextCommandMessage class.
+ */
+ public setReset(reset: boolean): this {
+ this.reset = reset;
+ return this;
+ }
+
+}
diff --git a/ts/spec/json/executeApplicationActionCommand.json b/ts/spec/json/executeApplicationActionCommand.json
new file mode 100644
index 0000000..457750f
--- /dev/null
+++ b/ts/spec/json/executeApplicationActionCommand.json
@@ -0,0 +1,8 @@
+{
+ "type": "executeApplicationActionCommand",
+ "command": "executeApplicationAction",
+ "applicationName": "HCM",
+ "pageName": "JobRequisition",
+ "action" : "updateFields",
+ "properties": {"foo": "bar"}
+}
\ No newline at end of file
diff --git a/ts/spec/json/textWithActions.json b/ts/spec/json/textWithActions.json
index f202a3c..4e55496 100644
--- a/ts/spec/json/textWithActions.json
+++ b/ts/spec/json/textWithActions.json
@@ -19,6 +19,8 @@
"word1",
"word2"
],
+ "displayType": "icon",
+ "style": "danger",
"channelExtensions": {
"facebook": {
"myProp": "myValue",
diff --git a/ts/spec/json/textWithPopupAction.json b/ts/spec/json/textWithPopupAction.json
new file mode 100644
index 0000000..fc3e0cf
--- /dev/null
+++ b/ts/spec/json/textWithPopupAction.json
@@ -0,0 +1,79 @@
+{
+ "text": "I'm sorry the answer wasn't helpful. Can you please provide feedback to help me improve?",
+ "type": "text",
+ "actions": [
+ {
+ "popupContent": {
+ "type": "editForm",
+ "title": "Give your feedback",
+ "fields": [
+ {
+ "displayType": "text",
+ "labelFontWeight": "bold",
+ "label": "What was the issue with this response?"
+ },
+ {
+ "displayType": "multiSelect",
+ "options": [
+ {
+ "label": "Inaccurate",
+ "value": "inaccurate"
+ },
+ {
+ "label": "Inappropriate",
+ "value": "inappropriate"
+ },
+ {
+ "label": "Irrelevant",
+ "value": "irrelevant"
+ },
+ {
+ "label": "Other",
+ "value": "other"
+ }
+ ],
+ "layoutStyle": "checkboxes",
+ "id": "system_feedback_reasons",
+ "required": true
+ },
+ {
+ "displayType": "textInput",
+ "multiLine": true,
+ "id": "system_feedback_comments",
+ "placeholder": "Additional feedback"
+ }
+ ],
+ "formColumns": 1,
+ "actions": [
+ {
+ "postback": {
+ "rating": "negative",
+ "system.botId": "D92910F5-16F9-4F24-BF2B-8284B356AC61",
+ "action": "cancel",
+ "system.flow": "UnresolvedIntent",
+ "feedbackType": "llm",
+ "system.state": "invokeLLM"
+ },
+ "label": "Cancel",
+ "type": "postback"
+ },
+ {
+ "postback": {
+ "rating": "negative",
+ "system.botId": "D92910F5-16F9-4F24-BF2B-8284B356AC61",
+ "action": "cancel",
+ "system.flow": "UnresolvedIntent",
+ "feedbackType": "llm",
+ "system.state": "invokeLLM"
+ },
+ "label": "Submit Feedback",
+ "type": "submitForm"
+ }
+ ],
+ "channelExtensions": {}
+ },
+ "displayType": "link",
+ "label": "Give Feedback",
+ "type": "popup"
+ }
+ ]}
\ No newline at end of file
diff --git a/ts/spec/json/updateApplicationContextCommand.json b/ts/spec/json/updateApplicationContextCommand.json
new file mode 100644
index 0000000..c38c809
--- /dev/null
+++ b/ts/spec/json/updateApplicationContextCommand.json
@@ -0,0 +1,10 @@
+{
+ "type": "updateApplicationContextCommand",
+ "command": "updateApplicationContext",
+ "applicationName": "HCM",
+ "source" : "skill",
+ "reset": true,
+ "pageName": "JobRequisition",
+ "fieldName": "JobDescription",
+ "parameters": {"foo": "bar"}
+}
\ No newline at end of file
diff --git a/ts/spec/lib/message/messageDeserializer.spec.ts b/ts/spec/lib/message/messageDeserializer.spec.ts
index 05c3567..d977989 100644
--- a/ts/spec/lib/message/messageDeserializer.spec.ts
+++ b/ts/spec/lib/message/messageDeserializer.spec.ts
@@ -3,7 +3,7 @@ import {
, MultiSelectLayoutStyle, CardLayout, Card, AttachmentType, FieldAlignment, PostbackAction, MessageUtil, ChannelExtensions, CardMessage,
LocationAction, TextInputField, TextField, LinkField, EditFormMessage, SingleSelectField, SubmitFormAction, FormMessage, TableMessage
, TableFormMessage, CommandMessage, CommandType, LocationMessage, PostbackMessage, FormSubmissionMessage, TextStreamMessage, StreamState
- , ColumnWidth, ActionField, VerticalAlignment, Column, FormRow
+ , ColumnWidth, ActionField, VerticalAlignment, Column, FormRow, PopupAction, DisplayType, ExecuteApplicationActionCommandMessage, UpdateApplicationContextCommandMessage, ContextSource
} from '../../../lib2';
import * as fs from 'fs';
import * as path from 'path';
@@ -44,6 +44,20 @@ describe('MessageDeserializer', () => {
});
+ it('Deserialize Text Message with PopupAction', function () {
+
+ const file = path.resolve('ts/spec/json/', 'textWithPopupAction.json');
+ let expected: string = fs.readFileSync(file, 'utf-8');
+
+ let msg = MF.messageFromJson(JSON.parse(expected)) as TextMessage;
+ expect(msg.getActions()[0] instanceof PopupAction).toBeTruthy;
+ let action = msg.getActions()[0] as PopupAction;
+ expect(action.getPopupContent() instanceof EditFormMessage).toBeTruthy;
+ expect(action.getDisplayType() === DisplayType.link).toBeTrue;
+
+ });
+
+
it('Deserialize Text Stream Message', function () {
const file = path.resolve('ts/spec/json/', 'textStream.json');
@@ -172,6 +186,33 @@ describe('MessageDeserializer', () => {
});
+ it('Deserialize ExecuteApplicationActionCommand', function () {
+
+ const file = path.resolve('ts/spec/json/', 'executeApplicationActionCommand.json');
+ let expected: string = fs.readFileSync(file, 'utf-8');
+ let msg = MF.messageFromJson(JSON.parse(expected)) as ExecuteApplicationActionCommandMessage;
+ expect(msg.getCommand()).toEqual(CommandType.executeApplicationAction);
+ expect(msg.getAction()).toEqual('updateFields');
+ expect(msg.getApplicationName()).toEqual('HCM');
+ expect(msg.getPageName()).toEqual('JobRequisition');
+ expect(msg.getPropertyValue('foo')).toEqual('bar');
+
+ });
+
+ it('Deserialize UpdateApplicationContextCommand', function () {
+
+ const file = path.resolve('ts/spec/json/', 'updateApplicationContextCommand.json');
+ let expected: string = fs.readFileSync(file, 'utf-8');
+ let msg = MF.messageFromJson(JSON.parse(expected)) as UpdateApplicationContextCommandMessage;
+ expect(msg.getCommand()).toEqual(CommandType.updateApplicationContext);
+ expect(msg.getContextSource()).toEqual(ContextSource.skill);
+ expect(msg.getReset()).toBeTruthy;
+ expect(msg.getApplicationName()).toEqual('HCM');
+ expect(msg.getPageName()).toEqual('JobRequisition');
+ expect(msg.getParameterValue('foo')).toEqual('bar');
+
+ });
+
it('Deserialize Location', function () {
const file = path.resolve('ts/spec/json/', 'location.json');
diff --git a/ts/spec/lib/message/messageFactory.spec.ts b/ts/spec/lib/message/messageFactory.spec.ts
index e80367d..c5ddc36 100644
--- a/ts/spec/lib/message/messageFactory.spec.ts
+++ b/ts/spec/lib/message/messageFactory.spec.ts
@@ -1,5 +1,5 @@
import { MessageFactory as MF, TextMessage, Voice, ChannelType, InputStyle, SingleSelectLayoutStyle, MultiSelectLayoutStyle, CardLayout
- , AttachmentType, FieldAlignment, CommandType, StreamState, TextStreamMessage} from '../../../lib2';
+ , AttachmentType, FieldAlignment, CommandType, StreamState, TextStreamMessage, DisplayType, ActionStyle} from '../../../lib2';
import * as fs from 'fs';
import * as path from 'path';
@@ -19,6 +19,8 @@ describe('MessageFactory', () => {
.setSkipAutoNumber(true)
.addKeyword('word1')
.addKeyword('word2')
+ .setDisplayType(DisplayType.icon)
+ .setStyle(ActionStyle.danger)
.setChannelExtensionProperty(ChannelType.facebook, 'myProp', 'myValue')
.setChannelExtensionProperty(ChannelType.facebook, 'myProp2', 'myValue2')
.setChannelExtensionProperty(ChannelType.slack, 'myProp', 'myValue')