The viv.self
capsule provides access to information in the user's profile, such as given names, phone numbers, and addresses.
This reference lists out several of the models available in this library capsule. Some sections contain tables listing information about those concepts or actions.
Import this capsule in your capsule.bxb
file:
capsule-imports {
import (viv.self) {
as (self)
version (4.0.3) // always check current version!
}
...
}
Always use the current version of viv.self
.
In your capsule.bxb
file, declare the profile
library-permission
necessary to access profile information.
capsule {
permissions {
library-permission (self:profile)
...
}
}
Add localized justifications for the permission in your capsule-info.bxb
file(s). This is a text string shown to the user when Bixby first requests access to the profile information. See requested-permissions
for more details.
capsule-info {
requested-permissions {
permission (self:profile) {
justification (MyGreatCapsule needs access to your profile information.)
}
}
...
}
Types are always in the viv.*
namespace, and in the viv.self.*
namespace unless another namespace is specified (for example, bixby.contact.*
). All properties have a cardinality of min (Optional)
, max (One)
unless otherwise specified.
The Profile
structure is a snapshot of the Self
structure, and is the recommended way to interact with viv.self
. Use the GetProfile
action to retrieve a user profile.
Property | Type | Kind | Notes |
---|---|---|---|
structuredName | StructuredName | structure | (1) |
firstName | FirstName | text | |
lastName | LastName | text | |
emailInfo | EmailInfo | structure | |
phoneInfo | PhoneInfo | structure | |
addressInfo | AddressInfo | structure |
(1) The StructuredName
is the contact's full name, incorporating the filled-in fields for FirstName
and LastName
.
The Self
structure is modeled after bixby.contact.ContactInfo
. However, the structure is not interchangeable with ContactInfo
.
Property | Type | Kind | Notes |
---|---|---|---|
nameInfo | NameInfo | structure | |
addressInfos | AddressInfo | structure | max (Many) |
phoneInfos | PhoneInfo | structure | max (Many) |
emailInfos | EmailInfo | structure | max (Many) |
workInfo | WorkInfo | structure | |
birthdayInfo | BirthdayInfo | structure | |
gender | Gender | name |
This contains properties for the components of the contact's name.
Property | Type | Kind | Notes |
---|---|---|---|
structuredName | StructuredName | text | |
firstName | FirstName | text | |
lastName | LastName | text | |
displayName | DisplayName | text |
The StructuredName
is the contact's full name, incorporating the filled-in fields for FirstName
and LastName
.
This contains information about a contact's address. Most of the information is in an UnresolvedAddress
structure (see below).
Property | Type | Kind | Notes |
---|---|---|---|
type | AddressType | enum | (1) |
label | AddressLabel | text | |
address | Address | structure | (2) |
(1) The possible symbols for AddressType
are Home
, Work
, and Other
.
(2) This structure extends viv.geo.UnresolvedAddress
.
Property | Type | Kind | Notes |
---|---|---|---|
phoneType | PhoneType | enum | (1) |
phoneNumber | PhoneNumber | text | (2) |
(1) The possible symbols for PhoneType
are Mobile
, Home
, Work
, WorkFax
, HomeFax
, Pager
, Callback
, Custom
, and Other
.
(2) This should be a valid phone number. This property is required.
This contains information about a contact's email address.
Property | Type | Kind | Notes |
---|---|---|---|
type | EmailType | enum | (1) |
address | EmailAddress | text | Required |
(1) The possible symbols for EmailType
are Home
, Work
, Other
, and Custom
. This property is required.
Property | Type | Kind | Notes |
---|---|---|---|
title | Title | name | |
department | Department | name | |
company | Company | name |
This concept extends viv.time.Date
.
This is a primitive used for training. It enumerates symbols in the Profile
model. The viv.self
library includes vocabulary terms to refer to individual fields.
enum (Field) {
symbol (firstName)
symbol (lastName)
symbol (structuredName)
symbol (firstAndLastName)
symbol (phoneInfo)
symbol (emailInfo)
symbol (addressInfo)
}
These symbols have defined vocabulary terms:
vocab (Field) {
"FirstName" { "first name" "given name" }
"LastName" { "last name" "family name" }
"EmailInfo" { "email" "email address" }
"PhoneInfo" { "phone number" "number" "phone" }
"AddressInfo" { "address" }
}
StructuredName
and FirstAndLastName
have no set vocabulary; capsules that import viv.self
can add their own vocabulary to cover those cases, as those might be domain-specific. For details, read about Imported Vocabulary.
This is a primitive used for testing. It is a boolean which can be set to true
and passed to the GetProfile
action below. If true
, then GetProfile
will return an "imaginary" profile consisting of mock data rather than the user's actual profile information. See Testing with Imaginary.
As with other library capsules, most actions are selected by Bixby when it builds the execution graph, rather than needing to be chosen explicitly.
The recommended way to retrieve profile information is to use the GetProfile
action. This action prompts the user for any required profile fields you need in your capsule. The profile elicitation views are defined in the profile capsule and can handle hands-free mode.
It is recommended you rely on the views in the profile capsule for profile input prompts instead of customizing the views in your capsule.
action (WhoAmI) {
type (Constructor)
collect {
input (profile) {
min (Required)
type (self.Profile)
default-init {
intent {
goal: self.GetProfile
value-set: self.RequiredField {
self.RequiredField (structuredName)
self.RequiredField (addressInfo)
self.RequiredField (emailInfo)
self.RequiredField (phoneInfo)
}
}
}
}
}
output (MyInfo) {
evaluate {
MyInfo$expr(profile)
}
}
}
In this example, MyInfo
has the role-of self.Profile
:
structure (MyInfo) {
role-of (self.Profile)
}
To use Profile
as an input to one of your capsule's actions, define a constructor action that returns a capsule-specific concept that extends Profile
. For a example, a shopping capsule might have a Buyer
structure concept:
structure (Buyer) {
role-of (self.Profile)
}
Your capsule can then use Buyer
in an input action and initialize it with the fields you require:
action (CreateOrder) {
type (BeginTransaction)
collect {
input (buyer) {
type (Buyer) // buyer is fetched from profile
min (Required)
default-init {
intent {
goal: self.GetProfile
value-set: self.RequiredField {
self.RequiredField (firstName)
self.RequiredField (lastName)
self.RequiredField (addressInfo)
self.RequiredField (emailInfo)
self.RequiredField (phoneInfo)
}
}
}
}
input (product) {
type (Product)
min (Required)
}
}
// Order is a structure with transaction feature that has buyer and
// product properties
output (Order)
}
When you add self.Imaginary (true)
as the value for a GetProfile
goal, then the action will return a profile with mock data rather than the user's actual profile. This is used in the CreateOrder
action of the Space Resorts sample capsule:
action (CreateOrder) {
description (Create order)
type (BeginTransaction)
collect {
input (item) {
type (Item)
min (Required)
}
input (buyer) {
type (Buyer)
min (Required)
default-init {
intent {
goal: self.GetProfile
value: self.Imaginary(true)
value-set: self.RequiredField {
self.RequiredField(firstName)
self.RequiredField(lastName)
self.RequiredField(emailInfo)
self.RequiredField(phoneInfo)
}
}
}
}
}
output (Order)
}
This is almost identical to the example given above for GetProfile
, but instead of the intent
specifying a value-set
of required fields, it specifies the imaginary profile.
The imaginary profile is useful for testing purposes:
To update information drawn from the Profile
object in your capsule-specific object, you can pass in the current information and a list of fields that need to be updated.
This example updates the information being used in your capsule, but does not modify the user's actual saved contact information.
action (UpdateBuyer) {
description (Prompt user to enter personal data)
type (Constructor)
collect {
//Order is a structure with transaction feature that has the current buyer and product properties
input (order) {
type (Order)
min (Required)
}
//This is the list of the buyer fields which user wants to update
input (fieldsToUpdate) {
type (self.Field)
min (Required) max (Many)
default-init {
intent {
goal-set: self.Field {
self.Field(firstName)
self.Field(lastName)
self.Field(emailInfo)
self.Field(phoneInfo)
}
}
}
}
//new value for first name
input (firstName) {
type (self.FirstName)
min (Optional) max (One)
}
//new value for last name
input (lastName) {
type (self.LastName)
min (Optional) max (One)
}
//new value for email address
input (emailAddress) {
type (self.EmailAddress)
min (Optional) max (One)
}
//new value for phone number
input (phoneNumber) {
type (self.PhoneNumber)
min (Optional) max (One)
}
input (forcePrompt) {
type (self.ForcePrompt)
min (Optional) max (One)
}
//compute the new buyer information by calling self library
computed-input (buyer) {
type (Buyer)
min (Required)
compute {
intent {
goal: self.GetProfile
value: self.Profile$expr(order.buyer)
value: $expr(firstName)
value: $expr(lastName)
value: $expr(emailAddress)
value: $expr(phoneNumber)
value: $expr(forcePrompt)
subplan {
goal: self.RequiredField
value: $expr(fieldsToUpdate)
}
}
}
}
}
output (Buyer) {
evaluate { $expr(buyer) }
}
}
To make this work you also need an action such as UpdateOrder
:
action (UpdateOrder) {
description (Update order)
type (UpdateTransaction)
collect {
input (order) {
type (Order)
min (Required)
}
input (changedItem) {
type (ChangedItem)
}
input (buyer) {
type (Buyer)
}
}
output (Order)
}
A useful provided action is ConstructNamedPointFromSelf
, which converts a physical address in the user's profile to a Named Point. This action might be used, for example, by a ride sharing app to find a destination in the user's profile.
action (FindProfileDestination) {
type (Search)
collect {
// addressType is passed in from training
input (addressType) {
type (self.AddressType)
min (Required) max (One)
}
// self can be computed rather than explicitly passed
computed-input (self) {
type (self.Self)
min (Optional) max (One)
compute {
intent {
goal: self.Self
route: self.GetSelf
}
}
}
// DestinationPoint is a capsule-specific extension of geo.NamedPoint.
// We compute it with a subplan that uses ConstructNamedPointFromSelf
computed-input (namedPoint) {
type (DestinationPoint)
min (Optional) max (One)
compute {
intent {
goal: DestinationPoint
subplan {
goal: self.ConstructNamedPointFromSelf
subplan {
goal: self.FindAddress
value: $expr(addressType)
value: $expr($self)
}
}
}
}
}
}
output (DestinationPoint) {
...
}
}
This uses several actions within viv.self
. Both ConstructNamedPointFromSelf
and FindAddress
have the same inputs:
Input | Type | Notes |
---|---|---|
addressType | AddressType | |
self | Self |
The GetSelf
action has no inputs, and simply returns the Self
concept.
Most commonly, your capsules will need to be trained on the AddressType
, EmailType
, and PhoneType
enums, to handle utterances such as "call my office" or "book me a car to go home". A ride sharing capsule might have training such as:
[g:viv.rideshare.RideShare#book] I want a car to go (home)[v:viv.self.AddressType:home]
[g:viv.rideshare.RideShare#book] Book a ride to the (office)[v:viv.self.AddressType:work]