Skip to content

Commit

Permalink
🔀 Merge pull request #1638 from sadlowskij/v4/feature/alexa-start-con…
Browse files Browse the repository at this point in the history
…nection-output

✨ Add StartConnectionOutput for Alexa
  • Loading branch information
jankoenig authored Jun 6, 2024
2 parents 4c86954 + 4138510 commit 7e3e4b3
Show file tree
Hide file tree
Showing 15 changed files with 274 additions and 334 deletions.
36 changes: 35 additions & 1 deletion platforms/platform-alexa/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,41 @@ You can build Alexa Skills with Jovo that make use of the Alexa Conversations di

You can use Jovo with [Alexa Skill Connections](https://developer.amazon.com/docs/alexa/custom-skills/understand-skill-connections.html) by sending a `Connections.StartConnection` directive as shown in the [official Alexa docs](https://developer.amazon.com/docs/alexa/custom-skills/use-skill-connections-to-request-tasks.html#implement-a-handler-to-return-a-connectionsstartconnection-directive-to-use-skill-connection).

For this, the Jovo Alexa integration offers convenience [output classes](https://www.jovo.tech/docs/output-classes). Below is an overview of all classes:
For example, if you want to connect to a [custom task in a specific skill](https://developer.amazon.com/en-US/docs/alexa/custom-skills/use-skill-connections-to-request-tasks.html#for-custom-task-direct-skill-connection-with-send_errors_only), you can use the `StartConnectionOutput` class provided by the Jovo Alexa integration.

```typescript
import { StartConnectionOutput, OnCompletion } from '@jovotech/platform-alexa';
// ...

someHandler() {
// ...

return this.$send(StartConnectionOutput, {
taskName: {
amazonPredefinedTask: false,
name: 'CountDown',
},
// Input for the task
input: {
upperLimit: 10,
lowerLimit: 1,
},
// Decides whether session is picked up after task
onCompletion: OnCompletion.SendErrorsOnly,
token: '<your-token>',
// defaults to 1
taskVersion: 1,
// This is mandatory in case taskName.amazonPredefinedTask is false
providerSkillId: '<skill-id>',
});
}
```

The Output Options can be changed to create a [managed skill connection](https://developer.amazon.com/en-US/docs/alexa/custom-skills/use-skill-connections-to-request-tasks.html#for-managed-skill-connection), by setting `taskName.amazonPredefinedTask` to true and omitting `providerSkillId`.

In case the session is supposed to be [resumed](https://developer.amazon.com/en-US/docs/alexa/custom-skills/use-skill-connections-to-request-tasks.html#return-connectionsstartconnection-directive-with-resume_session-set-explicitly-or-by-default) after the task is handled, `onCompletion` can be changed to `OnCompletion.ResumeSession`.

For some specific connections, the Jovo Alexa integration offers convenience [output classes](https://www.jovo.tech/docs/output-classes). Below is an overview of all classes:

- [`ConnectionAskForPermissionConsentOutput`](https://github.com/jovotech/jovo-framework/tree/v4/latest/platforms/platform-alexa/src/output/templates/ConnectionAskForPermissionConsentOutput.ts)
- [`ConnectionLinkAppOutput`](https://github.com/jovotech/jovo-framework/tree/v4/latest/platforms/platform-alexa/src/output/templates/ConnectionLinkAppOutput.ts)
Expand Down
1 change: 1 addition & 0 deletions platforms/platform-alexa/src/output/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export * from './common/AsinProduct';
export * from './common/ConnectionPostalAddress';
export * from './common/ConsentLevel';
export * from './common/PermissionScope';
export * from './common/OnCompletion';
export * from './dialog/DialogConfirmIntentDirective';
export * from './dialog/DialogConfirmSlotDirective';
export * from './dialog/DialogDelegateDirective';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework';
import { AsinProduct } from '../models';
import { OnCompletion } from '../models/common/OnCompletion';
import { StartConnectionOutput } from './StartConnectionOutput';

export interface ConnectionAddToShoppingCartOutputOptions extends OutputOptions {
shouldEndSession?: boolean;
Expand All @@ -19,33 +20,15 @@ export class ConnectionAddToShoppingCartOutput extends BaseOutput<ConnectionAddT
}

build(): OutputTemplate | OutputTemplate[] {
const shouldEndSession =
this.options.onCompletion === OnCompletion.SendErrorsOnly
? true
: this.options.shouldEndSession;

return {
message: this.options.message,
platforms: {
alexa: {
nativeResponse: {
response: {
shouldEndSession,
directives: [
{
type: 'Connections.StartConnection',
uri: 'connection://AMAZON.AddToShoppingCart/1',
input: {
products: this.options.products,
},
token: this.options.token,
onCompletion: this.options.onCompletion,
},
],
},
},
},
return new StartConnectionOutput(this.jovo, {
taskName: { name: 'AddToShoppingCart', amazonPredefinedTask: true },
taskVersion: 1,
shouldEndSession: this.options.shouldEndSession,
onCompletion: this.options.onCompletion,
input: {
products: this.options.products,
},
};
token: this.options.token,
}).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework';
import { ConnectionPermissionScopeLike, ConsentLevelLike } from '../models';
import { OnCompletion } from '../models/common/OnCompletion';
import { StartConnectionOutput } from './StartConnectionOutput';

export interface PermissionScopeItem {
permissionScope: ConnectionPermissionScopeLike;
Expand All @@ -24,35 +25,18 @@ export class ConnectionAskForPermissionConsentOutput extends BaseOutput<Connecti
}

build(): OutputTemplate | OutputTemplate[] {
const shouldEndSession =
this.options.onCompletion === OnCompletion.SendErrorsOnly
? true
: this.options.shouldEndSession;
return new StartConnectionOutput(this.jovo, {
taskName: { name: 'AskForPermissionsConsent', amazonPredefinedTask: true },
taskVersion: 2,

return {
message: this.options.message,
platforms: {
alexa: {
nativeResponse: {
response: {
shouldEndSession,
directives: [
{
type: 'Connections.StartConnection',
uri: 'connection://AMAZON.AskForPermissionsConsent/2',
input: {
'@type': 'AskForPermissionsConsentRequest',
'@version': '2',
'permissionScopes': this.options.permissionScopes,
},
token: this.options.token,
onCompletion: this.options.onCompletion,
},
],
},
},
},
shouldEndSession: this.options.shouldEndSession,
onCompletion: this.options.onCompletion,
input: {
'@type': 'AskForPermissionsConsentRequest',
'@version': '2',
'permissionScopes': this.options.permissionScopes,
},
};
token: this.options.token,
}).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework';
import { AsinProduct } from '../models';
import { OnCompletion } from '../models/common/OnCompletion';
import { StartConnectionOutput } from './StartConnectionOutput';

export interface ConnectionBuyShoppingProductsOutputOptions extends OutputOptions {
shouldEndSession?: boolean;
Expand All @@ -19,33 +20,15 @@ export class ConnectionBuyShoppingProductsOutput extends BaseOutput<ConnectionBu
}

build(): OutputTemplate | OutputTemplate[] {
const shouldEndSession =
this.options.onCompletion === OnCompletion.SendErrorsOnly
? true
: this.options.shouldEndSession;

return {
message: this.options.message,
platforms: {
alexa: {
nativeResponse: {
response: {
shouldEndSession,
directives: [
{
type: 'Connections.StartConnection',
uri: 'connection://AMAZON.BuyShoppingProducts/1',
input: {
products: this.options.products,
},
token: this.options.token,
onCompletion: this.options.onCompletion,
},
],
},
},
},
return new StartConnectionOutput(this.jovo, {
taskName: { name: 'BuyShoppingProducts', amazonPredefinedTask: true },
taskVersion: 1,
shouldEndSession: this.options.shouldEndSession,
onCompletion: this.options.onCompletion,
input: {
products: this.options.products,
},
};
token: this.options.token,
}).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework';
import { OnCompletion } from '../models/common/OnCompletion';
import { StartConnectionOutput } from './StartConnectionOutput';

export enum DirectLaunchDefaultPromptBehavior {
Speak = 'SPEAK',
Expand Down Expand Up @@ -30,44 +31,27 @@ export class ConnectionLinkAppOutput extends BaseOutput<ConnectionLinkAppOutputO
}

build(): OutputTemplate | OutputTemplate[] {
const shouldEndSession =
this.options.onCompletion === OnCompletion.SendErrorsOnly
? true
: this.options.shouldEndSession;

return {
message: this.options.message,
platforms: {
alexa: {
nativeResponse: {
response: {
shouldEndSession,
directives: [
{
type: 'Connections.StartConnection',
uri: 'connection://AMAZON.LinkApp/2',
input: {
links: this.options.links,
prompt: {
topic: this.options.topic,
directLaunchDefaultPromptBehavior:
this.options.directLaunchDefaultPromptBehavior,
},
directLaunch: {
enabled: this.options.directLaunchEnabled,
},
sendToDevice: {
enabled: this.options.sendToDeviceEnabled,
},
},
token: this.options.token,
onCompletion: this.options.onCompletion,
},
],
},
},
return new StartConnectionOutput(this.jovo, {
taskName: {
name: 'LinkApp',
},
taskVersion: 2,
shouldEndSession: this.options.shouldEndSession,
onCompletion: this.options.onCompletion,
input: {
links: this.options.links,
prompt: {
topic: this.options.topic,
directLaunchDefaultPromptBehavior: this.options.directLaunchDefaultPromptBehavior,
},
directLaunch: {
enabled: this.options.directLaunchEnabled,
},
sendToDevice: {
enabled: this.options.sendToDeviceEnabled,
},
},
};
token: this.options.token,
}).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework';
import { OnCompletion } from '../models/common/OnCompletion';
import { StartConnectionOutput } from './StartConnectionOutput';

export enum ImageType {
Jpg = 'JPG',
Expand Down Expand Up @@ -28,38 +29,20 @@ export class ConnectionPrintImageOutput extends BaseOutput<ConnectionPrintImageO
}

build(): OutputTemplate | OutputTemplate[] {
const shouldEndSession =
this.options.onCompletion === OnCompletion.SendErrorsOnly
? true
: this.options.shouldEndSession;

return {
message: this.options.message,
platforms: {
alexa: {
nativeResponse: {
response: {
shouldEndSession,
directives: [
{
type: 'Connections.StartConnection',
uri: 'connection://AMAZON.PrintImage/1',
input: {
'@type': 'PrintImageRequest',
'@version': '1',
'title': this.options.title,
'description': this.options.description,
'url': this.options.url,
'imageType': this.options.imageType,
},
token: this.options.token,
onCompletion: this.options.onCompletion,
},
],
},
},
},
return new StartConnectionOutput(this.jovo, {
taskName: { name: 'PrintImage', amazonPredefinedTask: true },
taskVersion: 1,
shouldEndSession: this.options.shouldEndSession,
onCompletion: this.options.onCompletion,
input: {
'@type': 'PrintImageRequest',
'@version': '1',
'title': this.options.title,
'description': this.options.description,
'url': this.options.url,
'imageType': this.options.imageType,
},
};
token: this.options.token,
}).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BaseOutput, Output, OutputOptions, OutputTemplate } from '@jovotech/framework';
import { OnCompletion } from '../models/common/OnCompletion';
import { StartConnectionOutput } from './StartConnectionOutput';

export interface ConnectionPrintPdfOutputOptions extends OutputOptions {
shouldEndSession?: boolean;
Expand All @@ -21,37 +22,19 @@ export class ConnectionPrintPdfOutput extends BaseOutput<ConnectionPrintPdfOutpu
}

build(): OutputTemplate | OutputTemplate[] {
const shouldEndSession =
this.options.onCompletion === OnCompletion.SendErrorsOnly
? true
: this.options.shouldEndSession;

return {
message: this.options.message,
platforms: {
alexa: {
nativeResponse: {
response: {
shouldEndSession,
directives: [
{
type: 'Connections.StartConnection',
uri: 'connection://AMAZON.PrintPDF/1',
input: {
'@type': 'PrintPDFRequest',
'@version': '1',
'title': this.options.title,
'description': this.options.description,
'url': this.options.url,
},
token: this.options.token,
onCompletion: this.options.onCompletion,
},
],
},
},
},
return new StartConnectionOutput(this.jovo, {
taskName: { name: 'PrintPDF', amazonPredefinedTask: true },
taskVersion: 1,
shouldEndSession: this.options.shouldEndSession,
onCompletion: this.options.onCompletion,
input: {
'@type': 'PrintPDFRequest',
'@version': '1',
'title': this.options.title,
'description': this.options.description,
'url': this.options.url,
},
};
token: this.options.token,
}).build();
}
}
Loading

0 comments on commit 7e3e4b3

Please sign in to comment.