Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: User Interest #170

Merged
merged 60 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
cd0997e
chore: Moving word doc to github
jlacivita Aug 16, 2023
befa844
chore: Fixing ToC
jlacivita Aug 18, 2023
bf060c6
Merge branch 'next' into feature/user-interest
jlacivita Nov 6, 2023
161314e
fix: Leverage provider pattern
jlacivita Jan 9, 2024
b21b03f
fix: Simplify which apps may respond
jlacivita Jan 11, 2024
f104046
Merge branch 'next' into feature/user-interest
jlacivita Jan 12, 2024
fe8dc46
feat: User Interest added to Discovery SDK
jlacivita Jan 12, 2024
28b0df2
fix: Discovery Tests
jlacivita Jan 12, 2024
288883e
Update package-lock.json
jlacivita Jan 12, 2024
e769c55
fix: feedback from @kpears201
jlacivita Jan 16, 2024
eec3bd7
fix: Remove todos
jlacivita Jan 16, 2024
1eeebe1
Merge branch 'next' into feature/user-interest
jlacivita Feb 21, 2024
6b0ac9f
feat: App Passthrough OpenRPC tags
jlacivita Feb 23, 2024
ec030df
fix: added appId insertion into results
jlacivita Feb 23, 2024
6deb6c9
fix: Added API Gateway note
jlacivita Feb 23, 2024
f6756d4
fix: clarified validation
jlacivita Feb 23, 2024
3f3b2c9
fix: Support composition for stronger validation
jlacivita Feb 27, 2024
ed35a97
fix: Rework based on @kpears201 's feedback
jlacivita Feb 29, 2024
8a46355
fix: Removed use of notifications for push methods
jlacivita Feb 29, 2024
0e8cd00
fix: Minor push/pull fixes
jlacivita Feb 29, 2024
82aa24a
fix: Further review w/ @kpears201
jlacivita Feb 29, 2024
3e4c585
fix: Clarification and updated examples
jlacivita Feb 29, 2024
f9a0145
feat: Added lifecycle api gating
jlacivita Mar 1, 2024
cb441d7
fix: Get app-passthrough working with existing APIs
jlacivita Mar 6, 2024
b5a5cc1
fix: swap generation order
jlacivita Mar 7, 2024
3109d17
fix: update capabilty and added test
jlacivita Mar 11, 2024
4592de0
Merge branch 'feature/app-passthrough' into feature/user-interest
jlacivita Mar 18, 2024
73a1e7c
fix: Use new app provider pattern
jlacivita Mar 18, 2024
3983f13
fix: Reworking doc to be less abstract
jlacivita Mar 19, 2024
d5749f1
fix: Add reason, clean up app-passthrough
jlacivita Apr 12, 2024
ef3598f
chore: Add Context Params spec
jlacivita Apr 12, 2024
32ffc39
fix: KP's feedback
jlacivita May 8, 2024
c76e9e3
fix: Point to real firebolt-openrpc branch
jlacivita May 9, 2024
6dbc159
fix: Fixing typo
jlacivita May 9, 2024
98e554e
fix: Update package-lock for CI
jlacivita May 9, 2024
8d0f937
Merge branch 'next' into feature/user-interest
jlacivita May 9, 2024
3bff344
fix: Okay, actually fixing build w/ #186 merged in
jlacivita May 9, 2024
92716af
fix: KP's additional comments.
jlacivita May 9, 2024
8446bc4
Debug discovery-sdk issue
kevinshahfws May 15, 2024
6ecf4a3
Debug discovery-sdk issue
kevinshahfws May 15, 2024
5f4af43
Debug discovery-sdk issue - changed openrpc dependency
kevinshahfws May 15, 2024
165bda1
Reverted debug changes
kevinshahfws May 15, 2024
909b6b8
Reverted package json version
kevinshahfws May 15, 2024
9a13483
fix: Point to real firebolt-openrpc branch
jlacivita May 16, 2024
ca615d1
package-lock.json points to latest commit
kevinshahfws May 17, 2024
8ef85f6
fix: Remove aggregated providers
jlacivita May 22, 2024
8b6a207
chore: resolve package-lock
jlacivita May 22, 2024
8034874
fix: Added previously generated methods, create Interest wrapper object
jlacivita May 22, 2024
88b556f
fix: Required fields on Interest
jlacivita May 22, 2024
cf6f29f
Update package-lock.json
jlacivita May 22, 2024
32415d9
fix: Split event and provider types
jlacivita May 22, 2024
3e963b1
fix: Turn on pass-through validation
jlacivita May 23, 2024
b9f6284
fix: Remove "push-pull" spec
jlacivita May 23, 2024
7ca8b2b
fix: Added provider result name disambiguation
jlacivita May 23, 2024
795e368
Update package-lock.json
jlacivita May 28, 2024
4066787
fix: Fixed capability string, added errors
jlacivita May 28, 2024
788743b
fix: Both UserInterestProviderParams are required now
jlacivita May 28, 2024
cb51c01
fix: Typos
jlacivita May 28, 2024
b9f774d
feat: User Interest
kevinshahfws Jun 6, 2024
65155b6
Merge branch 'next' into feature/user-interest
kevinshahfws Jun 6, 2024
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
310 changes: 54 additions & 256 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
},
"workspaces": [
"src/sdks/core",
"src/sdks/manage"
"src/sdks/manage",
"src/sdks/discovery"
],
"scripts": {
"fs:setup": "npm run clean && mkdir -p dist",
"validate:each": "npx firebolt-openrpc validate --input src/openrpc --schemas node_modules/@firebolt-js/schemas/src/schemas --schemas src/schemas --transformations",
"validate:each": "npx firebolt-openrpc validate --input src/openrpc --schemas src/schemas --transformations",
"validate:compiled": "npx firebolt-openrpc validate --input dist/firebolt-open-rpc.json && npm run validate --workspaces",
"validate": "npm run validate:each && npm run validate:compiled ",
"compile": "npx firebolt-openrpc openrpc --input src --template src/template/openrpc/template.json --output ./dist/firebolt-open-rpc.json --schemas node_modules/@firebolt-js/schemas/src/schemas --schemas src/schemas",
"compile": "npx firebolt-openrpc openrpc --input src --template src/template/openrpc/template.json --output ./dist/firebolt-open-rpc.json --schemas src/schemas",
"slice": "npm run slice --workspaces",
"sdks": "npm run sdk --workspaces",
"docs": "npm run docs --workspaces",
Expand Down Expand Up @@ -44,7 +45,7 @@
"devDependencies": {
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@firebolt-js/openrpc": "2.3.0",
"@firebolt-js/openrpc": "../firebolt-openrpc",
"@firebolt-js/schemas": "2.0.0",
"@saithodev/semantic-release-backmerge": "^3.2.0",
"@semantic-release/changelog": "^6.0.1",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
291 changes: 291 additions & 0 deletions requirements/specifications/intents/user-interest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
# User Interest
jlacivita marked this conversation as resolved.
Show resolved Hide resolved

Document Status: Candidate Specification

See [Firebolt Requirements Governance](../../governance.md) for more info.

| Contributor | Organization |
| -------------- | -------------- |
| Eugene Chung | Comcast |
| Tim Dibben | Sky |
| Mike Horwitz | Comcast |
| Jeremy LaCivita | Comcast |

## 1. Overview

In additional to traditional discovery APIs such as Watch History and
Watch Next, Firebolt provides a more abstract API that facilitates
impromptu content discovery connections between first-party Aggregated
Experiences and third-party Apps.

The User Interest Capability enables Apps to provide meta-data on
content that the user has expressed an interest in to Aggregated
Experience Apps that have been given access to use this Capability.

This allows for open ended design of Aggregated Experience App features
that present App-specific content to re-engage the user with the content
inside the originating App.

While the functionality and UX is left to the Aggregated Experience App,
typically designed by each Firebolt Distributor, the Firebolt API
enables events to register user interest and pass entity meta-data:

![Diagram Description automatically
generated](../../../requirements/images/specifications/intents/user-interest/media/image1.png)

Which generally enables Aggregated Experiences to present that entity
meta-data in some way that leads to re-launching the original App at a
later point, using a `navigateTo` notification:

![Diagram Description automatically
generated](../../../requirements/images/specifications/intents/user-interest/media/image2.png)

This is just one example of what an Aggregated Experience App might do
with the User Interest API.

Note that this API **SHOULD NOT** be used to implement Watch History or
Watch Next features. These concepts are much more fundamental to
Firebolt and have explicit APIs so that Firebolt Distributors can keep
track of which apps are using them separately.

## 2. Table of Contents
- [1. Overview](#1-overview)
- [2. Table of Contents](#2-table-of-contents)
- [3. User Interest Flows](#3-user-interest-flows)
- [3.1. User Interest from an in-app UX](#31-user-interest-from-an-in-app-ux)
- [3.2. User Interest from a platform UX](#32-user-interest-from-a-platform-ux)
- [3.3. Upstream User Interest Intent](#33-upstream-user-interest-intent)
- [3.4. User Interest Bulk Updates](#34-user-interest-bulk-updates)
- [4. Core SDK APIs](#4-core-sdk-apis)
- [4.1. InterestType](#41-interesttype)
- [4.2. InterestReason](#42-interestreason)
- [4.3. Discovery.userInterest](#43-discoveryuserinterest)
- [4.4. Discovery Interest Provider](#44-discovery-interest-provider)
- [4.5. InterestIntent](#45-interestintent)
- [5. Discovery SDK APIs](#5-discovery-sdk-apis)
- [5.1. Content.requestUserInterest](#51-contentrequestuserinterest)
- [5.2. Content.onUserInterestedIn](#52-contentonuserinterestedin)


## 3. User Interest Flows
### 3.1. User Interest from an in-app UX

Some Apps will have a built-in user interface for users to express
interest in content from the App. This could be a "Favorite" button,
an in-app "My List" button, etc.

If the App wants to leverage any additional exposure from the device's
Aggregated Experience, it can wire up its own UI to the Firebolt User
Interest API, in addition to any in-app features that it's already
invoking.

By calling the `Discovery.userInterest` method with the relevant entity
meta-data, the device\'s Aggregated Experience will be notified of the
user's interest in that entity:

```typescript
Discovery.userInterest(type:InterestType, reason: InterestReason, entity:EntityInfo)
```

The `type` parameter denotes the directionality of the interest:

- `interest`
- `disinterest`

The `reason` parameter denotes why or how the user has expressed interest:

| Reason | Description |
| ------ | ----------- |
| `playlist` | Interested in adding to a list |
| `reaction` | Interested in submitting a reaction, e.g. like or dislike |
| `recording` | Interest in scheduling a recording |
| `share` | Interest in sharing the content on social media |

**NOTE**: We can remove some of these (not `playlist`) these are here for now to illustrate the purpose for the reason paramater.

An app **MUST** `provide` the `xrn:firebolt:capability:discovery:interest`
capability in order to call `Discovery.userInterest`.

When this method is called with a valid `EntityInfo`, the platform
**MUST** dispatch a `Content.onUserInterest` notification to all Apps
that have registered for it (typically Aggregated Experience Apps) with
information about the app, interest type, and the entity.

The `Content.onUserInterest` event has a `UserInterestInfo` object with the `type`, `reason` and `entity` parameters as it's properties.

An Aggregated Experience can register for the `Content.onUserInterest`
notification, and it will receive notifications when an `EntityInfo` is
returned from the active App after a `Discovery.userInterest` call is
fulfilled.

An app **MUST** have permissions to `use` the
`xrn:firebolt:capability:discovery:interest` capability in order to
listen to the `Content.onUserInterest` notification.

If the result is `null` or is not a valid entity, i.e. does not match
the [EntityInfo](../entities/) schema, then no `Content.onUserInterestedIn`
notification will be dispatched.

The `Discovery.userInterest` method **SHOULD NOT** be used in place of more
specific Discovery methods, e.g. `Discovery.watchNext` or
`Discovery.watched`. These methods facilitate specific UX flows that may
have separate legal opt-outs for each user.

The `Discovery.userInterest` method **SHOULD NOT** be called unless the user
is activating a UI element in the app, or in a second screen experience
that is communicating with the app, that implies interest of some kind.

### 3.2. User Interest from a platform UX

Firebolt platforms may provide a platform UX, e.g. voice or and RCU, to
express user interest in content from an active App. To facilitate this
Apps will need to be told about the user\'s expressed interest in their
content.

First, the Aggregated Experience (or some app with the correct
capability) detects that the user is interested in something. In this
picture the interest is triggered by an RCU button, but how this occurs
is outside the scope of this document. When this happens, the Aggregated
Experience app calls `Content.requestUserInterest()`, which will trigger the
foreground app's UserInterest provider and call it's `userInterest` method
jlacivita marked this conversation as resolved.
Show resolved Hide resolved
by invoking the RPC method `Discovery.onRequestUserInterest`.

![](../../../requirements/images/specifications/intents/user-interest/media/image3.png)

Next, the foreground app receives and responds to the request with an
EntityInfo, which is returned as the result to the pending
`Content.requestUserInterest` method:

![](../../../requirements/images/specifications/intents/user-interest/media/image4.png)

Once an App's callback is invoked, that app will have `interestTimeout`
milliseconds to return a value or throw an error. Values returned after
that time **MUST** be ignored. The timeout value is stored in the
device's configuration manifest.

To be notified when a user expresses interest in the currently displayed
content, an App **MUST** provide the
`xrn:firebolt:capability:discovery:interest` capability by enabling the
`Discovery.onRequestUserInterest` notification.

If there is a valid entity to return, then the method registered by the
App **MUST** return the currently displayed entity meta-data.

If there is no valid entity to return, then the method **MUST** throw an
jlacivita marked this conversation as resolved.
Show resolved Hide resolved
exception.

If the foreground App returns a valid `EntityInfo` before the timeout,
then, the returned value **MUST** be used.

If there is no app registered the an error **MUST** be returned.

### 3.3. Upstream User Interest Intent
In some cases, e.g. a voice assistant, some upstream component will inform
the platform that the user is interested in whatever is currently being presented.

To do this, the upstream system **MUST** send a `Interest` intent, which describes the type of and reason for the interest.

```json
{
"action": "interest",
"data": {
"type": "interest",
"reason": "playlist"
}
}
```

When a Firebolt platform receives this intent, it **SHOULD** initiate the platform's [user interest flow](#4-user-interest-from-a-platform-ux).

### 3.4. User Interest Bulk Updates

Sending bulk interest updates, e.g. Entities the user expressed interest
in on a different platform, is not supported.

## 4. Core SDK APIs

The following APIs are exposed by the Firebolt Core SDK as part of the
`Discovery` module.

### 4.1. InterestType
This is an enum with the following values:

- `"interest"`
- `"disinterest"`

### 4.2. InterestReason
This is an enum with the following values:

| Reason | Description |
| ------ | ----------- |
| `playlist` | Interested in adding to a list |
| `reaction` | Interested in submitting a reaction, e.g. like or dislike |
| `recording` | Interest in scheduling a recording |
| `share` | Interest in sharing the content on social media |

### 4.3. Discovery.userInterest

This is a push API that allows Apps to push entities that the user has
expressed interest in to the platform.

To push an entity that the user is interested in pass an `EntityInfo`
object to the method:

```typescript
Discovery.userInterest(type: InterestType, reason: InterestReason, entity: EntityInfo): Promise<void>
```

### 4.4. Discovery Interest Provider
To respond to requests for the current entity, because the user has
expressed interest in some way that the platform manages, register a
provider:

```typescript
interface IDiscoveryInterestProvider {
function userInterest(type: InterestType, reason: InterestReason): Promise<EntityInfo>
}

Discovery.provide("xrn:firbolt:capability:discovery:interest", IDiscoveryInterestProvider)
```

### 4.5. InterestIntent
jlacivita marked this conversation as resolved.
Show resolved Hide resolved

An `InterestIntent` denotes that the user has expressed interest in the
currently displayed and/or selected content:

```typescript
type InterestIntent {
action: "interest"
data: {
type: "interest" | "disinterest",
reason: "playlist" | "reaction" | "recording"
},
context: {
source: "rcu" | "voice"
}
}
```

## 5. Discovery SDK APIs

The following APIs are exposed by the Firebolt Discovery SDK as part of the
`Content` module.

### 5.1. Content.requestUserInterest
This method triggers the corresponding Discovery provider API for the
foreground app.

```typescript
Content.requestUserInterest(type: InterestType, reason: InterestReason): Promise<EntityInfo>
```

### 5.2. Content.onUserInterestedIn

This notification allows Aggregated Experience Apps to be informed when
a user expresses interest in some Content, and the content resolves to a
valid Entity from some App.

`Content.listen('userInterest', UserInterestInfo => void): Promise<void>`

The callback will be passed an `UserInterestInfo` object with
the type, reason, and information about the entity that the user expressed interest in.
Loading
Loading