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

498 Allow intents to be resolved on output type (where they return data) #499

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
167a7d4
Merge branch '432-return-data-from-an-intent' into 498-resolve-intent…
kriswest Nov 12, 2021
85619ec
Add suport for metadata on output types for intent to appD and the fi…
kriswest Nov 12, 2021
0adfd83
changelog
kriswest Nov 12, 2021
bd97624
WIP
kriswest Nov 18, 2021
ea69042
WIP
kriswest Nov 18, 2021
22cd3be
Merge branch '432-return-data-from-an-intent' into 498-resolve-intent…
kriswest Nov 18, 2021
6d68022
Changing IntentResolution.getData() to IntentResolution.getResult()
kriswest Nov 18, 2021
bb1e120
Changing IntentResolution.getData() to IntentResolution.getResult()
kriswest Nov 18, 2021
e3a962e
WIP
kriswest Nov 18, 2021
240b424
WIP
kriswest Nov 19, 2021
9b0b3b4
completed draft of feeds
kriswest Nov 19, 2021
075067a
changelog
kriswest Nov 19, 2021
ea3e2eb
outputContext -> resultContext and other comments from review
kriswest Nov 22, 2021
157a46f
Mergeing updates from review of upstream PR
kriswest Nov 22, 2021
4c274a4
Apply suggestions from code review
kriswest Dec 13, 2021
461bf95
Merge branch 'master' into 498-resolve-intents-on-output-type
kriswest Jan 25, 2022
3fa81cb
Merge branch '498-resolve-intents-on-output-type' into 433-private-ch…
kriswest Jan 25, 2022
dbd3e81
Merge branch 'master' into 433-private-channels-returned-by-intents
kriswest Feb 4, 2022
ef1d315
Merge branch 'master' into 433-private-channels-returned-by-intents
kriswest Feb 21, 2022
6412fba
Removing defunct paragraph from docs/api/spec.md (bad merge)
kriswest Feb 21, 2022
1da923a
prettier
kriswest Feb 21, 2022
b88b4af
Update docs/api/ref/DesktopAgent.md
kriswest Feb 15, 2022
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
Prev Previous commit
Next Next commit
Merge branch 'master' into 433-private-channels-returned-by-intents
  • Loading branch information
kriswest authored Feb 4, 2022
commit dbd3e81c4a32093e2c068813c26fa9f5aa4dda8e
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
* Added the ability to return data from an intent, via the addition of an IntentHandler type and a `getResult()` to IntentResolution, both of which return a Promise of a Context object. ([#495](https://github.com/finos/FDC3/pull/495))
* Added a field to specify the Context type that intent can return to the AppD Application schema and extended the findIntent API calls to be able to use it for resolution. ([#499](https://github.com/finos/FDC3/pull/499))
* Added the ability to return a Channel from an intent (via the `IntentResult` type), resolver support for intents that return Channels and the concept of PrivateChannels. ([#508](https://github.com/finos/FDC3/pull/508))
* Added error `UserCancelled` to the `ResolveError` enumeration to be used when user closes the resolver UI or otherwise cancels resolution of a raised intent ([#522 ](https://github.com/finos/FDC3/pull/522))
* Added an `instanceId` (and optional `instanceMetadata`) field to `AppMetadata` allowing it to refer to specific app instances and thereby supporting targetting of intents to specific app instances. Also added a `findInstanes()` function to the desktop agent. ([#509]((https://github.com/finos/FDC3/pull/509))
* Added a References and Bibliography section to the Standard's documentation to hold links to 'normative references' and other documentation that is useful for understanding the standard ([#530](https://github.com/finos/FDC3/pull/530))
* `IntentResolution` now requires the name of the intent raised to included, allowing it to be used to determine the intent raised via `fdc3.raiseIntentForContext()`. ([#507](https://github.com/finos/FDC3/pull/507))
* A Trademarks page was added to acknowledge trademarks used within the Standard not owned by FINOS or the Linux Foundation ([#534](https://github.com/finos/FDC3/pull/534))
Expand Down
68 changes: 38 additions & 30 deletions docs/api/ref/DesktopAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,58 +267,66 @@ const appIntent = await fdc3.findIntent("QuoteStream", instrument, "channel<fdc3
findIntentsByContext(context: Context, resultType?: string): Promise<Array<AppIntent>>;
```

Find all the avalable intents for a particular context, and optionally a desired result context type.
Find all the available intents for a particular context, and optionally a desired result context type.

`findIntentsByContext` is effectively granting programmatic access to the Desktop Agent's resolver.
A promise resolving to all the intents, their metadata and metadata about the apps and app instances that registered as handlers is returned, based on the context types the intents have registered.

If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.
If the resolution fails, the promise will return an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration.

The optional `resultType` argument may be a type name, the string `"channel"` (which indicates that the app will return a channel) or a string indicating a channel that returns a specific type, e.g. `"channel<fdc3,instrument>"`. If intent resolution to an app returning a channel is requested, the desktop agent MUST include both apps that are registered as returning a channel and those registered as returning a channel with a specific type in the response.
The optional `resultType` argument may be a type name, the string `"channel"` (which indicates that the app will return a channel) or a string indicating a channel that returns a specific type, e.g. `"channel<fdc3,instrument>"`. If intent resolution to an app returning a channel is requested, the desktop agent MUST include both apps that are registered as returning a channel and those registered as returning a channel with a specific type in the response.

#### Example
I have a context object, and I want to know what I can do with it, hence, I look for intents and apps to resolve them...
#### Example
I have a context object, and I want to know what I can do with it, hence, I look for intents and apps to resolve them...

```js
const appIntents = await fdc3.findIntentsByContext(context);
```js
const appIntents = await fdc3.findIntentsByContext(context);

// returns, for example:
// [{
// [
// {
// intent: { name: "StartCall", displayName: "Call" },
// apps: [{ name: "Skype" }]
// },
// {
// intent: { name: "StartChat", displayName: "Chat" },
// apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }]
// },
// {
// },
// {
// intent: { name: "StartChat", displayName: "Chat" },
// apps: [
// { name: "Skype" },
// { name: "Symphony" },
// { name: "Symphony", instanceId: "93d2fe3e-a66c-41e1-b80b-246b87120859" },
// { name: "Slack" }
// ]
// },
// {
// intent: { name: "ViewContact", displayName: "View Contact" },
// apps: [{ name: "Symphony" }, { name: "MyCRM", resultType: "fdc3.ContactList"}]
// }];
// }
// ];
```

or I look for only intents that are resolved by apps returning a particular result type

```js
const appIntentsForType = await fdc3.findIntentsByContext(context, "fdc3.ContactList");
// returns for example:
// [{
// intent: { name: "ViewContact", displayName: "View Contacts" },
// apps: [{ name: "MyCRM", resultType: "fdc3.ContactList"}]
// intent: { name: "ViewContact", displayName: "View Contact" },
// apps: [{ name: "Symphony" }, { name: "MyCRM", resultType: "fdc3.ContactList"}]
// }];

// select a particular intent to raise
const resolvedIntent = appIntents[0];
const startChat = appIntents[1];

// target a particular app
const selectedApp = resolvedIntent.apps[0];
// target a particular app or instance
const selectedApp = startChat.apps[2];

// raise the intent, passing the given context, targeting the app
await fdc3.raiseIntent(resolvedIntent.intent.name, context, selectedApp.name);
await fdc3.raiseIntent(startChat.intent.name, context, selectedApp);
```

#### See also
* [`findIntent()`](#findintent)
* [`ResolveError`](Errors#resolveerror)
* [`findIntent()`](#findintent)
* [`ResolveError`](Errors#resolveerror)



Expand Down Expand Up @@ -566,16 +574,17 @@ raiseIntent(intent: string, context: Context, app?: TargetApp): Promise<IntentRe
Raises a specific intent for resolution against apps registered with the desktop agent.

The desktop agent MUST resolve the correct app to target based on the provided intent name and context data. If multiple matching apps are found, a method for resolving the intent to a target app, such as presenting the user with a resolver UI allowing them to pick an app, SHOULD be provided.
Alternatively, the specific app to target can also be provided. A list of valid target applications can be retrieved via [`findIntent`](DesktopAgent#findintent).
Alternatively, the specific app or app instance to target can also be provided. A list of valid target applications and instances can be retrieved via [`findIntent`](DesktopAgent#findintent).

If a target app for the intent cannot be found with the criteria provided, an `Error` with a string from the [`ResolveError`](Errors#resolverror) enumeration is returned.

If you wish to raise an Intent without a context, use the `fdc3.nothing` context type. This type exists so that apps can explicitly declare support for raising an intent without context.
If you wish to raise an intent without a context, use the `fdc3.nothing` context type. This type exists so that apps can explicitly declare support for raising an intent without context.

Returns an [`IntentResolution`](Metadata#intentresolution) object with details of the app that was selected to respond to the intent.
Returns an [`IntentResolution`](Metadata#intentresolution) object with details of the app instance that was selected (or started) to respond to the intent.

Issuing apps may optionally wait on the promise that is returned by the `getResult()` member of the IntentResolution. This promise will resolve when the _receiving app's_ intent handler function returns and resolves a promise. The Desktop Agent resolves the issuing app's promise with the Context object or Channel that is provided as resolution within the receiving app. The Desktop Agent MUST reject the issuing app's promise, with a string from the [`ResultError`](Errors#resulterror) enumeration, if: (1) the intent handling function's returned promise rejects, (2) the intent handling function doesn't return a promise, or (3) the returned promise resolves to an invalid type.
If a target app for the intent cannot be found with the criteria provided or the user either closes the resolver UI or otherwise cancels resolution, an `Error` with a string from the [`ResolveError`](Errors#resolveerror) enumeration is returned. If a specific target `app` parameter was set, but either the app or app instance is not available then the `ResolveError.TargetAppUnavailable` or `ResolveError.TargetInstanceUnavailable` errors MUST be returned.

Issuing apps may optionally wait on the promise that is returned by the `getResult()` member of the IntentResolution. This promise will resolve when the _receiving app's_ intent handler function returns and resolves a promise. The Desktop Agent resolves the issuing app's promise with the Context object or Channel that is provided as resolution within the receiving app. The Desktop Agent MUST reject the issuing app's promise, with a string from the [`ResultError`](Errors#resulterror) enumeration, if: (1) the intent handling function's returned promise rejects, (2) the intent handling function doesn't return a promise, or (3) the returned promise resolves to an invalid type.

#### Example

Expand All @@ -587,9 +596,8 @@ await fdc3.raiseIntent("StartChat", context);

// or find apps to resolve an intent to start a chat with a given contact
const appIntent = await fdc3.findIntent("StartChat", context);
// use the name of one of the associated apps returned by findIntent as the specific intent target
await fdc3.raiseIntent("StartChat", context, appIntent.apps[0].name);
// or use the metadata of the app to fully describe the target app for the intent

// use the metadata of an app or app instance to describe the target app for the intent
await fdc3.raiseIntent("StartChat", context, appIntent.apps[0]);

//Raise an intent without a context by using the null context type
Expand Down
38 changes: 31 additions & 7 deletions docs/api/ref/Metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,34 @@ For each intent, it reference the applications that support that intent.
interface AppMetadata {
/** The unique app name that can be used with the open and raiseIntent calls. */
readonly name: string;

/** The unique application identifier located within a specific application directory instance. An example of an appId might be 'app@sub.root' */
readonly appId?: string;

/** The Version of the application. */
readonly version?: string;

/** An optional instance identifier, indicating that this object represents a specific instance of the application described.*/
readonly instanceId?: string;

/** An optional set of, implementation specific, metadata fields that can be used to disambiguate instances, such as a window title or screen position. Must only be set if `instanceId` is set. */
readonly instanceMetadata?: Record<string, any>;

/** A more user-friendly application title that can be used to render UI elements */
readonly title?: string;

/** A tooltip for the application that can be used to render UI elements */
readonly tooltip?: string;
/** A longer, multi-paragraph description for the application that could include markup */

/** A longer, multi-paragraph description for the application that could include mark-up */
readonly description?: string;

/** A list of icon URLs for the application that can be used to render UI elements */
readonly icons?: Array<Icon>;

/** A list of image URLs for the application that can be used to render UI elements */
readonly images?: Array<string>;

/** The type of result returned for any intent specified during resolution.
* May express a particular context type (e.g. "fdc3.instrument"), channel
* (e.g. "channel") or a channel that will receive a specified type
Expand All @@ -49,15 +63,13 @@ interface AppMetadata {
}
```

App metadata is usually provided by the FDC3 App Directory that the desktop agent connects to.
Describes an application, or instance of an application, using metadata that is usually provided by an FDC3 App Directory that the desktop agent connects to.

Will always includes at least a `name` property, which can be used with [`open`](DesktopAgent#open) and [`raiseIntent`](DesktopAgent#raiseIntent). If the `instanceId` field is set then the `AppMetadata` object represents a specific instance of the application that may be addressed using that Id.

Optionally, extra information from the app directory can be returned, to aid in rendering UI elements, e.g. a context menu. This includes a title, description, tooltip and icon and image URLs.

In situations where a desktop agent connects to multiple app directories or multiple versions of the same app exists in a single app directory, it may be neccessary to specify appId and version to target applications that share the same name.

`AppMetadata`
In situations where a desktop agent connects to multiple app directories or multiple versions of the same app exists in a single app directory, it may be necessary to specify `appId` or `version` to target applications that share the same name.

#### See also
* [`AppIntent.apps`](AppIntent)
Expand Down Expand Up @@ -133,8 +145,10 @@ The interface used to describe an intent within the platform.
```ts
interface IntentResolution {

/**
* The application that resolved the intent.
/**
* Metadata about the app instance that was selected (or started) to resolve the intent.
* `source.instanceId` MUST be set, indicating the specific app instance that
* received the intent.
*/
readonly source: AppMetadata;
/**
Expand Down Expand Up @@ -171,6 +185,16 @@ IntentResolution provides a standard format for data returned upon resolving an
//resolve a "Chain" type intent
let resolution = await agent.raiseIntent("intentName", context);

// Use metadata about the resolving app instance to target a further intent
try {
const resolution = await fdc3.raiseIntent('StageOrder', context);
...

//some time later
await agent.raiseIntent("UpdateOrder", context, resolution.source);
}
catch (err) { ... }

//resolve a "Client-Service" type intent with a data or channel response
let resolution = await agent.raiseIntent("intentName", context);
try {
Expand Down
13 changes: 7 additions & 6 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Intents provide a way for an app to request functionality from another app and d
- **Remote API**: An app wants to remote an entire API that it owns to another App. In this case, the API for the App cannot be standardized. However, the FDC3 API can address how an App connects to another App in order to get access to a proprietary API.

#### Intents and Context
When raising an Intent a specific context may be provided as input. The type of the provided context may determine which applications can resolve the Intent.
When raising an intent a specific context may be provided as input. The type of the provided context may determine which applications can resolve the intent.

A context type may also be associated with multiple intents. For example, an `fdc3.instrument` could be associated with `ViewChart`, `ViewNews`, `ViewAnalysis` or other intents. In addition to raising a specific intent, you can raise an intent for a specific context allowing the Desktop Agent or the user (if the intent is ambiguous) to select the appropriate intent for the selected context and then to raise that intent for resolution.

Expand Down Expand Up @@ -172,7 +172,8 @@ try {
catch (err){ ... }
```

or to raise an unspecified Intent for a specific context, where the user may select an intent from a resolver dialog:
or to raise an unspecified intent for a specific context, where the user will select an intent from a resolver dialog:

```js
try {
const resolution = await fdc3.raiseIntentForContext(context);
Expand Down Expand Up @@ -229,7 +230,7 @@ try {
const result = await resolution.getResult();
console.log(`${resolution.source} returned ${JSON.stringify(result)}`);
} catch(error) {
console.error(`${resolution.source} returned a result error: ${error}`);
console.error(`${resolution.source} returned a result error: ${error}`);
}

//Find apps to resolve an intent and return a channel
Expand All @@ -245,7 +246,7 @@ try {
console.log(`${resolution.source} didn't return a channel! Result: ${JSON.stringify(result)}`);
}
} catch(error) {
console.error(`${resolution.source} returned a result error: ${error}`);
console.error(`${resolution.source} returned a result error: ${error}`);
}

//Find apps that can perform any intent with the specified context
Expand All @@ -268,10 +269,10 @@ const chartApp = fin.Application.wrap(chart.source);
![Upgrading Connection to Remote API](assets/api-3.png)

### Register an Intent Handler
Applications need to let the system know the Intents they can support. Typically, this is done via registration with the App Directory. It is also possible for Intents to be registered at the application level as well to support ad-hoc registration which may be helpful at development time. While, dynamic registration is not part of this specification, a Desktop Agent agent may choose to support any number of registration paths.
Applications need to let the system know the intents they can support. Typically, this is done via registration with an App Directory. It is also possible for intents to be registered at the application level as well to support ad-hoc registration which may be helpful at development time. While, dynamic registration is not part of this specification, a Desktop Agent agent may choose to support any number of registration paths.

#### Compliance with Intent Standards
Intents represent a contract with expected behavior if an app asserts that it supports the intent. Where this contract is enforceable by schema (for example, return object types), the FDC3 API implementation should enforce compliance and return an error if the interface is not met.
Intents represent a contract with expected behaviour if an app asserts that it supports the intent. Where this contract is enforceable by schema (for example, return object types), the FDC3 API implementation should enforce compliance and return an error if the interface is not met.

It is expected that App Directories will also curate listed apps and ensure that they are complying with declared intents.

Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.