Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0952b9a
updated js runtime to match the latest sdk
chon219 Oct 23, 2020
280788d
updated composerbot of js runtime
chon219 Oct 26, 2020
89c2024
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Oct 26, 2020
beedbe0
updated sdk to 4.11.0-rc1
chon219 Oct 29, 2020
3f1cede
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Oct 29, 2020
8c52fe0
Merge branch 'main' into zim/update-js-runtime
luhan2017 Oct 30, 2020
3fbaf46
fixed test failure for js runtime
chon219 Oct 30, 2020
9595f07
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Oct 30, 2020
4e95867
Merge branch 'zim/update-js-runtime' of https://github.com/microsoft/…
chon219 Oct 30, 2020
7f8792e
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 3, 2020
649b550
updated sdk to 4.11 rc3
chon219 Nov 3, 2020
0533e92
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Nov 3, 2020
af295a1
Merge branch 'zim/update-js-runtime' of https://github.com/microsoft/…
chon219 Nov 3, 2020
05ac7db
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 4, 2020
d20771d
added schemas in node runtime
chon219 Nov 4, 2020
b35328c
copy schemas folder while ejecting
chon219 Nov 4, 2020
357ff56
added sample for custom action
chon219 Nov 4, 2020
4324deb
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Nov 4, 2020
a8be9d5
inline comments and converters
chon219 Nov 5, 2020
393eb97
updated update-schema script
chon219 Nov 5, 2020
2460b91
more inline comments
chon219 Nov 5, 2020
0cc31fe
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Nov 5, 2020
a85257f
Merge branch 'main' into zim/update-js-runtime
chon219 Nov 5, 2020
d7de7b9
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 9, 2020
20138c3
updated js runtime to 4.11.0
chon219 Nov 10, 2020
5a45ca7
Merge branch 'main' of https://github.com/microsoft/botframework-comp…
chon219 Nov 10, 2020
ed8cf93
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 12, 2020
b92dafd
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 13, 2020
f8a579c
Merge branch 'main' into zim/update-js-runtime
cwhitten Nov 17, 2020
94ddebf
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 18, 2020
6a1ecc5
Merge branch 'main' into zim/update-js-runtime
cwhitten Nov 19, 2020
8fdf593
Merge branch 'main' into zim/update-js-runtime
cwhitten Nov 19, 2020
0047308
Merge branch 'main' into zim/update-js-runtime
chon219 Nov 26, 2020
125edff
Merge branch 'main' into zim/update-js-runtime
luhan2017 Nov 30, 2020
f00a423
Merge branch 'main' into zim/update-js-runtime
cwhitten Dec 1, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions extensions/runtimes/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,30 @@ export default async (composer: any): Promise<void> => {
// used to read bot project template from source (bundled in plugin)
const excludeFolder = new Set<string>().add(path.resolve(sourcePath, 'node_modules'));
await copyDir(sourcePath, localDisk, destPath, project.fileStorage, excludeFolder);
const schemaDstPath = path.join(project.dir, 'schemas');
const schemaSrcPath = path.join(sourcePath, 'schemas');
const customSchemaExists = fs.existsSync(schemaDstPath);
const pathsToExclude: Set<string> = new Set();
if (customSchemaExists) {
const sdkExcludePath = await localDisk.glob('sdk.schema', schemaSrcPath);
if (sdkExcludePath.length > 0) {
pathsToExclude.add(path.join(schemaSrcPath, sdkExcludePath[0]));
}
}
await copyDir(schemaSrcPath, localDisk, schemaDstPath, project.fileStorage, pathsToExclude);
const schemaFolderInRuntime = path.join(destPath, 'schemas');
await removeDirAndFiles(schemaFolderInRuntime);
// install dev dependencies in production, make sure typescript is installed
const { stderr: initErr } = await execAsync('npm install && npm install --only=dev', {
cwd: destPath,
});
if (initErr) {
composer.log(initErr);
}
const { stderr: initErr2 } = await execAsync('npm run build', { cwd: destPath });
if (initErr2) {
throw new Error(initErr2);
}
return destPath;
} else {
throw new Error(`Runtime already exists at ${destPath}`);
Expand Down
16 changes: 11 additions & 5 deletions runtime/node/__tests__/actions.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as path from 'path';
import { ConversationState, MemoryStorage, TestAdapter, TurnContext, useBotState, UserState } from 'botbuilder';
import { ResourceExplorer } from 'botbuilder-dialogs-declarative';
import { AdaptiveDialogComponentRegistration } from 'botbuilder-dialogs-adaptive';
import { TestAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
import { ActivityTypes, Activity, ChannelAccount } from 'botframework-schema';
import { ComposerBot } from '../src/shared/composerBot';
import { SkillConversationIdFactory } from '../src/shared/skillConversationIdFactory';
import * as helpers from '../src/shared/helpers';
import { ActivityTypes, Activity, ChannelAccount } from 'botframework-schema';
import { TurnContext } from 'botbuilder-core';

const samplesDirectory = path.resolve(__dirname, '../../../extensions/samples/assets/projects', 'ActionsSample');

Expand Down Expand Up @@ -43,7 +41,6 @@ const getSettings = jest.spyOn(helpers, 'getSettings').mockImplementation((root:

beforeAll(() => {
resourceExplorer.addFolders(samplesDirectory, ['runtime'], false);
resourceExplorer.addComponent(new AdaptiveDialogComponentRegistration(resourceExplorer));
adapter = new TestAdapter(
async (context: TurnContext): Promise<any> => {
// Route activity to bot.
Expand All @@ -60,6 +57,8 @@ beforeEach(() => {
// Create shared user state and conversation state instances.
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
useBotState(adapter, userState, conversationState);

// Create shared skill conversation id factory instance.
const skillConversationIdFactory = new SkillConversationIdFactory();
bot = new ComposerBot(userState, conversationState, skillConversationIdFactory);
Expand Down Expand Up @@ -232,6 +231,13 @@ describe('test runtime used ActionsSample', () => {
basicActiivty,
true
);
const memoryStorage = new MemoryStorage();

// Create shared user state and conversation state instances.
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
useBotState(adapter, userState, conversationState);

await adapter
.send(conversationUpdateActivity)
.assertReply(
Expand Down
7 changes: 3 additions & 4 deletions runtime/node/__tests__/controllingConversation.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import * as path from 'path';
import { ResourceExplorer } from 'botbuilder-dialogs-declarative';
import { AdaptiveDialogComponentRegistration } from 'botbuilder-dialogs-adaptive';
import { TestAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
import { ConversationState, MemoryStorage, TestAdapter, TurnContext, useBotState, UserState } from 'botbuilder';
import { ComposerBot } from '../src/shared/composerBot';
import { ActivityTypes, Activity, ChannelAccount } from 'botframework-schema';
import { TurnContext } from 'botbuilder-core';
import * as helpers from '../src/shared/helpers';
import { SkillConversationIdFactory } from '../src/shared/skillConversationIdFactory';

Expand Down Expand Up @@ -47,7 +45,6 @@ let adapter: TestAdapter;

beforeAll(() => {
resourceExplorer.addFolders(samplesDirectory, ['runtime'], false);
resourceExplorer.addComponent(new AdaptiveDialogComponentRegistration(resourceExplorer));
adapter = new TestAdapter(
async (context: TurnContext): Promise<any> => {
// Route activity to bot.
Expand All @@ -62,6 +59,8 @@ beforeAll(() => {
// Create shared user state and conversation state instances.
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
useBotState(adapter, userState, conversationState);

// Create shared skill conversation id factory instance.
const skillConversationIdFactory = new SkillConversationIdFactory();
bot = new ComposerBot(userState, conversationState, skillConversationIdFactory);
Expand Down
7 changes: 3 additions & 4 deletions runtime/node/__tests__/inputs.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import * as path from 'path';
import { ResourceExplorer } from 'botbuilder-dialogs-declarative';
import { AdaptiveDialogComponentRegistration } from 'botbuilder-dialogs-adaptive';
import { TestAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
import { ConversationState, MemoryStorage, TestAdapter, TurnContext, useBotState, UserState } from 'botbuilder';
import { ComposerBot } from '../src/shared/composerBot';
import { ActivityTypes, Activity, ChannelAccount } from 'botframework-schema';
import { TurnContext } from 'botbuilder-core';
import { SkillConversationIdFactory } from '../src/shared/skillConversationIdFactory';
import * as helpers from '../src/shared/helpers';

Expand Down Expand Up @@ -46,7 +44,6 @@ let bot: ComposerBot;
let adapter: TestAdapter;
beforeAll(() => {
resourceExplorer.addFolders(samplesDirectory, ['runtime'], false);
resourceExplorer.addComponent(new AdaptiveDialogComponentRegistration(resourceExplorer));
adapter = new TestAdapter(
async (context: TurnContext): Promise<any> => {
// Route activity to bot.
Expand All @@ -61,6 +58,8 @@ beforeAll(() => {
// Create shared user state and conversation state instances.
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
useBotState(adapter, userState, conversationState);

// Create shared skill conversation id factory instance.
const skillConversationIdFactory = new SkillConversationIdFactory();
bot = new ComposerBot(userState, conversationState, skillConversationIdFactory);
Expand Down
9 changes: 4 additions & 5 deletions runtime/node/__tests__/message.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import * as path from 'path';
import { ConversationState, MemoryStorage, TestAdapter, TurnContext, useBotState, UserState } from 'botbuilder';
import { ResourceExplorer } from 'botbuilder-dialogs-declarative';
import { AdaptiveDialogComponentRegistration } from 'botbuilder-dialogs-adaptive';
import { TestAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
import { ComposerBot } from '../src/shared/composerBot';
import { ActivityTypes, Activity, ChannelAccount } from 'botframework-schema';
import { TurnContext } from 'botbuilder-core';
import { ComposerBot } from '../src/shared/composerBot';
import { SkillConversationIdFactory } from '../src/shared/skillConversationIdFactory';
import * as helpers from '../src/shared/helpers';

Expand Down Expand Up @@ -39,7 +37,6 @@ let bot: ComposerBot;
let adapter: TestAdapter;
beforeAll(() => {
resourceExplorer.addFolders(samplesDirectory, ['runtime'], false);
resourceExplorer.addComponent(new AdaptiveDialogComponentRegistration(resourceExplorer));
adapter = new TestAdapter(
async (context: TurnContext): Promise<any> => {
// Route activity to bot.
Expand All @@ -53,6 +50,8 @@ beforeAll(() => {
// Create shared user state and conversation state instances.
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
useBotState(adapter, userState, conversationState);

// Create shared skill conversation id factory instance.
const skillConversationIdFactory = new SkillConversationIdFactory();
bot = new ComposerBot(userState, conversationState, skillConversationIdFactory);
Expand Down
9 changes: 4 additions & 5 deletions runtime/node/__tests__/todobot.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import * as path from 'path';
import { ConversationState, MemoryStorage, TestAdapter, TurnContext, useBotState, UserState } from 'botbuilder';
import { ResourceExplorer } from 'botbuilder-dialogs-declarative';
import { AdaptiveDialogComponentRegistration } from 'botbuilder-dialogs-adaptive';
import { TestAdapter, ConversationState, MemoryStorage, UserState } from 'botbuilder';
import { ComposerBot } from '../src/shared/composerBot';
import { ActivityTypes, Activity, ChannelAccount } from 'botframework-schema';
import { TurnContext } from 'botbuilder-core';
import { ComposerBot } from '../src/shared/composerBot';
import { SkillConversationIdFactory } from '../src/shared/skillConversationIdFactory';
import * as helpers from '../src/shared/helpers';

Expand Down Expand Up @@ -35,7 +33,6 @@ let bot: ComposerBot;
let adapter: TestAdapter;
beforeAll(() => {
resourceExplorer.addFolders(samplesDirectory, ['runtime'], false);
resourceExplorer.addComponent(new AdaptiveDialogComponentRegistration(resourceExplorer));
adapter = new TestAdapter(
async (context: TurnContext): Promise<any> => {
// Route activity to bot.
Expand All @@ -49,6 +46,8 @@ beforeAll(() => {
// Create shared user state and conversation state instances.
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);
useBotState(adapter, userState, conversationState);

// Create shared skill conversation id factory instance.
const skillConversationIdFactory = new SkillConversationIdFactory();
bot = new ComposerBot(userState, conversationState, skillConversationIdFactory);
Expand Down
10 changes: 6 additions & 4 deletions runtime/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
"license": "ISC",
"dependencies": {
"@azure/functions": "^1.2.2",
"botbuilder": "4.10.0-rc0",
"botbuilder-dialogs": "4.10.0-rc0",
"botbuilder-dialogs-adaptive": "4.10.0-rc0-preview",
"botbuilder-dialogs-declarative": "4.10.0-rc0-preview",
"adaptive-expressions": "4.11.0",
"botbuilder": "4.11.0",
"botbuilder-ai": "4.11.0",
"botbuilder-dialogs": "4.11.0",
"botbuilder-dialogs-adaptive": "4.11.0-preview",
"botbuilder-dialogs-declarative": "4.11.0-preview",
"debug": "^4.1.1",
"lodash": "^4.17.19",
"minimist": "1.2.5",
Expand Down
144 changes: 144 additions & 0 deletions runtime/node/schemas/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# How to update the schema file

Once the bot has been setup with Composer and we wish to make changes to the schema, the first step in this process is to eject the runtime through the `Runtime Config` in Composer. The ejected runtime folder will broadly have the following structure

```
bot
/bot.dialog
/language-generation
/language-understanding
/dialogs
/customized-dialogs
/runtime
/schemas
sdk.schema
```

##### Prequisites

Botframework CLI > 4.10

```
npm i -g @microsoft/botframework-cli
```

> NOTE: Previous versions of botframework-cli required you to install @microsoft/bf-plugin. You will need to uninstall for 4.10 and above.
>
> ```
> bf plugins:uninstall @microsoft/bf-dialog
> ```

## Adding Custom Actions to your Composer bot for C#

**NOTE: These steps assume you are using azurewebapp as your deployment solution. Replicating it on azurefunctions would be similar
**

- In this tutorial, we will be going over the steps to include a custom action `MultiplyDialog` that multiplies two numbers passed as inputs. Note that the ejected runtime should contain a `customaction` folder that has this sample.

- Navigate to the csproj file inside the `runtime` folder (bot/runtime/azurewebapp/Microsoft.BotFramework.Composer.WebApp.csproj) and include a project reference to the customaction project like `<ProjectReference Include="..\customaction\Microsoft.BotFramework.Composer.CustomAction.csproj" />`.

- Then Uncomment line 28 and 139 in azurewebapp/Startup.cs file so as to register this action.

```

using Microsoft.BotFramework.Composer.CustomAction;
// This is for custom action component registration.
ComponentRegistration.Add(new CustomActionComponentRegistration());

```

- Run the command `dotnet build` on the azurewebapp project to verify if it passes build after adding custom actions to it.

- Navigate to to the `schemas (bot/schemas)` folder. This folder contains a Powershell script and a bash script. Run either of these scripts `./update-schema.ps1 -runtime azurewebapp` or `sh ./update-schema.sh -runtime azurewebapp`. The runtime `azurewebapp` is chosen by default if no argument is passed.

- Validate that the partial schema (MultiplyDialog.schema inside customaction/Schema) has been appended to the default sdk.schema file to generate one single consolidated sdk.schema file.

The above steps should have generated a new sdk.schema file inside `schemas` folder for Composer to use. Reload the bot and you should be able to include your new custom action!

## Adding Custom Actions to your Composer bot for Node.js

- In this tutorial, we will be going over the steps to include a custom action `MultiplyDialog` that multiplies two numbers passed as inputs. Note that the ejected runtime should contain a `customaction` folder that has this sample.

- Uncomment line 30 and 61 in src/shared/composerBot.ts file so as to register this action.

```

import { CustomActionComponentRegistration } from '../customaction/customActionComponentRegistration';
// This is for custom action component registration, uncomment this to enable custom action support.
ComponentRegistration.add(new CustomActionComponentRegistration());

```

- Run the command `npm run build` on the runtime to verify if it passes build after adding custom actions to it.

- Navigate to to the `schemas (bot/schemas)` folder. This folder contains a Powershell script and a bash script. Run either of these scripts `./update-schema.ps1` or `sh ./update-schema.sh`.

- Validate that the partial schema (MultiplyDialog.schema inside customaction) has been appended to the default sdk.schema file to generate one single consolidated sdk.schema file.

The above steps should have generated a new sdk.schema file inside `schemas` folder for Composer to use. Reload the bot and you should be able to include your new custom action!

## Customizing Composer using the UI Schema

Composer's UI can be customized using the UI Schema. You can either customize one of your custom actions or override Composer defaults.

There are 2 ways to do this.

1. **Component UI Schema File**

To customize a specific component, simply create a `.uischema` file inside of the `/schemas` directory with the same name as the component, These files will be merged into a single `.uischema` file when running the `update-schema` script.

Example:

```json
// Microsoft.SendActivity.uischema
{
"$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
"form": {
"label": "A custom label"
}
}
```

2. **UI Schema Override File**

This approach allows you to co-locate all of your UI customizations into a single file. This will not be merged into the `sdk.uischema`, instead it will be loaded by Composer and applied as overrides.

Example:

```json
{
"$schema": "https://schemas.botframework.com/schemas/ui/v1.0/ui.schema",
"Microsoft.SendActivity": {
"form": {
"label": "A custom label"
}
}
}
```

#### UI Customization Options

##### Form

| **Property** | **Description** | **Type** | **Default** |
| ------------ | -------------------------------------------------------------------------------------- | ------------------- | -------------------- |
| description | Text used in tooltips. | `string` | `schema.description` |
| helpLink | URI to component or property documentation. Used in tooltips. | `string` | |
| hidden | An array of property names to hide in the UI. | `string[]` | |
| label | Label override. Can either be a string or false to hide the label. | `string` \| `false` | `schema.title` |
| order | Set the order of fields. Use "\_" for all other fields. ex. ["foo", "_", "bar"] | `string[]` | `[*]` |
| placeholder | Placeholder override. | `string` | `schema.examples` |
| properties | A map of component property names to UI options with customizations for each property. | `object` | |
| subtitle | Subtitle rendered in form title. | `string` | `schema.$kind` |
| widget | Override default field widget. See list of widgets below. | `enum` | |

###### Widgets

- checkbox
- date
- datetime
- input
- number
- radio
- select
- textarea
Loading